Merge "Update lint rules for graphics/text package layering"
diff --git a/Android.bp b/Android.bp
index 39da11f..ca1c614 100644
--- a/Android.bp
+++ b/Android.bp
@@ -25,8 +25,8 @@
 //
 // READ ME: ########################################################
 
-java_library {
-    name: "framework",
+java_defaults {
+    name: "framework-defaults",
     installable: true,
 
     srcs: [
@@ -381,6 +381,7 @@
         "core/java/com/android/internal/backup/IBackupTransport.aidl",
         "core/java/com/android/internal/backup/IObbBackupService.aidl",
         "core/java/com/android/internal/inputmethod/IInputContentUriToken.aidl",
+        "core/java/com/android/internal/inputmethod/IInputMethodPrivilegedOperations.aidl",
         "core/java/com/android/internal/net/INetworkWatchlistManager.aidl",
         "core/java/com/android/internal/policy/IKeyguardDrawnCallback.aidl",
         "core/java/com/android/internal/policy/IKeyguardDismissCallback.aidl",
@@ -554,6 +555,7 @@
         "telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl",
         "telephony/java/com/android/internal/telephony/ISms.aidl",
         "telephony/java/com/android/internal/telephony/ISub.aidl",
+        "telephony/java/com/android/internal/telephony/IAnas.aidl",
         "telephony/java/com/android/internal/telephony/ITelephony.aidl",
         "telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl",
         "telephony/java/com/android/internal/telephony/IWapPushManager.aidl",
@@ -681,6 +683,7 @@
 
     static_libs: [
         "framework-protos",
+        "mediaplayer2-protos",
         "android.hidl.base-V1.0-java",
         "android.hardware.cas-V1.0-java",
         "android.hardware.contexthub-V1.0-java",
@@ -703,12 +706,38 @@
         "libmedia2_jni",
     ],
 
-    javac_shard_size: 150,
-
     dxflags: [
         "--core-library",
         "--multi-dex",
     ],
+
+}
+
+java_library {
+    name: "framework",
+    defaults: ["framework-defaults"],
+    javac_shard_size: 150,
+}
+
+java_library {
+    name: "framework-annotation-proc",
+    defaults: ["framework-defaults"],
+    // Use UsedByApps annotation processor
+    annotation_processors: ["unsupportedappusage-annotation-processor"],
+    // b/25860419: annotation processors must be explicitly specified for grok
+    annotation_processor_classes: [
+        "android.processor.unsupportedappusage.UsedByAppsProcessor",
+    ],
+}
+
+// A host library including just UnsupportedAppUsage.java so that the annotation
+// processor can also use this annotation.
+java_library_host {
+    name: "unsupportedappusage-annotation",
+    srcs: [
+        "core/java/android/annotation/IntDef.java",
+        "core/java/android/annotation/UnsupportedAppUsage.java",
+    ],
 }
 
 // A temporary build target that is conditionally included on the bootclasspath if
@@ -792,9 +821,10 @@
     name: "platformprotos",
     srcs: [
         "cmds/am/proto/instrumentation_data.proto",
+        "cmds/statsd/src/**/*.proto",
         "core/proto/**/*.proto",
         "libs/incident/proto/**/*.proto",
-        "cmds/statsd/src/**/*.proto",
+        "proto/src/stats_enums.proto",
     ],
     proto: {
         include_dirs: ["external/protobuf/src"],
@@ -832,6 +862,7 @@
     srcs: [
         "core/proto/**/*.proto",
         "libs/incident/proto/android/os/**/*.proto",
+        "proto/src/stats_enums.proto",
     ],
     // Protos have lots of MissingOverride and similar.
     errorprone: {
@@ -857,6 +888,7 @@
     srcs: [
         "core/proto/**/*.proto",
         "libs/incident/**/*.proto",
+        "proto/src/stats_enums.proto",
     ],
 
     target: {
@@ -1052,53 +1084,63 @@
      "-federate SupportLib https://developer.android.com " +
      "-federationapi SupportLib $(location current/support-api.txt) "
 
-doc_defaults {
-    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",
-    ],
-    srcs_lib: "framework",
-    srcs_lib_whitelist_dirs: frameworks_base_subdirs,
-    srcs_lib_whitelist_pkgs: packages_to_document,
-    libs: [
-        "core-oj",
-        "core-libart",
-        "conscrypt",
-        "bouncycastle",
-        "okhttp",
-        "ext",
-        "framework",
-        "voip-common",
-        "android.test.mock.impl",
-    ],
-    local_sourcepaths: frameworks_base_subdirs,
-    html_dirs: [
-        "docs/html",
-    ],
-    knowntags: [
-        "docs/knowntags.txt",
-        ":known-oj-tags",
-    ],
-    custom_template: "droiddoc-templates-sdk",
-    hdf: [
-        "dac true",
-        "sdk.codename O",
-        "sdk.preview.version 1",
-        "sdk.version 7.0",
-        "sdk.rel.id 1",
-        "sdk.preview 0",
-    ],
-    resourcesdir: "docs/html/reference/images",
-    resourcesoutdir: "reference/android/images",
-    installable: false,
-}
+framework_docs_only_args = " -android -manifest $(location core/res/AndroidManifest.xml) " +
+     "-overview $(location core/java/overview.html) " +
+     // Federate Support Library references against local API file.
+     "-federate SupportLib https://developer.android.com " +
+     "-federationapi SupportLib $(location current/support-api.txt) "
 
-doc_defaults {
-    name: "framework-docs-default",
+framework_docs_only_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",
+]
+
+metalava_framework_docs_args = "--manifest $(location core/res/AndroidManifest.xml) " +
+    "--hide-package com.android.okhttp " +
+    "--hide-package com.android.org.conscrypt --hide-package com.android.server " +
+    "--hide RequiresPermission " +
+    "--hide MissingPermission --hide BroadcastBehavior " +
+    "--hide HiddenSuperclass --hide DeprecationMismatch --hide UnavailableSymbol " +
+    "--hide SdkConstant --hide HiddenTypeParameter --hide Todo --hide Typo"
+
+stubs_defaults {
+    name: "framework-doc-stubs-default",
     srcs: [
         "test-base/src/**/*.java",
         ":opt-telephony-srcs",
@@ -1112,47 +1154,25 @@
     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",
-    ],
+    libs: framework_docs_only_libs,
     local_sourcepaths: frameworks_base_subdirs,
+    create_doc_stubs: true,
+    annotations_enabled: true,
+    api_levels_annotations_enabled: true,
+    api_levels_annotations_dirs: [
+        "sdk-dir",
+        "api-versions-jars-dir",
+    ],
+    previous_api: ":last-released-public-api",
+    merge_annotations_dirs: [
+        "metalava-manual",
+        "ojluni-annotated-stubs",
+    ],
+}
+
+doc_defaults {
+    name: "framework-docs-default",
+    libs: framework_docs_only_libs,
     html_dirs: [
         "docs/html",
     ],
@@ -1173,23 +1193,13 @@
     ],
     arg_files: [
         "core/res/AndroidManifest.xml",
-        ":api-version-xml",
         "core/java/overview.html",
         ":current-support-api",
-        "api/current.txt",
     ],
     create_stubs: false,
 }
 
-metalava_framework_docs_args = "--manifest $(location core/res/AndroidManifest.xml) " +
-    "--hide-package com.android.okhttp " +
-    "--hide-package com.android.org.conscrypt --hide-package com.android.server " +
-    "--hide RequiresPermission " +
-    "--hide MissingPermission --hide BroadcastBehavior " +
-    "--hide HiddenSuperclass --hide DeprecationMismatch --hide UnavailableSymbol " +
-    "--hide SdkConstant --hide HiddenTypeParameter --hide Todo --hide Typo"
-
-doc_defaults {
+stubs_defaults {
     name: "metalava-api-stubs-default",
     srcs: [
         ":opt-telephony-srcs",
@@ -1214,30 +1224,53 @@
     ],
     local_sourcepaths: frameworks_base_subdirs,
     installable: false,
-    metalava_enabled: true,
-    metalava_annotations_enabled: true,
-    metalava_previous_api: ":last-released-public-api",
-    metalava_merge_annotations_dirs: [
+    annotations_enabled: true,
+    previous_api: ":last-released-public-api",
+    merge_annotations_dirs: [
         "metalava-manual",
         "ojluni-annotated-stubs",
     ],
 }
 
+droidstubs {
+    name: "framework-doc-stubs",
+    defaults: ["framework-doc-stubs-default"],
+    arg_files: [
+        "core/res/AndroidManifest.xml",
+    ],
+    args: metalava_framework_docs_args,
+}
+
+droidstubs {
+    name: "framework-doc-system-stubs",
+    defaults: ["framework-doc-stubs-default"],
+    arg_files: [
+        "core/res/AndroidManifest.xml",
+    ],
+    args: metalava_framework_docs_args + " --show-annotation android.annotation.SystemApi ",
+}
+
 droiddoc {
     name: "doc-comment-check-docs",
     defaults: ["framework-docs-default"],
-    args: framework_docs_args + " -referenceonly -parsecomments",
+    srcs: [
+        ":framework-doc-stubs",
+    ],
+    args: framework_docs_only_args + " -referenceonly -parsecomments",
     installable: false,
 }
 
 droiddoc {
     name: "offline-sdk-docs",
     defaults: ["framework-docs-default"],
+    srcs: [
+        ":framework-doc-stubs",
+    ],
     hdf: [
         "android.whichdoc offline",
     ],
     proofread_file: "offline-sdk-docs-proofrerad.txt",
-    args: framework_docs_args + " -offlinemode -title \"Android SDK\"",
+    args: framework_docs_only_args + " -offlinemode -title \"Android SDK\"",
     write_sdk_values: true,
     static_doc_index_redirect: "docs/docs-preview-index.html",
 }
@@ -1245,11 +1278,14 @@
 droiddoc {
     name: "offline-sdk-referenceonly-docs",
     defaults: ["framework-docs-default"],
+    srcs: [
+        ":framework-doc-stubs",
+    ],
     hdf: [
         "android.whichdoc offline",
     ],
     proofread_file: "offline-sdk-referenceonly-docs-proofrerad.txt",
-    args: framework_docs_args + " -offlinemode -title \"Android SDK\" -referenceonly",
+    args: framework_docs_only_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",
@@ -1258,13 +1294,15 @@
 droiddoc {
     name: "offline-system-sdk-referenceonly-docs",
     defaults: ["framework-docs-default"],
+    srcs: [
+        ":framework-doc-system-stubs",
+    ],
     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",
+    args: framework_docs_only_args  + " -hide 101 -hide 104 -hide 108" +
+        " -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",
@@ -1273,12 +1311,15 @@
 droiddoc {
     name: "online-sdk-docs",
     defaults: ["framework-docs-default"],
+    srcs: [
+        ":framework-doc-stubs",
+    ],
     hdf: [
         "android.whichdoc online",
         "android.hasSamples true",
     ],
     proofread_file: "online-sdk-docs-proofrerad.txt",
-    args: framework_docs_args +
+    args: framework_docs_only_args  +
         " -toroot / -samplegroup Admin " +
         " -samplegroup Background " +
         " -samplegroup Connectivity " +
@@ -1299,14 +1340,16 @@
 droiddoc {
     name: "online-system-api-sdk-docs",
     defaults: ["framework-docs-default"],
+    srcs: [
+        ":framework-doc-system-stubs",
+    ],
     hdf: [
         "android.whichdoc online",
         "android.hasSamples true",
     ],
     proofread_file: "online-system-api-sdk-docs-proofrerad.txt",
-    args: framework_docs_args +
+    args: framework_docs_only_args +
         " -referenceonly " +
-        " -showAnnotation android.annotation.SystemApi " +
         " -title \"Android SDK - Including system APIs.\" " +
         " -hide 101 " +
         " -hide 104 " +
@@ -1332,12 +1375,15 @@
 droiddoc {
     name: "ds-docs",
     defaults: ["framework-docs-default"],
+    srcs: [
+        ":framework-doc-stubs",
+    ],
     hdf: [
         "android.whichdoc online",
         "android.hasSamples true",
     ],
     proofread_file: "ds-docs-proofrerad.txt",
-    args: framework_docs_args +
+    args: framework_docs_only_args +
         " -toroot / -samplegroup Admin " +
         " -samplegroup Background " +
         " -samplegroup Connectivity " +
@@ -1358,11 +1404,14 @@
 droiddoc {
     name: "ds-static-docs",
     defaults: ["framework-docs-default"],
+    srcs: [
+        ":framework-doc-stubs",
+    ],
     hdf: [
         "android.whichdoc online",
     ],
     proofread_file: "ds-static-docs-proofrerad.txt",
-    args: framework_docs_args +
+    args: framework_docs_only_args +
           " -staticonly " +
           " -toroot / " +
           " -devsite " +
@@ -1372,11 +1421,14 @@
 droiddoc {
     name: "ds-ref-navtree-docs",
     defaults: ["framework-docs-default"],
+    srcs: [
+        ":framework-doc-stubs",
+    ],
     hdf: [
         "android.whichdoc online",
     ],
     proofread_file: "ds-ref-navtree-docs-proofrerad.txt",
-    args: framework_docs_args +
+    args: framework_docs_only_args +
           " -toroot / " +
           " -atLinksNavtree " +
           " -navtreeonly ",
@@ -1385,12 +1437,15 @@
 droiddoc {
     name: "online-sdk-dev-docs",
     defaults: ["framework-docs-default"],
+    srcs: [
+        ":framework-doc-stubs",
+    ],
     hdf: [
         "android.whichdoc online",
         "android.hasSamples true",
     ],
     proofread_file: "online-sdk-dev-docs-proofrerad.txt",
-    args: framework_docs_args +
+    args: framework_docs_only_args +
         " -toroot / -samplegroup Admin " +
         " -samplegroup Background " +
         " -samplegroup Connectivity " +
@@ -1411,13 +1466,16 @@
 droiddoc {
     name: "hidden-docs",
     defaults: ["framework-docs-default"],
+    srcs: [
+        ":framework-doc-stubs",
+    ],
     proofread_file: "hidden-docs-proofrerad.txt",
-    args: framework_docs_args +
+    args: framework_docs_only_args +
           " -referenceonly " +
           " -title \"Android SDK - Including hidden APIs.\"",
 }
 
-droiddoc {
+droidstubs {
     name: "hwbinder-stubs-docs",
     srcs: [
         "core/java/android/os/HidlSupport.java",
@@ -1435,10 +1493,15 @@
         "core/java/android/os/RemoteException.java",
         "core/java/android/util/AndroidException.java",
     ],
-    custom_template: "droiddoc-templates-sdk",
     installable: false,
     no_framework_libs: true,
-    args: "-showAnnotation android.annotation.SystemApi -nodocs -stubsourceonly",
+    annotations_enabled: true,
+    previous_api: ":last-released-public-api",
+    merge_annotations_dirs: [
+        "metalava-manual",
+        "ojluni-annotated-stubs",
+    ],
+    args: " --show-annotation android.annotation.SystemApi",
 }
 
 java_library_static {
@@ -1449,7 +1512,7 @@
     ],
 }
 
-droiddoc {
+droidstubs {
     name: "hiddenapi-lists-docs",
     defaults: ["metalava-api-stubs-default"],
     arg_files: [
@@ -1465,23 +1528,17 @@
 }
 
 
-droiddoc {
+droidstubs {
     name: "hiddenapi-mappings",
-    defaults: ["api-stubs-default"],
+    defaults: ["metalava-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",
+    args: metalava_framework_docs_args +
+        " --show-unannotated " +
+        " --show-annotation android.annotation.SystemApi " +
+        " --show-annotation android.annotation.TestApi "
 }
 
 filegroup {
@@ -1508,7 +1565,7 @@
     ],
 }
 
-droiddoc {
+droidstubs {
     name: "api-stubs-docs",
     defaults: ["metalava-api-stubs-default"],
     api_filename: "public_api.txt",
@@ -1530,7 +1587,7 @@
     },
 }
 
-droiddoc {
+droidstubs {
     name: "system-api-stubs-docs",
     defaults: ["metalava-api-stubs-default"],
     api_tag_name: "SYSTEM",
@@ -1554,7 +1611,7 @@
     },
 }
 
-droiddoc {
+droidstubs {
     name: "test-api-stubs-docs",
     defaults: ["metalava-api-stubs-default"],
     api_tag_name: "TEST",
@@ -1571,3 +1628,10 @@
         },
     },
 }
+
+filegroup {
+    name: "framework-annotation-nonnull-srcs",
+    srcs: [
+        "core/java/android/annotation/NonNull.java",
+    ],
+}
diff --git a/Android.mk b/Android.mk
index 988c009..5c4c237 100644
--- a/Android.mk
+++ b/Android.mk
@@ -322,6 +322,11 @@
 	( unzip -qo $< -d $(OUT_DOCS)/offline-sdk && touch -f $@ ) || exit 1
 
 # ==== hiddenapi lists =======================================
+.KATI_RESTAT: \
+	$(INTERNAL_PLATFORM_HIDDENAPI_WHITELIST) \
+	$(INTERNAL_PLATFORM_HIDDENAPI_LIGHT_GREYLIST) \
+	$(INTERNAL_PLATFORM_HIDDENAPI_DARK_GREYLIST) \
+	$(INTERNAL_PLATFORM_HIDDENAPI_BLACKLIST)
 $(INTERNAL_PLATFORM_HIDDENAPI_WHITELIST): \
     .KATI_IMPLICIT_OUTPUTS := \
         $(INTERNAL_PLATFORM_HIDDENAPI_LIGHT_GREYLIST) \
@@ -346,10 +351,14 @@
 	                   $(INTERNAL_PLATFORM_HIDDENAPI_PRIVATE_LIST)) \
 	        $(PRIVATE_GREYLIST_INPUTS) \
 	    --input-blacklists frameworks/base/config/hiddenapi-force-blacklist.txt \
-	    --output-whitelist $(INTERNAL_PLATFORM_HIDDENAPI_WHITELIST) \
-	    --output-light-greylist $(INTERNAL_PLATFORM_HIDDENAPI_LIGHT_GREYLIST) \
-	    --output-dark-greylist $(INTERNAL_PLATFORM_HIDDENAPI_DARK_GREYLIST) \
-	    --output-blacklist $(INTERNAL_PLATFORM_HIDDENAPI_BLACKLIST)
+	    --output-whitelist $(INTERNAL_PLATFORM_HIDDENAPI_WHITELIST).tmp \
+	    --output-light-greylist $(INTERNAL_PLATFORM_HIDDENAPI_LIGHT_GREYLIST).tmp \
+	    --output-dark-greylist $(INTERNAL_PLATFORM_HIDDENAPI_DARK_GREYLIST).tmp \
+	    --output-blacklist $(INTERNAL_PLATFORM_HIDDENAPI_BLACKLIST).tmp
+	$(call commit-change-for-toc,$(INTERNAL_PLATFORM_HIDDENAPI_WHITELIST))
+	$(call commit-change-for-toc,$(INTERNAL_PLATFORM_HIDDENAPI_LIGHT_GREYLIST))
+	$(call commit-change-for-toc,$(INTERNAL_PLATFORM_HIDDENAPI_DARK_GREYLIST))
+	$(call commit-change-for-toc,$(INTERNAL_PLATFORM_HIDDENAPI_BLACKLIST))
 
 # Include subdirectory makefiles
 # ============================================================
diff --git a/apct-tests/perftests/core/src/android/os/BinderCallsStatsPerfTest.java b/apct-tests/perftests/core/src/android/os/BinderCallsStatsPerfTest.java
index 66a2600d..d8d4a6e 100644
--- a/apct-tests/perftests/core/src/android/os/BinderCallsStatsPerfTest.java
+++ b/apct-tests/perftests/core/src/android/os/BinderCallsStatsPerfTest.java
@@ -23,8 +23,7 @@
 
 import com.android.internal.os.BinderCallsStats;
 import com.android.internal.os.BinderInternal.CallSession;
-
-import java.util.Random;
+import com.android.internal.os.CachedDeviceState;
 
 import org.junit.After;
 import org.junit.Before;
@@ -32,8 +31,6 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-import static org.junit.Assert.assertNull;
-
 
 /**
  * Performance tests for {@link BinderCallsStats}
@@ -49,6 +46,8 @@
     @Before
     public void setUp() {
         mBinderCallsStats = new BinderCallsStats(new BinderCallsStats.Injector());
+        CachedDeviceState deviceState = new CachedDeviceState(false, false);
+        mBinderCallsStats.setDeviceState(deviceState.getReadonlyClient());
     }
 
     @After
diff --git a/apct-tests/perftests/core/src/android/os/LooperStatsPerfTest.java b/apct-tests/perftests/core/src/android/os/LooperStatsPerfTest.java
new file mode 100644
index 0000000..0f880b7
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/os/LooperStatsPerfTest.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 android.os;
+
+
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.support.test.filters.LargeTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.android.internal.os.CachedDeviceState;
+import com.android.internal.os.LooperStats;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+
+/**
+ * Performance tests for {@link LooperStats}.
+ */
+@RunWith(AndroidJUnit4.class)
+@LargeTest
+public class LooperStatsPerfTest {
+    private static final int DISTINCT_MESSAGE_COUNT = 1000;
+
+    @Rule
+    public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+    private LooperStats mStats;
+    private CachedDeviceState mDeviceState;
+    private HandlerThread mThread;
+    private Message[] mMessages = new Message[DISTINCT_MESSAGE_COUNT];
+
+    @Before
+    public void setUp() {
+        mStats = new LooperStats(1, DISTINCT_MESSAGE_COUNT - 1);
+        mDeviceState = new CachedDeviceState(false, false);
+        mStats.setDeviceState(mDeviceState.getReadonlyClient());
+        // The tests are all single-threaded. HandlerThread is created to allow creating Handlers.
+        mThread = new HandlerThread("UnusedThread");
+        mThread.start();
+        for (int i = 0; i < DISTINCT_MESSAGE_COUNT; i++) {
+            mMessages[i] = mThread.getThreadHandler().obtainMessage(i);
+        }
+    }
+
+    @After
+    public void tearDown() {
+        mThread.quit();
+    }
+
+    @Test
+    public void timeHundredPercentSampling() {
+        mStats.setSamplingInterval(1);
+        runScenario();
+    }
+
+    @Test
+    public void timeOnePercentSampling() {
+        mStats.setSamplingInterval(100);
+        runScenario();
+    }
+
+    @Test
+    public void timeCollectionDisabled() {
+        // We do not collect data on charger.
+        mDeviceState.setCharging(true);
+        runScenario();
+    }
+
+    private void runScenario() {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            for (int i = 0; i < DISTINCT_MESSAGE_COUNT; i++) {
+                Object token = mStats.messageDispatchStarting();
+                mStats.messageDispatched(token, mMessages[i]);
+            }
+        }
+    }
+}
diff --git a/api/current.txt b/api/current.txt
old mode 100644
new mode 100755
index 7cacc8e..27222e1
--- a/api/current.txt
+++ b/api/current.txt
@@ -934,6 +934,7 @@
     field public static final int minSdkVersion = 16843276; // 0x101020c
     field public static final int minWidth = 16843071; // 0x101013f
     field public static final int minimumHorizontalAngle = 16843901; // 0x101047d
+    field public static final int minimumUiTimeout = 16844174; // 0x101058e
     field public static final int minimumVerticalAngle = 16843902; // 0x101047e
     field public static final int mipMap = 16843725; // 0x10103cd
     field public static final int mirrorForRtl = 16843726; // 0x10103ce
@@ -2826,7 +2827,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
+    field public static final int SHOW_MODE_IGNORE_HARD_KEYBOARD = 2; // 0x2
   }
 
   public static abstract class AccessibilityService.GestureResultCallback {
@@ -2874,10 +2875,12 @@
     method public int getCapabilities();
     method public deprecated java.lang.String getDescription();
     method public java.lang.String getId();
+    method public int getMinimumUiTimeoutMillis();
     method public android.content.pm.ResolveInfo getResolveInfo();
     method public java.lang.String getSettingsActivityName();
     method public java.lang.String loadDescription(android.content.pm.PackageManager);
     method public java.lang.CharSequence loadSummary(android.content.pm.PackageManager);
+    method public void setMinimumUiTimeoutMillis(int);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final int CAPABILITY_CAN_CONTROL_MAGNIFICATION = 16; // 0x10
     field public static final int CAPABILITY_CAN_PERFORM_GESTURES = 32; // 0x20
@@ -4382,6 +4385,7 @@
 
   public final class AutomaticZenRule implements android.os.Parcelable {
     ctor public AutomaticZenRule(java.lang.String, android.content.ComponentName, android.net.Uri, int, boolean);
+    ctor public AutomaticZenRule(java.lang.String, android.content.ComponentName, android.net.Uri, android.service.notification.ZenPolicy, boolean);
     ctor public AutomaticZenRule(android.os.Parcel);
     method public int describeContents();
     method public android.net.Uri getConditionId();
@@ -4389,11 +4393,13 @@
     method public int getInterruptionFilter();
     method public java.lang.String getName();
     method public android.content.ComponentName getOwner();
+    method public android.service.notification.ZenPolicy getZenPolicy();
     method public boolean isEnabled();
     method public void setConditionId(android.net.Uri);
     method public void setEnabled(boolean);
     method public void setInterruptionFilter(int);
     method public void setName(java.lang.String);
+    method public void setZenPolicy(android.service.notification.ZenPolicy);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.app.AutomaticZenRule> CREATOR;
   }
@@ -5680,6 +5686,7 @@
   public class NotificationManager {
     method public java.lang.String addAutomaticZenRule(android.app.AutomaticZenRule);
     method public boolean areNotificationsEnabled();
+    method public boolean canNotifyAsPackage(java.lang.String);
     method public void cancel(int);
     method public void cancel(java.lang.String, int);
     method public void cancelAll();
@@ -5698,13 +5705,17 @@
     method public android.app.NotificationChannelGroup getNotificationChannelGroup(java.lang.String);
     method public java.util.List<android.app.NotificationChannelGroup> getNotificationChannelGroups();
     method public java.util.List<android.app.NotificationChannel> getNotificationChannels();
+    method public java.lang.String getNotificationDelegate();
     method public android.app.NotificationManager.Policy getNotificationPolicy();
     method public boolean isNotificationListenerAccessGranted(android.content.ComponentName);
     method public boolean isNotificationPolicyAccessGranted();
     method public void notify(int, android.app.Notification);
     method public void notify(java.lang.String, int, android.app.Notification);
+    method public void notifyAsPackage(java.lang.String, java.lang.String, int, android.app.Notification);
     method public boolean removeAutomaticZenRule(java.lang.String);
+    method public void revokeNotificationDelegate();
     method public final void setInterruptionFilter(int);
+    method public void setNotificationDelegate(java.lang.String);
     method public void setNotificationPolicy(android.app.NotificationManager.Policy);
     method public boolean updateAutomaticZenRule(java.lang.String, android.app.AutomaticZenRule);
     field public static final java.lang.String ACTION_APP_BLOCK_STATE_CHANGED = "android.app.action.APP_BLOCK_STATE_CHANGED";
@@ -9332,6 +9343,7 @@
     ctor public ContentUris();
     method public static android.net.Uri.Builder appendId(android.net.Uri.Builder, long);
     method public static long parseId(android.net.Uri);
+    method public static android.net.Uri removeId(android.net.Uri);
     method public static android.net.Uri withAppendedId(android.net.Uri, long);
   }
 
@@ -11313,6 +11325,7 @@
     field public static final java.lang.String FEATURE_DEVICE_ADMIN = "android.software.device_admin";
     field public static final java.lang.String FEATURE_EMBEDDED = "android.hardware.type.embedded";
     field public static final java.lang.String FEATURE_ETHERNET = "android.hardware.ethernet";
+    field public static final java.lang.String FEATURE_FACE = "android.hardware.face";
     field public static final java.lang.String FEATURE_FAKETOUCH = "android.hardware.faketouch";
     field public static final java.lang.String FEATURE_FAKETOUCH_MULTITOUCH_DISTINCT = "android.hardware.faketouch.multitouch.distinct";
     field public static final java.lang.String FEATURE_FAKETOUCH_MULTITOUCH_JAZZHAND = "android.hardware.faketouch.multitouch.jazzhand";
@@ -11322,6 +11335,7 @@
     field public static final java.lang.String FEATURE_HIFI_SENSORS = "android.hardware.sensor.hifi_sensors";
     field public static final java.lang.String FEATURE_HOME_SCREEN = "android.software.home_screen";
     field public static final java.lang.String FEATURE_INPUT_METHODS = "android.software.input_methods";
+    field public static final java.lang.String FEATURE_IRIS = "android.hardware.iris";
     field public static final java.lang.String FEATURE_LEANBACK = "android.software.leanback";
     field public static final java.lang.String FEATURE_LEANBACK_ONLY = "android.software.leanback_only";
     field public static final java.lang.String FEATURE_LIVE_TV = "android.software.live_tv";
@@ -11918,6 +11932,7 @@
     method public android.graphics.drawable.Drawable getDrawable(int, android.content.res.Resources.Theme) throws android.content.res.Resources.NotFoundException;
     method public deprecated android.graphics.drawable.Drawable getDrawableForDensity(int, int) throws android.content.res.Resources.NotFoundException;
     method public android.graphics.drawable.Drawable getDrawableForDensity(int, int, android.content.res.Resources.Theme);
+    method public float getFloat(int);
     method public android.graphics.Typeface getFont(int) throws android.content.res.Resources.NotFoundException;
     method public float getFraction(int, int, int);
     method public int getIdentifier(java.lang.String, java.lang.String, java.lang.String);
@@ -12645,7 +12660,7 @@
     ctor public SQLiteMisuseException(java.lang.String);
   }
 
-  public abstract class SQLiteOpenHelper {
+  public abstract class SQLiteOpenHelper implements java.lang.AutoCloseable {
     ctor public SQLiteOpenHelper(android.content.Context, java.lang.String, android.database.sqlite.SQLiteDatabase.CursorFactory, int);
     ctor public SQLiteOpenHelper(android.content.Context, java.lang.String, android.database.sqlite.SQLiteDatabase.CursorFactory, int, android.database.DatabaseErrorHandler);
     ctor public SQLiteOpenHelper(android.content.Context, java.lang.String, int, android.database.sqlite.SQLiteDatabase.OpenParams);
@@ -13784,7 +13799,7 @@
     field public static final int YV12 = 842094169; // 0x32315659
   }
 
-  public class Insets {
+  public final class Insets {
     method public static android.graphics.Insets of(int, int, int, int);
     method public static android.graphics.Insets of(android.graphics.Rect);
     field public static final android.graphics.Insets NONE;
@@ -13976,6 +13991,7 @@
     method public float getFontSpacing();
     method public java.lang.String getFontVariationSettings();
     method public int getHinting();
+    method public int getHyphenEdit();
     method public float getLetterSpacing();
     method public android.graphics.MaskFilter getMaskFilter();
     method public int getOffsetForAdvance(char[], int, int, int, int, boolean, float);
@@ -13984,6 +14000,8 @@
     method public float getRunAdvance(char[], int, int, int, int, boolean, int);
     method public float getRunAdvance(java.lang.CharSequence, int, int, int, int, boolean, int);
     method public android.graphics.Shader getShader();
+    method public float getStrikeThruPosition();
+    method public float getStrikeThruThickness();
     method public android.graphics.Paint.Cap getStrokeCap();
     method public android.graphics.Paint.Join getStrokeJoin();
     method public float getStrokeMiter();
@@ -14004,6 +14022,9 @@
     method public int getTextWidths(java.lang.String, int, int, float[]);
     method public int getTextWidths(java.lang.String, float[]);
     method public android.graphics.Typeface getTypeface();
+    method public float getUnderlinePosition();
+    method public float getUnderlineThickness();
+    method public float getWordSpacing();
     method public android.graphics.Xfermode getXfermode();
     method public boolean hasGlyph(java.lang.String);
     method public final boolean isAntiAlias();
@@ -14034,6 +14055,7 @@
     method public void setFontFeatureSettings(java.lang.String);
     method public boolean setFontVariationSettings(java.lang.String);
     method public void setHinting(int);
+    method public void setHyphenEdit(int);
     method public void setLetterSpacing(float);
     method public void setLinearText(boolean);
     method public android.graphics.MaskFilter setMaskFilter(android.graphics.MaskFilter);
@@ -14055,6 +14077,7 @@
     method public void setTextSkewX(float);
     method public android.graphics.Typeface setTypeface(android.graphics.Typeface);
     method public void setUnderlineText(boolean);
+    method public void setWordSpacing(float);
     method public android.graphics.Xfermode setXfermode(android.graphics.Xfermode);
     field public static final int ANTI_ALIAS_FLAG = 1; // 0x1
     field public static final int DEV_KERN_TEXT_FLAG = 256; // 0x100
@@ -14571,6 +14594,14 @@
     method public android.graphics.Typeface.Builder setWeight(int);
   }
 
+  public static class Typeface.CustomFallbackBuilder {
+    ctor public Typeface.CustomFallbackBuilder(android.graphics.fonts.FontFamily);
+    method public android.graphics.Typeface build();
+    method public android.graphics.Typeface.CustomFallbackBuilder setFallback(java.lang.String);
+    method public android.graphics.Typeface.CustomFallbackBuilder setItalic(boolean);
+    method public android.graphics.Typeface.CustomFallbackBuilder setWeight(int);
+  }
+
   public class Xfermode {
     ctor public Xfermode();
   }
@@ -15135,9 +15166,9 @@
   public class StateListDrawable extends android.graphics.drawable.DrawableContainer {
     ctor public StateListDrawable();
     method public void addState(int[], android.graphics.drawable.Drawable);
+    method public int findStateDrawableIndex(int[]);
     method public int getStateCount();
     method public android.graphics.drawable.Drawable getStateDrawable(int);
-    method public int getStateDrawableIndex(int[]);
     method public int[] getStateSet(int);
   }
 
@@ -15210,6 +15241,9 @@
 
   public final class Font {
     method public android.graphics.fonts.FontVariationAxis[] getAxes();
+    method public java.nio.ByteBuffer getBuffer();
+    method public java.io.File getFile();
+    method public android.os.LocaleList getLocaleList();
     method public int getTtcIndex();
     method public int getWeight();
     method public boolean isItalic();
@@ -15218,7 +15252,9 @@
     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_MAX = 1000; // 0x3e8
     field public static final int FONT_WEIGHT_MEDIUM = 500; // 0x1f4
+    field public static final int FONT_WEIGHT_MIN = 1; // 0x1
     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
@@ -15258,6 +15294,10 @@
     method public static java.lang.String toFontVariationSettings(android.graphics.fonts.FontVariationAxis[]);
   }
 
+  public class SystemFonts {
+    method public static java.util.Set<android.graphics.fonts.Font> getAvailableFonts();
+  }
+
 }
 
 package android.graphics.pdf {
@@ -15998,6 +16038,7 @@
     method public java.util.List<android.hardware.camera2.CaptureRequest.Key<?>> getAvailablePhysicalCameraRequestKeys();
     method public java.util.List<android.hardware.camera2.CaptureRequest.Key<?>> getAvailableSessionKeys();
     method public java.util.List<android.hardware.camera2.CameraCharacteristics.Key<?>> getKeys();
+    method public java.util.List<android.hardware.camera2.CameraCharacteristics.Key<?>> getKeysNeedingPermission();
     method public java.util.Set<java.lang.String> getPhysicalCameraIds();
     field public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES;
     field public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> CONTROL_AE_AVAILABLE_ANTIBANDING_MODES;
@@ -36553,9 +36594,9 @@
     field public static final java.lang.String IS_PRIVATE = "isprivate";
     field public static final java.lang.String LATITUDE = "latitude";
     field public static final java.lang.String LONGITUDE = "longitude";
-    field public static final java.lang.String MINI_THUMB_MAGIC = "mini_thumb_magic";
+    field public static final deprecated java.lang.String MINI_THUMB_MAGIC = "mini_thumb_magic";
     field public static final java.lang.String ORIENTATION = "orientation";
-    field public static final java.lang.String PICASA_ID = "picasa_id";
+    field public static final deprecated java.lang.String PICASA_ID = "picasa_id";
   }
 
   public static final class MediaStore.Images.Media implements android.provider.MediaStore.Images.ImageColumns {
@@ -36658,7 +36699,7 @@
     field public static final java.lang.String LANGUAGE = "language";
     field public static final java.lang.String LATITUDE = "latitude";
     field public static final java.lang.String LONGITUDE = "longitude";
-    field public static final java.lang.String MINI_THUMB_MAGIC = "mini_thumb_magic";
+    field public static final deprecated java.lang.String MINI_THUMB_MAGIC = "mini_thumb_magic";
     field public static final java.lang.String RESOLUTION = "resolution";
     field public static final java.lang.String TAGS = "tags";
   }
@@ -39530,6 +39571,7 @@
     method public final deprecated void cancelNotification(java.lang.String, java.lang.String, int);
     method public final void cancelNotification(java.lang.String);
     method public final void cancelNotifications(java.lang.String[]);
+    method public final void clearRequestedListenerHints();
     method public android.service.notification.StatusBarNotification[] getActiveNotifications();
     method public android.service.notification.StatusBarNotification[] getActiveNotifications(java.lang.String[]);
     method public final int getCurrentInterruptionFilter();
@@ -39629,10 +39671,12 @@
     method public int getId();
     method public java.lang.String getKey();
     method public android.app.Notification getNotification();
+    method public java.lang.String getOpPkg();
     method public java.lang.String getOverrideGroupKey();
     method public java.lang.String getPackageName();
     method public long getPostTime();
     method public java.lang.String getTag();
+    method public int getUid();
     method public android.os.UserHandle getUser();
     method public deprecated int getUserId();
     method public boolean isClearable();
@@ -39643,6 +39687,61 @@
     field public static final android.os.Parcelable.Creator<android.service.notification.StatusBarNotification> CREATOR;
   }
 
+  public final class ZenPolicy implements android.os.Parcelable {
+    method public int describeContents();
+    method public int getPriorityCallSenders();
+    method public int getPriorityCategoryAlarms();
+    method public int getPriorityCategoryCalls();
+    method public int getPriorityCategoryEvents();
+    method public int getPriorityCategoryMedia();
+    method public int getPriorityCategoryMessages();
+    method public int getPriorityCategoryReminders();
+    method public int getPriorityCategoryRepeatCallers();
+    method public int getPriorityCategorySystem();
+    method public int getPriorityMessageSenders();
+    method public int getVisualEffectAmbient();
+    method public int getVisualEffectBadge();
+    method public int getVisualEffectFullScreenIntent();
+    method public int getVisualEffectLights();
+    method public int getVisualEffectNotificationList();
+    method public int getVisualEffectPeek();
+    method public int getVisualEffectStatusBar();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.service.notification.ZenPolicy> CREATOR;
+    field public static final int PEOPLE_TYPE_ANYONE = 1; // 0x1
+    field public static final int PEOPLE_TYPE_CONTACTS = 2; // 0x2
+    field public static final int PEOPLE_TYPE_NONE = 4; // 0x4
+    field public static final int PEOPLE_TYPE_STARRED = 3; // 0x3
+    field public static final int PEOPLE_TYPE_UNSET = 0; // 0x0
+    field public static final int STATE_ALLOW = 1; // 0x1
+    field public static final int STATE_DISALLOW = 2; // 0x2
+    field public static final int STATE_UNSET = 0; // 0x0
+  }
+
+  public static class ZenPolicy.Builder {
+    ctor public ZenPolicy.Builder();
+    method public android.service.notification.ZenPolicy.Builder allowAlarms(boolean);
+    method public android.service.notification.ZenPolicy.Builder allowAllSounds();
+    method public android.service.notification.ZenPolicy.Builder allowCalls(int);
+    method public android.service.notification.ZenPolicy.Builder allowEvents(boolean);
+    method public android.service.notification.ZenPolicy.Builder allowMedia(boolean);
+    method public android.service.notification.ZenPolicy.Builder allowMessages(int);
+    method public android.service.notification.ZenPolicy.Builder allowReminders(boolean);
+    method public android.service.notification.ZenPolicy.Builder allowRepeatCallers(boolean);
+    method public android.service.notification.ZenPolicy.Builder allowSystem(boolean);
+    method public android.service.notification.ZenPolicy build();
+    method public android.service.notification.ZenPolicy.Builder disallowAllSounds();
+    method public android.service.notification.ZenPolicy.Builder hideAllVisualEffects();
+    method public android.service.notification.ZenPolicy.Builder showAllVisualEffects();
+    method public android.service.notification.ZenPolicy.Builder showBadges(boolean);
+    method public android.service.notification.ZenPolicy.Builder showFullScreenIntent(boolean);
+    method public android.service.notification.ZenPolicy.Builder showInAmbientDisplay(boolean);
+    method public android.service.notification.ZenPolicy.Builder showInNotificationList(boolean);
+    method public android.service.notification.ZenPolicy.Builder showLights(boolean);
+    method public android.service.notification.ZenPolicy.Builder showPeeking(boolean);
+    method public android.service.notification.ZenPolicy.Builder showStatusBarIcons(boolean);
+  }
+
 }
 
 package android.service.quicksettings {
@@ -41867,6 +41966,9 @@
     field public static final java.lang.String KEY_ALWAYS_SHOW_EMERGENCY_ALERT_ONOFF_BOOL = "always_show_emergency_alert_onoff_bool";
     field public static final java.lang.String KEY_APN_EXPAND_BOOL = "apn_expand_bool";
     field public static final java.lang.String KEY_AUTO_RETRY_ENABLED_BOOL = "auto_retry_enabled_bool";
+    field public static final java.lang.String KEY_CALL_BARRING_SUPPORTS_DEACTIVATE_ALL_BOOL = "call_barring_supports_deactivate_all_bool";
+    field public static final java.lang.String KEY_CALL_BARRING_SUPPORTS_PASSWORD_CHANGE_BOOL = "call_barring_supports_password_change_bool";
+    field public static final java.lang.String KEY_CALL_BARRING_VISIBILITY_BOOL = "call_barring_visibility_bool";
     field public static final java.lang.String KEY_CALL_FORWARDING_BLOCKS_WHILE_ROAMING_STRING_ARRAY = "call_forwarding_blocks_while_roaming_string_array";
     field public static final java.lang.String KEY_CARRIER_ALLOW_TURNOFF_IMS_BOOL = "carrier_allow_turnoff_ims_bool";
     field public static final java.lang.String KEY_CARRIER_DATA_CALL_PERMANENT_FAILURE_STRINGS = "carrier_data_call_permanent_failure_strings";
@@ -42599,6 +42701,7 @@
   }
 
   public class SubscriptionManager {
+    method public void addOnOpportunisticSubscriptionsChangedListener(java.util.concurrent.Executor, android.telephony.SubscriptionManager.OnOpportunisticSubscriptionsChangedListener);
     method public void addOnSubscriptionsChangedListener(android.telephony.SubscriptionManager.OnSubscriptionsChangedListener);
     method public boolean canManageSubscription(android.telephony.SubscriptionInfo);
     method public static deprecated android.telephony.SubscriptionManager from(android.content.Context);
@@ -42612,8 +42715,12 @@
     method public static int getDefaultSmsSubscriptionId();
     method public static int getDefaultSubscriptionId();
     method public static int getDefaultVoiceSubscriptionId();
+    method public java.util.List<android.telephony.SubscriptionInfo> getOpportunisticSubscriptions(int);
+    method public static int[] getSubscriptionIds(int);
     method public java.util.List<android.telephony.SubscriptionPlan> getSubscriptionPlans(int);
     method public boolean isNetworkRoaming(int);
+    method public static boolean isValidSubscriptionId(int);
+    method public void removeOnOpportunisticSubscriptionsChangedListener(android.telephony.SubscriptionManager.OnOpportunisticSubscriptionsChangedListener);
     method public void removeOnSubscriptionsChangedListener(android.telephony.SubscriptionManager.OnSubscriptionsChangedListener);
     method public void setSubscriptionOverrideCongested(int, boolean, long);
     method public void setSubscriptionOverrideUnmetered(int, boolean, long);
@@ -42629,6 +42736,11 @@
     field public static final int INVALID_SUBSCRIPTION_ID = -1; // 0xffffffff
   }
 
+  public static class SubscriptionManager.OnOpportunisticSubscriptionsChangedListener {
+    ctor public SubscriptionManager.OnOpportunisticSubscriptionsChangedListener();
+    method public void onOpportunisticSubscriptionsChanged();
+  }
+
   public static class SubscriptionManager.OnSubscriptionsChangedListener {
     ctor public SubscriptionManager.OnSubscriptionsChangedListener();
     method public void onSubscriptionsChanged();
@@ -43462,6 +43574,22 @@
     method public abstract void handleTag(boolean, java.lang.String, android.text.Editable, org.xml.sax.XMLReader);
   }
 
+  public class Hyphenator {
+    method public static int packHyphenEdit(int, int);
+    method public static int unpackEndHyphenEdit(int);
+    method public static int unpackStartHyphenEdit(int);
+    field public static final int END_HYPHEN_EDIT_INSERT_ARMENIAN_HYPHEN = 3; // 0x3
+    field public static final int END_HYPHEN_EDIT_INSERT_HYPHEN = 2; // 0x2
+    field public static final int END_HYPHEN_EDIT_INSERT_MAQAF = 4; // 0x4
+    field public static final int END_HYPHEN_EDIT_INSERT_UCAS_HYPHEN = 5; // 0x5
+    field public static final int END_HYPHEN_EDIT_INSERT_ZWJ_AND_HYPHEN = 6; // 0x6
+    field public static final int END_HYPHEN_EDIT_NO_EDIT = 0; // 0x0
+    field public static final int END_HYPHEN_EDIT_REPLACE_WITH_HYPHEN = 1; // 0x1
+    field public static final int START_HYPHEN_EDIT_INSERT_HYPHEN = 1; // 0x1
+    field public static final int START_HYPHEN_EDIT_INSERT_ZWJ = 2; // 0x2
+    field public static final int START_HYPHEN_EDIT_NO_EDIT = 0; // 0x0
+  }
+
   public abstract interface InputFilter {
     method public abstract java.lang.CharSequence filter(java.lang.CharSequence, int, int, android.text.Spanned, int, int);
   }
@@ -44486,6 +44614,11 @@
     method public abstract void chooseHeight(java.lang.CharSequence, int, int, int, int, android.graphics.Paint.FontMetricsInt);
   }
 
+  public static class LineHeightSpan.Standard implements android.text.style.LineHeightSpan {
+    ctor public LineHeightSpan.Standard(int);
+    method public void chooseHeight(java.lang.CharSequence, int, int, int, int, android.graphics.Paint.FontMetricsInt);
+  }
+
   public static abstract interface LineHeightSpan.WithDensity implements android.text.style.LineHeightSpan {
     method public abstract void chooseHeight(java.lang.CharSequence, int, int, int, int, android.graphics.Paint.FontMetricsInt, android.text.TextPaint);
   }
@@ -45429,6 +45562,7 @@
     field public static final int DENSITY_420 = 420; // 0x1a4
     field public static final int DENSITY_440 = 440; // 0x1b8
     field public static final int DENSITY_560 = 560; // 0x230
+    field public static final int DENSITY_600 = 600; // 0x258
     field public static final int DENSITY_DEFAULT = 160; // 0xa0
     field public static final int DENSITY_DEVICE_STABLE;
     field public static final int DENSITY_HIGH = 240; // 0xf0
@@ -45975,6 +46109,7 @@
     method public float getDimension(android.util.DisplayMetrics);
     method public final float getFloat();
     method public float getFraction(float, float);
+    method public boolean isColorType();
     method public void setTo(android.util.TypedValue);
     field public static final int COMPLEX_MANTISSA_MASK = 16777215; // 0xffffff
     field public static final int COMPLEX_MANTISSA_SHIFT = 8; // 0x8
@@ -49477,6 +49612,7 @@
     method public deprecated java.util.List<android.content.pm.ServiceInfo> getAccessibilityServiceList();
     method public java.util.List<android.accessibilityservice.AccessibilityServiceInfo> getEnabledAccessibilityServiceList(int);
     method public java.util.List<android.accessibilityservice.AccessibilityServiceInfo> getInstalledAccessibilityServiceList();
+    method public int getMinimumUiTimeoutMillis();
     method public void interrupt();
     method public static boolean isAccessibilityButtonSupported();
     method public boolean isEnabled();
@@ -53032,6 +53168,7 @@
     method public int getSourceWidth();
     method public int getWidth();
     method public float getZoom();
+    method public void setZoom(float);
     method public void show(float, float);
     method public void show(float, float, float, float);
     method public void update();
diff --git a/api/system-current.txt b/api/system-current.txt
index 1d5f586..d29b216 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -355,6 +355,11 @@
     field public static final android.os.Parcelable.Creator<android.app.AppOpsManager.PackageOps> CREATOR;
   }
 
+  public final class AutomaticZenRule implements android.os.Parcelable {
+    ctor public AutomaticZenRule(java.lang.String, android.content.ComponentName, android.net.Uri, int, boolean, long);
+    ctor public AutomaticZenRule(java.lang.String, android.content.ComponentName, android.net.Uri, int, boolean, long, android.service.notification.ZenPolicy);
+  }
+
   public class BroadcastOptions {
     method public static android.app.BroadcastOptions makeBasic();
     method public void setDontSendToRestrictedApps(boolean);
@@ -474,9 +479,6 @@
     method public android.app.Vr2dDisplayProperties.Builder setEnabled(boolean);
   }
 
-  public static abstract class Vr2dDisplayProperties.Vr2dDisplayFlag implements java.lang.annotation.Annotation {
-  }
-
   public class VrManager {
     method public int getVr2dDisplayId();
     method public boolean isPersistentVrModeEnabled();
@@ -1118,6 +1120,7 @@
 
   public abstract class PackageManager {
     method public abstract void addOnPermissionsChangeListener(android.content.pm.PackageManager.OnPermissionsChangedListener);
+    method public abstract boolean arePermissionsIndividuallyControlled();
     method public abstract java.util.List<android.content.IntentFilter> getAllIntentFilters(java.lang.String);
     method public android.content.pm.dex.ArtManager getArtManager();
     method public abstract java.lang.String getDefaultBrowserPackageNameAsUser(int);
@@ -1269,6 +1272,14 @@
 
 }
 
+package android.graphics.drawable {
+
+  public final class Icon implements android.os.Parcelable {
+    method public static android.graphics.drawable.Icon createWithResource(android.content.res.Resources, int);
+  }
+
+}
+
 package android.hardware {
 
   public final class Sensor {
@@ -2618,6 +2629,7 @@
     method public deprecated boolean addGpsNavigationMessageListener(android.location.GpsNavigationMessageEvent.Listener);
     method public void flushGnssBatch();
     method public int getGnssBatchSize();
+    method public java.lang.String getNetworkProviderPackage();
     method public boolean isLocationEnabledForUser(android.os.UserHandle);
     method public boolean isProviderEnabledForUser(java.lang.String, android.os.UserHandle);
     method public boolean registerGnssBatchedLocationCallback(long, boolean, android.location.BatchedLocationCallback, android.os.Handler);
@@ -3800,6 +3812,14 @@
     field public static final java.lang.String ACTION_UPDATE_SMS_SHORT_CODES = "android.intent.action.UPDATE_SMS_SHORT_CODES";
   }
 
+  public class Environment {
+    method public static java.io.File getOdmDirectory();
+    method public static java.io.File getOemDirectory();
+    method public static java.io.File getProductDirectory();
+    method public static java.io.File getProductServicesDirectory();
+    method public static java.io.File getVendorDirectory();
+  }
+
   public class HidlSupport {
     method public static boolean deepEquals(java.lang.Object, java.lang.Object);
     method public static int deepHashCode(java.lang.Object);
@@ -4100,6 +4120,9 @@
     method public boolean isSystem();
     method public static int myUserId();
     method public static android.os.UserHandle of(int);
+    field public static final android.os.UserHandle ALL;
+    field public static final android.os.UserHandle CURRENT;
+    field public static final android.os.UserHandle SYSTEM;
     field public static final int USER_NULL = -10000; // 0xffffd8f0
   }
 
@@ -6778,7 +6801,6 @@
     method public static android.content.pm.PackageInfo getLoadedPackageInfo();
     method public static int loadWebViewNativeLibraryFromPackage(java.lang.String, java.lang.ClassLoader);
     method public static void prepareWebViewInZygote();
-    field public static final java.lang.String CHROMIUM_WEBVIEW_VMSIZE_SIZE_PROPERTY = "persist.sys.webview.vmsize";
     field public static final int LIBLOAD_ADDRESS_SPACE_NOT_RESERVED = 2; // 0x2
     field public static final int LIBLOAD_FAILED_JNI_CALL = 7; // 0x7
     field public static final int LIBLOAD_FAILED_LISTING_WEBVIEW_PACKAGES = 4; // 0x4
diff --git a/api/test-current.txt b/api/test-current.txt
index 40aa440..e22f516 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -259,6 +259,7 @@
   }
 
   public abstract class Context {
+    method public android.content.Context createPackageContextAsUser(java.lang.String, int, android.os.UserHandle) throws android.content.pm.PackageManager.NameNotFoundException;
     method public abstract java.lang.String getOpPackageName();
     method public android.os.UserHandle getUser();
     method public int getUserId();
@@ -765,6 +766,8 @@
     method public static int getAppId(int);
     method public int getIdentifier();
     method public static boolean isApp(int);
+    field public static final android.os.UserHandle ALL;
+    field public static final android.os.UserHandle CURRENT;
     field public static final android.os.UserHandle SYSTEM;
   }
 
@@ -1336,30 +1339,47 @@
     method public void writeRawZigZag64(long);
   }
 
-  public final class ProtoOutputStream {
+  public final class ProtoInputStream extends android.util.proto.ProtoStream {
+    ctor public ProtoInputStream(java.io.InputStream, int);
+    ctor public ProtoInputStream(java.io.InputStream);
+    ctor public ProtoInputStream(byte[]);
+    method public int decodeZigZag32(int);
+    method public long decodeZigZag64(long);
+    method public java.lang.String dumpDebugData();
+    method public void end(long);
+    method public int getFieldNumber();
+    method public int getOffset();
+    method public int getWireType();
+    method public boolean isNextField(long) throws java.io.IOException;
+    method public int nextField() throws java.io.IOException;
+    method public boolean readBoolean(long) throws java.io.IOException;
+    method public byte[] readBytes(long) throws java.io.IOException;
+    method public double readDouble(long) throws java.io.IOException;
+    method public float readFloat(long) throws java.io.IOException;
+    method public int readInt(long) throws java.io.IOException;
+    method public long readLong(long) throws java.io.IOException;
+    method public java.lang.String readString(long) throws java.io.IOException;
+    method public void skip() throws java.io.IOException;
+    method public long start(long) throws java.io.IOException;
+    field public static final int NO_MORE_FIELDS = -1; // 0xffffffff
+  }
+
+  public final class ProtoOutputStream extends android.util.proto.ProtoStream {
     ctor public ProtoOutputStream();
     ctor public ProtoOutputStream(int);
     ctor public ProtoOutputStream(java.io.OutputStream);
     ctor public ProtoOutputStream(java.io.FileDescriptor);
     method public static int checkFieldId(long, long);
-    method public static int convertObjectIdToOrdinal(int);
     method public void dump(java.lang.String);
     method public void end(long);
     method public deprecated void endObject(long);
     method public deprecated void endRepeatedObject(long);
     method public void flush();
     method public byte[] getBytes();
-    method public static int getDepthFromToken(long);
-    method public static int getObjectIdFromToken(long);
-    method public static boolean getRepeatedFromToken(long);
-    method public static int getSizePosFromToken(long);
-    method public static int getTagSizeFromToken(long);
     method public static long makeFieldId(int, long);
-    method public static long makeToken(int, boolean, int, int, int);
     method public long start(long);
     method public deprecated long startObject(long);
     method public deprecated long startRepeatedObject(long);
-    method public static java.lang.String token2String(long);
     method public void write(long, double);
     method public void write(long, float);
     method public void write(long, int);
@@ -1416,6 +1436,27 @@
     method public void writeTag(int, int);
     method public deprecated void writeUInt32(long, int);
     method public deprecated void writeUInt64(long, long);
+  }
+
+  public class ProtoParseException extends java.lang.RuntimeException {
+    ctor public ProtoParseException(java.lang.String);
+  }
+
+  public abstract class ProtoStream {
+    ctor public ProtoStream();
+    method public static int convertObjectIdToOrdinal(int);
+    method public static int getDepthFromToken(long);
+    method public static java.lang.String getFieldCountString(long);
+    method public static java.lang.String getFieldIdString(long);
+    method public static java.lang.String getFieldTypeString(long);
+    method public static int getObjectIdFromToken(long);
+    method public static int getOffsetFromToken(long);
+    method public static boolean getRepeatedFromToken(long);
+    method public static int getTagSizeFromToken(long);
+    method public static java.lang.String getWireTypeString(int);
+    method public static long makeFieldId(int, long);
+    method public static long makeToken(int, boolean, int, int, int);
+    method public static java.lang.String token2String(long);
     field public static final long FIELD_COUNT_MASK = 16492674416640L; // 0xf0000000000L
     field public static final long FIELD_COUNT_PACKED = 5497558138880L; // 0x50000000000L
     field public static final long FIELD_COUNT_REPEATED = 2199023255552L; // 0x20000000000L
@@ -1435,6 +1476,7 @@
     field public static final long FIELD_TYPE_INT64 = 12884901888L; // 0x300000000L
     field public static final long FIELD_TYPE_MASK = 1095216660480L; // 0xff00000000L
     field public static final long FIELD_TYPE_MESSAGE = 47244640256L; // 0xb00000000L
+    field protected static final java.lang.String[] FIELD_TYPE_NAMES;
     field public static final long FIELD_TYPE_SFIXED32 = 64424509440L; // 0xf00000000L
     field public static final long FIELD_TYPE_SFIXED64 = 68719476736L; // 0x1000000000L
     field public static final int FIELD_TYPE_SHIFT = 32; // 0x20
@@ -1444,7 +1486,6 @@
     field public static final long FIELD_TYPE_UINT32 = 55834574848L; // 0xd00000000L
     field public static final long FIELD_TYPE_UINT64 = 17179869184L; // 0x400000000L
     field public static final long FIELD_TYPE_UNKNOWN = 0L; // 0x0L
-    field public static final java.lang.String TAG = "ProtoOutputStream";
     field public static final int WIRE_TYPE_END_GROUP = 4; // 0x4
     field public static final int WIRE_TYPE_FIXED32 = 5; // 0x5
     field public static final int WIRE_TYPE_FIXED64 = 1; // 0x1
@@ -1454,8 +1495,8 @@
     field public static final int WIRE_TYPE_VARINT = 0; // 0x0
   }
 
-  public class ProtoParseException extends java.lang.RuntimeException {
-    ctor public ProtoParseException(java.lang.String);
+  public class WireTypeMismatchException extends android.util.proto.ProtoParseException {
+    ctor public WireTypeMismatchException(java.lang.String);
   }
 
 }
@@ -1598,6 +1639,7 @@
   public final class Magnifier {
     method public android.graphics.Bitmap getContent();
     method public static android.graphics.PointF getMagnifierDefaultSize();
+    method public android.graphics.Bitmap getOriginalContent();
     method public void setOnOperationCompleteCallback(android.widget.Magnifier.Callback);
   }
 
diff --git a/cmds/incidentd/src/Section.h b/cmds/incidentd/src/Section.h
index 302b4ef..86d956f 100644
--- a/cmds/incidentd/src/Section.h
+++ b/cmds/incidentd/src/Section.h
@@ -171,7 +171,7 @@
  */
 class TombstoneSection : public WorkerThreadSection {
 public:
-    TombstoneSection(int id, const char* type, int64_t timeoutMs = 30000 /* 30 seconds */);
+    TombstoneSection(int id, const char* type, int64_t timeoutMs = 120000 /* 2 minutes */);
     virtual ~TombstoneSection();
 
     virtual status_t BlockingCall(int pipeWriteFd) const;
diff --git a/cmds/statsd/Android.bp b/cmds/statsd/Android.bp
index b566099..94203f4f 100644
--- a/cmds/statsd/Android.bp
+++ b/cmds/statsd/Android.bp
@@ -43,3 +43,26 @@
 }
 
 
+// ====  java proto device library (for test only)  ==============================
+java_library {
+    name: "statsdprotolite",
+    no_framework_libs: true,
+    proto: {
+        type: "lite",
+        include_dirs: ["external/protobuf/src"],
+    },
+
+    srcs: [
+        "src/stats_log.proto",
+        "src/statsd_config.proto",
+        "src/atoms.proto",
+    ],
+
+    static_libs: [
+        "platformprotoslite",
+    ],
+    // Protos have lots of MissingOverride and similar.
+    errorprone: {
+        javacflags: ["-XepDisableAllChecks"],
+    },
+}
diff --git a/cmds/statsd/Android.mk b/cmds/statsd/Android.mk
index ba2aaad8..5e87ef6 100644
--- a/cmds/statsd/Android.mk
+++ b/cmds/statsd/Android.mk
@@ -243,28 +243,6 @@
 include $(BUILD_NATIVE_TEST)
 
 ##############################
-# stats proto static java lib
-##############################
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := statsdprotolite
-
-LOCAL_SRC_FILES := \
-    src/stats_log.proto \
-    src/statsd_config.proto \
-    src/atoms.proto
-
-LOCAL_PROTOC_OPTIMIZE_TYPE := lite
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
-    platformprotoslite
-
-LOCAL_PROTOC_FLAGS := \
-    -Iexternal/protobuf/src
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
-##############################
 # statsd micro benchmark
 ##############################
 
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 6065bbf..3bd1bb0 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -29,6 +29,8 @@
 import "frameworks/base/core/proto/android/telecomm/enums.proto";
 import "frameworks/base/core/proto/android/telephony/enums.proto";
 import "frameworks/base/core/proto/android/view/enums.proto";
+import "frameworks/base/proto/src/stats_enums.proto";
+import "frameworks/base/core/proto/android/service/procstats.proto";
 
 /**
  * The master atom class. This message defines all of the available
@@ -89,7 +91,7 @@
         ActivityForegroundStateChanged activity_foreground_state_changed = 42;
         IsolatedUidChanged isolated_uid_changed = 43;
         PacketWakeupOccurred packet_wakeup_occurred = 44;
-        // 45 is available
+        WallClockTimeShifted wall_clock_time_shifted = 45;
         AnomalyDetected anomaly_detected = 46;
         AppBreadcrumbReported app_breadcrumb_reported = 47;
         AppStartOccurred app_start_occurred = 48;
@@ -128,10 +130,13 @@
         LowMemReported low_mem_reported = 81;
         GenericAtom generic_atom = 82;
         KeyValuePairsAtom key_value_pairs_atom = 83;
+        VibratorStateChanged vibrator_state_changed = 84;
+        DeferredJobStatsReported deferred_job_stats_reported = 85;
+        ThermalThrottlingStateChanged thermal_throttling = 86;
     }
 
     // Pulled events will start at field 10000.
-    // Next: 10024
+    // Next: 10025
     oneof pulled {
         WifiBytesTransfer wifi_bytes_transfer = 10000;
         WifiBytesTransferByFgBg wifi_bytes_transfer_by_fg_bg = 10001;
@@ -151,12 +156,18 @@
         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;
+        LooperStats looper_stats = 10024;
+        DiskStats disk_stats = 10025;
+        DirectoryUsage directory_usage = 10026;
+        AppSize app_size = 10027;
+        CategorySize category_size = 10028;
+        android.service.procstats.ProcessStatsSectionProto proc_stats = 10029;
     }
 
     // DO NOT USE field numbers above 100,000 in AOSP. Field numbers above
@@ -219,6 +230,26 @@
  */
 
 /**
+ * Logs when the Thermal service HAL notifies the throttling start/stop events.
+ *
+ * Logged from:
+ *   frameworks/base/services/core/java/com/android/server/stats/StatsCompanionService.java
+ */
+message ThermalThrottlingStateChanged {
+    optional android.os.TemperatureTypeEnum sensor_type = 1;
+
+    enum State {
+        UNKNOWN = 0;
+        START = 1;
+        STOP = 2;
+    }
+
+    optional State state = 2;
+
+    optional float temperature = 3;
+}
+
+/**
  * Logs when the screen state changes.
  *
  * Logged from:
@@ -466,6 +497,22 @@
     optional State state = 3;
 }
 
+/*
+ * Deferred job stats.
+ *
+ * Logged from:
+ *   frameworks/base/services/core/java/com/android/server/job/JobSchedulerService.java
+*/
+message DeferredJobStatsReported {
+    repeated AttributionNode attribution_node = 1;
+
+    // Number of jobs deferred.
+    optional int32 num_jobs_deferred = 2;
+
+    // Time since the last job runs.
+    optional int64 time_since_last_job_millis = 3;
+}
+
 /**
  * Logs when a job scheduler job state changes.
  *
@@ -734,7 +781,7 @@
  * Logs kernel wakeup reasons and aborts.
  *
  * Logged from:
- *   frameworks/base/services/core/java/com/android/server/am/BatteryStatsService.java
+ *   frameworks/base/core/java/com/android/internal/os/BatteryStatsImpl.java
  */
 message KernelWakeupReported {
     // Name of the kernel wakeup reason (or abort).
@@ -1410,6 +1457,25 @@
     optional ForegroundState foreground_state = 6;
 }
 
+/**
+ * Logs when the vibrator state changes.
+ * Logged from:
+ *      frameworks/base/services/core/java/com/android/server/VibratorService.java
+ */
+message VibratorStateChanged {
+    repeated AttributionNode attribution_node = 1;
+
+    enum State {
+        OFF = 0;
+        ON = 1;
+    }
+    optional State state = 2;
+
+    // Duration (in milliseconds) requested to keep the vibrator on.
+    // Only applicable for State == ON.
+    optional int64 duration_millis = 3;
+}
+
 /*
  * Allows other apps to push events into statsd.
  * Logged from:
@@ -1434,6 +1500,18 @@
 }
 
 /**
+ * Logs the wall-clock time when a significant wall-clock time shift occurs.
+ * For example, this could be due to the user manually changing the time.
+ *
+ * Logged from:
+ *   frameworks/base/services/core/java/com/android/server/AlarmManagerService.java
+ */
+message WallClockTimeShifted {
+    // New wall-clock time in milliseconds, according to System.currentTimeMillis().
+    optional int64 wall_clock_timestamp_millis = 1;
+}
+
+/**
  * Logs when statsd detects an anomaly.
  *
  * Logged from:
@@ -1750,7 +1828,7 @@
     optional int32 uid = 1 [(is_uid) = true];
 
     // An event_id indicates the type of event.
-    optional int32 event_id = 2;
+    optional android.os.statsd.EventType event_id = 2;
 }
 
 //////////////////////////////////////////////////////////////////////
@@ -2182,3 +2260,129 @@
     // Total number of exceptions.
     optional int64 exception_count = 2;
 }
+
+message LooperStats {
+    // Currently not collected and always set to 0.
+    optional int32 uid = 1 [(is_uid) = true];
+
+    // Fully qualified class name of the handler target class.
+    //
+    // This field does not contain PII. This is a system server class name.
+    optional string handler_class_name = 2;
+
+    // The name of the thread that runs the Looper.
+    //
+    // This field does not contain PII. This is a system server thread name.
+    optional string looper_thread_name = 3;
+
+    // The name of the dispatched message.
+    //
+    // This field does not contain PII. This is a system server constant or class
+    // name.
+    optional string message_name = 4;
+
+    // Total number of successfully dispatched messages.
+    optional int64 message_count = 5;
+
+    // Total number of messages that failed dispatching.
+    optional int64 exception_count = 6;
+
+    // Total number of processed messages we have data recorded for. If we
+    // collected data for all the messages, message_count will be equal to
+    // recorded_message_count.
+    //
+    // If recorded_message_count is different than message_count, it means data
+    // collection has been sampled. All the fields below will be sampled in this
+    // case.
+    optional int64 recorded_message_count = 7;
+
+    // Total latency of all processed messages.
+    // Average can be computed using recorded_total_latency_micros /
+    // recorded_message_count.
+    optional int64 recorded_total_latency_micros = 8;
+
+    // Total CPU usage of all processed message.
+    // Average can be computed using recorded_total_cpu_micros /
+    // recorded_message_count. Total can be computed using
+    // recorded_total_cpu_micros / recorded_message_count * call_count.
+    optional int64 recorded_total_cpu_micros = 9;
+}
+
+/**
+ * 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/external/Perfetto.cpp b/cmds/statsd/src/external/Perfetto.cpp
index e44351b..42cc543 100644
--- a/cmds/statsd/src/external/Perfetto.cpp
+++ b/cmds/statsd/src/external/Perfetto.cpp
@@ -105,9 +105,9 @@
 
     readPipe.reset();  // Close the read end (owned by the child process).
 
-    // Using fopen() because fwrite() has the right logic to chunking write()
+    // Using fdopen() because fwrite() has the right logic to chunking write()
     // over a pipe (see __sfvwrite()).
-    FILE* writePipeStream = fdopen(writePipe.get(), "wb");
+    FILE* writePipeStream = android::base::Fdopen(std::move(writePipe), "wb");
     if (!writePipeStream) {
         ALOGE("fdopen() failed while calling the Perfetto client: %s", strerror(errno));
         return false;
diff --git a/cmds/statsd/src/external/StatsPullerManager.cpp b/cmds/statsd/src/external/StatsPullerManager.cpp
index e6e8455..f6ba0b6 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,7 @@
           1 * NS_PER_SEC,
           new StatsCompanionServicePuller(android::util::PROCESS_MEMORY_STATE)}},
         // temperature
-        {android::util::TEMPERATURE, {{}, {}, 1, new ResourceThermalManagerPuller()}},
+        {android::util::TEMPERATURE, {{}, {}, 1 * NS_PER_SEC, new ResourceThermalManagerPuller()}},
         // binder_calls
         {android::util::BINDER_CALLS,
          {{4, 5, 6, 8, 12},
@@ -183,7 +180,37 @@
          {{},
           {},
           1 * NS_PER_SEC,
-          new StatsCompanionServicePuller(android::util::BINDER_CALLS_EXCEPTIONS)}}
+          new StatsCompanionServicePuller(android::util::BINDER_CALLS_EXCEPTIONS)}},
+        // looper_stats
+        {android::util::LOOPER_STATS,
+         {{5, 6, 7, 8, 9},
+          {2, 3, 4},
+          1 * NS_PER_SEC,
+          new StatsCompanionServicePuller(android::util::LOOPER_STATS)}},
+        // 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/logd/LogEvent.cpp b/cmds/statsd/src/logd/LogEvent.cpp
index 73e6572..cf04ee3 100644
--- a/cmds/statsd/src/logd/LogEvent.cpp
+++ b/cmds/statsd/src/logd/LogEvent.cpp
@@ -175,6 +175,56 @@
     return false;
 }
 
+
+
+bool LogEvent::writeKeyValuePairs(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) {
+    if (mContext) {
+         if (android_log_write_list_begin(mContext) < 0) {
+            return false;
+         }
+         for (const auto& itr : int_map) {
+             if (android_log_write_list_begin(mContext) < 0) {
+                return false;
+             }
+             write(itr.first);
+             write(itr.second);
+             if (android_log_write_list_end(mContext) < 0) {
+                return false;
+             }
+         }
+
+         for (const auto& itr : string_map) {
+             if (android_log_write_list_begin(mContext) < 0) {
+                return false;
+             }
+             write(itr.first);
+             write(itr.second.c_str());
+             if (android_log_write_list_end(mContext) < 0) {
+                return false;
+             }
+         }
+
+         for (const auto& itr : float_map) {
+             if (android_log_write_list_begin(mContext) < 0) {
+                return false;
+             }
+             write(itr.first);
+             write(itr.second);
+             if (android_log_write_list_end(mContext) < 0) {
+                return false;
+             }
+         }
+
+         if (android_log_write_list_end(mContext) < 0) {
+            return false;
+         }
+         return true;
+    }
+    return false;
+}
+
 bool LogEvent::write(const std::vector<AttributionNodeInternal>& nodes) {
     if (mContext) {
          if (android_log_write_list_begin(mContext) < 0) {
@@ -225,6 +275,7 @@
     int i = 0;
     int depth = -1;
     int pos[] = {1, 1, 1};
+    bool isKeyValuePairAtom = false;
     do {
         elem = android_log_read_next(context);
         switch ((int)elem.type) {
@@ -232,6 +283,7 @@
                 // elem at [0] is EVENT_TYPE_LIST, [1] is the timestamp, [2] is tag id.
                 if (i == 2) {
                     mTagId = elem.data.int32;
+                    isKeyValuePairAtom = (mTagId == android::util::KEY_VALUE_PAIRS_ATOM);
                 } else {
                     if (depth < 0 || depth > 2) {
                         return;
@@ -249,6 +301,11 @@
                     return;
                 }
 
+                // Handles the oneof field in KeyValuePair atom.
+                if (isKeyValuePairAtom && depth == 2) {
+                    pos[depth] = 4;
+                }
+
                 mValues.push_back(FieldValue(Field(mTagId, pos, depth), Value(elem.data.float32)));
 
                 pos[depth]++;
@@ -260,6 +317,10 @@
                     return;
                 }
 
+                // Handles the oneof field in KeyValuePair atom.
+                if (isKeyValuePairAtom && depth == 2) {
+                    pos[depth] = 3;
+                }
                 mValues.push_back(FieldValue(Field(mTagId, pos, depth),
                                              Value(string(elem.data.string, elem.len))));
 
@@ -274,6 +335,10 @@
                         ALOGE("Depth > 2. Not supported!");
                         return;
                     }
+                    // Handles the oneof field in KeyValuePair atom.
+                    if (isKeyValuePairAtom && depth == 2) {
+                        pos[depth] = 2;
+                    }
                     mValues.push_back(
                             FieldValue(Field(mTagId, pos, depth), Value((int64_t)elem.data.int64)));
 
diff --git a/cmds/statsd/src/logd/LogEvent.h b/cmds/statsd/src/logd/LogEvent.h
index 9ed09dd..2ee6bdf 100644
--- a/cmds/statsd/src/logd/LogEvent.h
+++ b/cmds/statsd/src/logd/LogEvent.h
@@ -119,6 +119,9 @@
     bool write(float value);
     bool write(const std::vector<AttributionNodeInternal>& nodes);
     bool write(const AttributionNodeInternal& node);
+    bool writeKeyValuePairs(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);
 
     /**
      * Return a string representation of this event.
diff --git a/cmds/statsd/src/metrics/EventMetricProducer.cpp b/cmds/statsd/src/metrics/EventMetricProducer.cpp
index eec90fc..afd8ec2 100644
--- a/cmds/statsd/src/metrics/EventMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/EventMetricProducer.cpp
@@ -49,7 +49,6 @@
 // for EventMetricData
 const int FIELD_ID_ELAPSED_TIMESTAMP_NANOS = 1;
 const int FIELD_ID_ATOMS = 2;
-const int FIELD_ID_WALL_CLOCK_TIMESTAMP_NANOS = 3;
 
 EventMetricProducer::EventMetricProducer(const ConfigKey& key, const EventMetric& metric,
                                          const int conditionIndex,
@@ -146,13 +145,9 @@
     if (truncateTimestamp) {
         mProto->write(FIELD_TYPE_INT64 | FIELD_ID_ELAPSED_TIMESTAMP_NANOS,
             (long long)truncateTimestampNsToFiveMinutes(event.GetElapsedTimestampNs()));
-        mProto->write(FIELD_TYPE_INT64 | FIELD_ID_WALL_CLOCK_TIMESTAMP_NANOS,
-            (long long)truncateTimestampNsToFiveMinutes(getWallClockNs()));
     } else {
         mProto->write(FIELD_TYPE_INT64 | FIELD_ID_ELAPSED_TIMESTAMP_NANOS,
             (long long)event.GetElapsedTimestampNs());
-        mProto->write(FIELD_TYPE_INT64 | FIELD_ID_WALL_CLOCK_TIMESTAMP_NANOS,
-            (long long)getWallClockNs());
     }
 
     uint64_t eventToken = mProto->start(FIELD_TYPE_MESSAGE | FIELD_ID_ATOMS);
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
index 284c451..02b9773 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
@@ -63,7 +63,6 @@
 // for GaugeBucketInfo
 const int FIELD_ID_ATOM = 3;
 const int FIELD_ID_ELAPSED_ATOM_TIMESTAMP = 4;
-const int FIELD_ID_WALL_CLOCK_ATOM_TIMESTAMP = 5;
 const int FIELD_ID_BUCKET_NUM = 6;
 const int FIELD_ID_START_BUCKET_ELAPSED_MILLIS = 7;
 const int FIELD_ID_END_BUCKET_ELAPSED_MILLIS = 8;
@@ -286,16 +285,9 @@
                     const int64_t elapsedTimestampNs =  truncateTimestamp ?
                         truncateTimestampNsToFiveMinutes(atom.mElapsedTimestamps) :
                             atom.mElapsedTimestamps;
-                    const int64_t wallClockNs = truncateTimestamp ?
-                        truncateTimestampNsToFiveMinutes(atom.mWallClockTimestampNs) :
-                            atom.mWallClockTimestampNs;
                     protoOutput->write(
                         FIELD_TYPE_INT64 | FIELD_COUNT_REPEATED | FIELD_ID_ELAPSED_ATOM_TIMESTAMP,
                         (long long)elapsedTimestampNs);
-                    protoOutput->write(
-                        FIELD_TYPE_INT64 | FIELD_COUNT_REPEATED |
-                            FIELD_ID_WALL_CLOCK_ATOM_TIMESTAMP,
-                        (long long)wallClockNs);
                 }
             }
             protoOutput->end(bucketInfoToken);
@@ -367,13 +359,26 @@
 }
 
 std::shared_ptr<vector<FieldValue>> GaugeMetricProducer::getGaugeFields(const LogEvent& event) {
+    std::shared_ptr<vector<FieldValue>> gaugeFields;
     if (mFieldMatchers.size() > 0) {
-        std::shared_ptr<vector<FieldValue>> gaugeFields = std::make_shared<vector<FieldValue>>();
+        gaugeFields = std::make_shared<vector<FieldValue>>();
         filterGaugeValues(mFieldMatchers, event.getValues(), gaugeFields.get());
-        return gaugeFields;
     } else {
-        return std::make_shared<vector<FieldValue>>(event.getValues());
+        gaugeFields = std::make_shared<vector<FieldValue>>(event.getValues());
     }
+    // Trim all dimension fields from output. Dimensions will appear in output report and will
+    // benefit from dictionary encoding. For large pulled atoms, this can give the benefit of
+    // optional repeated field.
+    for (const auto& field : mDimensionsInWhat) {
+        for (auto it = gaugeFields->begin(); it != gaugeFields->end();) {
+            if (it->mField.matches(field)) {
+                it = gaugeFields->erase(it);
+            } else {
+                it++;
+            }
+        }
+    }
+    return gaugeFields;
 }
 
 void GaugeMetricProducer::onDataPulled(const std::vector<std::shared_ptr<LogEvent>>& allData) {
@@ -437,7 +442,7 @@
     if ((*mCurrentSlicedBucket)[eventKey].size() >= mGaugeAtomsPerDimensionLimit) {
         return;
     }
-    GaugeAtom gaugeAtom(getGaugeFields(event), eventTimeNs, getWallClockNs());
+    GaugeAtom gaugeAtom(getGaugeFields(event), eventTimeNs);
     (*mCurrentSlicedBucket)[eventKey].push_back(gaugeAtom);
     // Anomaly detection on gauge metric only works when there is one numeric
     // field specified.
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.h b/cmds/statsd/src/metrics/GaugeMetricProducer.h
index 15be1d7..6379389 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.h
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.h
@@ -33,12 +33,11 @@
 namespace statsd {
 
 struct GaugeAtom {
-    GaugeAtom(std::shared_ptr<vector<FieldValue>> fields, int64_t elapsedTimeNs, int64_t wallClockNs)
-        : mFields(fields), mElapsedTimestamps(elapsedTimeNs), mWallClockTimestampNs(wallClockNs) {
+    GaugeAtom(std::shared_ptr<vector<FieldValue>> fields, int64_t elapsedTimeNs)
+        : mFields(fields), mElapsedTimestamps(elapsedTimeNs) {
     }
     std::shared_ptr<vector<FieldValue>> mFields;
     int64_t mElapsedTimestamps;
-    int64_t mWallClockTimestampNs;
 };
 
 struct GaugeBucket {
@@ -175,6 +174,7 @@
     FRIEND_TEST(GaugeMetricProducerTest, TestPulledEventsAnomalyDetection);
     FRIEND_TEST(GaugeMetricProducerTest, TestFirstBucket);
     FRIEND_TEST(GaugeMetricProducerTest, TestPullOnTrigger);
+    FRIEND_TEST(GaugeMetricProducerTest, TestRemoveDimensionInOutput);
 };
 
 }  // namespace statsd
diff --git a/cmds/statsd/src/stats_log.proto b/cmds/statsd/src/stats_log.proto
index db7e680..ab0b23c 100644
--- a/cmds/statsd/src/stats_log.proto
+++ b/cmds/statsd/src/stats_log.proto
@@ -46,7 +46,7 @@
 
   optional Atom atom = 2;
 
-  optional int64 wall_clock_timestamp_nanos = 3;
+  optional int64 wall_clock_timestamp_nanos = 3 [deprecated = true];
 }
 
 message CountBucketInfo {
@@ -142,7 +142,7 @@
 
   repeated int64 elapsed_timestamp_nanos = 4;
 
-  repeated int64 wall_clock_timestamp_nanos = 5;
+  repeated int64 wall_clock_timestamp_nanos = 5 [deprecated = true];
 
   optional int64 bucket_num = 6;
 
diff --git a/cmds/statsd/tests/LogEvent_test.cpp b/cmds/statsd/tests/LogEvent_test.cpp
index acfa151..6e3b04c 100644
--- a/cmds/statsd/tests/LogEvent_test.cpp
+++ b/cmds/statsd/tests/LogEvent_test.cpp
@@ -89,6 +89,89 @@
     EXPECT_EQ((float)1.1, item7.mValue.float_value);
 }
 
+TEST(LogEventTest, TestKeyValuePairsAtomParsing) {
+    LogEvent event1(83, 2000);
+    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;
+
+    EXPECT_TRUE(event1.writeKeyValuePairs(int_map, string_map, float_map));
+    event1.init();
+
+    EXPECT_EQ(83, event1.GetTagId());
+    const auto& items = event1.getValues();
+    EXPECT_EQ((size_t)12, items.size());
+
+    const FieldValue& item0 = event1.getValues()[0];
+    EXPECT_EQ(0x2010101, item0.mField.getField());
+    EXPECT_EQ(Type::INT, item0.mValue.getType());
+    EXPECT_EQ(11, item0.mValue.int_value);
+
+    const FieldValue& item1 = event1.getValues()[1];
+    EXPECT_EQ(0x2010182, item1.mField.getField());
+    EXPECT_EQ(Type::LONG, item1.mValue.getType());
+    EXPECT_EQ(123L, item1.mValue.long_value);
+
+    const FieldValue& item2 = event1.getValues()[2];
+    EXPECT_EQ(0x2010201, item2.mField.getField());
+    EXPECT_EQ(Type::INT, item2.mValue.getType());
+    EXPECT_EQ(22, item2.mValue.int_value);
+
+    const FieldValue& item3 = event1.getValues()[3];
+    EXPECT_EQ(0x2010282, item3.mField.getField());
+    EXPECT_EQ(Type::LONG, item3.mValue.getType());
+    EXPECT_EQ(345L, item3.mValue.long_value);
+
+    const FieldValue& item4 = event1.getValues()[4];
+    EXPECT_EQ(0x2010301, item4.mField.getField());
+    EXPECT_EQ(Type::INT, item4.mValue.getType());
+    EXPECT_EQ(1, item4.mValue.int_value);
+
+    const FieldValue& item5 = event1.getValues()[5];
+    EXPECT_EQ(0x2010383, item5.mField.getField());
+    EXPECT_EQ(Type::STRING, item5.mValue.getType());
+    EXPECT_EQ("test2", item5.mValue.str_value);
+
+    const FieldValue& item6 = event1.getValues()[6];
+    EXPECT_EQ(0x2010401, item6.mField.getField());
+    EXPECT_EQ(Type::INT, item6.mValue.getType());
+    EXPECT_EQ(2, item6.mValue.int_value);
+
+    const FieldValue& item7 = event1.getValues()[7];
+    EXPECT_EQ(0x2010483, item7.mField.getField());
+    EXPECT_EQ(Type::STRING, item7.mValue.getType());
+    EXPECT_EQ("test1", item7.mValue.str_value);
+
+    const FieldValue& item8 = event1.getValues()[8];
+    EXPECT_EQ(0x2010501, item8.mField.getField());
+    EXPECT_EQ(Type::INT, item8.mValue.getType());
+    EXPECT_EQ(111, item8.mValue.int_value);
+
+    const FieldValue& item9 = event1.getValues()[9];
+    EXPECT_EQ(0x2010584, item9.mField.getField());
+    EXPECT_EQ(Type::FLOAT, item9.mValue.getType());
+    EXPECT_EQ(2.2f, item9.mValue.float_value);
+
+    const FieldValue& item10 = event1.getValues()[10];
+    EXPECT_EQ(0x2018601, item10.mField.getField());
+    EXPECT_EQ(Type::INT, item10.mValue.getType());
+    EXPECT_EQ(222, item10.mValue.int_value);
+
+    const FieldValue& item11 = event1.getValues()[11];
+    EXPECT_EQ(0x2018684, item11.mField.getField());
+    EXPECT_EQ(Type::FLOAT, item11.mValue.getType());
+    EXPECT_EQ(1.1f, item11.mValue.float_value);
+}
+
 TEST(LogEventTest, TestLogParsing2) {
     LogEvent event1(1, 2000);
 
@@ -158,7 +241,7 @@
     EXPECT_EQ((float)1.1, item7.mValue.float_value);
 }
 
-TEST(LogEventTest, TestKeyValuePairsAtomParsing) {
+TEST(LogEventTest, TestKeyValuePairsEvent) {
     std::map<int32_t, int64_t> int_map;
     std::map<int32_t, std::string> string_map;
     std::map<int32_t, float> float_map;
diff --git a/cmds/statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp b/cmds/statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp
index d98395e..5b6f167 100644
--- a/cmds/statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp
+++ b/cmds/statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp
@@ -48,6 +48,7 @@
     *gaugeMetric->mutable_dimensions_in_what() =
         CreateDimensions(android::util::TEMPERATURE, {2/* sensor name field */ });
     gaugeMetric->set_bucket(FIVE_MINUTES);
+    config.set_hash_strings_in_metric_report(false);
 
     return config;
 }
@@ -147,10 +148,10 @@
     EXPECT_EQ(1, data.bucket_info(0).atom_size());
     EXPECT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size());
     EXPECT_EQ(configAddedTimeNs + 55, data.bucket_info(0).elapsed_timestamp_nanos(0));
-    EXPECT_EQ(1, data.bucket_info(0).wall_clock_timestamp_nanos_size());
+    EXPECT_EQ(0, data.bucket_info(0).wall_clock_timestamp_nanos_size());
     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_FALSE(data.bucket_info(0).atom(0).temperature().sensor_name().empty());
+    EXPECT_TRUE(data.bucket_info(0).atom(0).temperature().sensor_name().empty());
     EXPECT_GT(data.bucket_info(0).atom(0).temperature().temperature_dc(), 0);
 
     EXPECT_EQ(1, data.bucket_info(1).atom_size());
@@ -159,7 +160,7 @@
     EXPECT_EQ(configAddedTimeNs + 55, data.bucket_info(0).elapsed_timestamp_nanos(0));
     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_FALSE(data.bucket_info(1).atom(0).temperature().sensor_name().empty());
+    EXPECT_TRUE(data.bucket_info(1).atom(0).temperature().sensor_name().empty());
     EXPECT_GT(data.bucket_info(1).atom(0).temperature().temperature_dc(), 0);
 
     EXPECT_EQ(1, data.bucket_info(2).atom_size());
@@ -168,7 +169,7 @@
               data.bucket_info(2).elapsed_timestamp_nanos(0));
     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_FALSE(data.bucket_info(2).atom(0).temperature().sensor_name().empty());
+    EXPECT_TRUE(data.bucket_info(2).atom(0).temperature().sensor_name().empty());
     EXPECT_GT(data.bucket_info(2).atom(0).temperature().temperature_dc(), 0);
 
     EXPECT_EQ(1, data.bucket_info(3).atom_size());
@@ -177,7 +178,7 @@
               data.bucket_info(3).elapsed_timestamp_nanos(0));
     EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(3).start_bucket_elapsed_nanos());
     EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(3).end_bucket_elapsed_nanos());
-    EXPECT_FALSE(data.bucket_info(3).atom(0).temperature().sensor_name().empty());
+    EXPECT_TRUE(data.bucket_info(3).atom(0).temperature().sensor_name().empty());
     EXPECT_GT(data.bucket_info(3).atom(0).temperature().temperature_dc(), 0);
 
     EXPECT_EQ(1, data.bucket_info(4).atom_size());
@@ -186,7 +187,7 @@
               data.bucket_info(4).elapsed_timestamp_nanos(0));
     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_FALSE(data.bucket_info(4).atom(0).temperature().sensor_name().empty());
+    EXPECT_TRUE(data.bucket_info(4).atom(0).temperature().sensor_name().empty());
     EXPECT_GT(data.bucket_info(4).atom(0).temperature().temperature_dc(), 0);
 
     EXPECT_EQ(1, data.bucket_info(5).atom_size());
@@ -195,7 +196,7 @@
               data.bucket_info(5).elapsed_timestamp_nanos(0));
     EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(5).start_bucket_elapsed_nanos());
     EXPECT_EQ(baseTimeNs + 9 * bucketSizeNs, data.bucket_info(5).end_bucket_elapsed_nanos());
-    EXPECT_FALSE(data.bucket_info(5).atom(0).temperature().sensor_name().empty());
+    EXPECT_TRUE(data.bucket_info(5).atom(0).temperature().sensor_name().empty());
     EXPECT_GT(data.bucket_info(5).atom(0).temperature().temperature_dc(), 0);
 }
 
@@ -270,10 +271,10 @@
     EXPECT_EQ(1, data.bucket_info(0).atom_size());
     EXPECT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size());
     EXPECT_EQ(configAddedTimeNs + 55, data.bucket_info(0).elapsed_timestamp_nanos(0));
-    EXPECT_EQ(1, data.bucket_info(0).wall_clock_timestamp_nanos_size());
+    EXPECT_EQ(0, data.bucket_info(0).wall_clock_timestamp_nanos_size());
     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_FALSE(data.bucket_info(0).atom(0).temperature().sensor_name().empty());
+    EXPECT_TRUE(data.bucket_info(0).atom(0).temperature().sensor_name().empty());
     EXPECT_GT(data.bucket_info(0).atom(0).temperature().temperature_dc(), 0);
 
     EXPECT_EQ(1, data.bucket_info(1).atom_size());
@@ -282,7 +283,7 @@
     EXPECT_EQ(configAddedTimeNs + 55, data.bucket_info(0).elapsed_timestamp_nanos(0));
     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_FALSE(data.bucket_info(1).atom(0).temperature().sensor_name().empty());
+    EXPECT_TRUE(data.bucket_info(1).atom(0).temperature().sensor_name().empty());
     EXPECT_GT(data.bucket_info(1).atom(0).temperature().temperature_dc(), 0);
 
     EXPECT_EQ(2, data.bucket_info(2).atom_size());
@@ -293,9 +294,9 @@
               data.bucket_info(2).elapsed_timestamp_nanos(1));
     EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
     EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
-    EXPECT_FALSE(data.bucket_info(2).atom(0).temperature().sensor_name().empty());
+    EXPECT_TRUE(data.bucket_info(2).atom(0).temperature().sensor_name().empty());
     EXPECT_GT(data.bucket_info(2).atom(0).temperature().temperature_dc(), 0);
-    EXPECT_FALSE(data.bucket_info(2).atom(1).temperature().sensor_name().empty());
+    EXPECT_TRUE(data.bucket_info(2).atom(1).temperature().sensor_name().empty());
     EXPECT_GT(data.bucket_info(2).atom(1).temperature().temperature_dc(), 0);
 }
 
@@ -374,10 +375,9 @@
     EXPECT_EQ(1, data.bucket_info(0).atom_size());
     EXPECT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size());
     EXPECT_EQ(configAddedTimeNs + 55, data.bucket_info(0).elapsed_timestamp_nanos(0));
-    EXPECT_EQ(1, data.bucket_info(0).wall_clock_timestamp_nanos_size());
     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_FALSE(data.bucket_info(0).atom(0).temperature().sensor_name().empty());
+    EXPECT_TRUE(data.bucket_info(0).atom(0).temperature().sensor_name().empty());
     EXPECT_GT(data.bucket_info(0).atom(0).temperature().temperature_dc(), 0);
 
     EXPECT_EQ(1, data.bucket_info(1).atom_size());
@@ -386,7 +386,7 @@
     EXPECT_EQ(configAddedTimeNs + 55, data.bucket_info(0).elapsed_timestamp_nanos(0));
     EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
     EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos());
-    EXPECT_FALSE(data.bucket_info(1).atom(0).temperature().sensor_name().empty());
+    EXPECT_TRUE(data.bucket_info(1).atom(0).temperature().sensor_name().empty());
     EXPECT_GT(data.bucket_info(1).atom(0).temperature().temperature_dc(), 0);
 
     EXPECT_EQ(1, data.bucket_info(2).atom_size());
@@ -395,7 +395,7 @@
               data.bucket_info(2).elapsed_timestamp_nanos(0));
     EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
     EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
-    EXPECT_FALSE(data.bucket_info(2).atom(0).temperature().sensor_name().empty());
+    EXPECT_TRUE(data.bucket_info(2).atom(0).temperature().sensor_name().empty());
     EXPECT_GT(data.bucket_info(2).atom(0).temperature().temperature_dc(), 0);
 
 }
diff --git a/cmds/statsd/tests/e2e/GaugeMetric_e2e_push_test.cpp b/cmds/statsd/tests/e2e/GaugeMetric_e2e_push_test.cpp
index 3de8d0d..5c1ef01 100644
--- a/cmds/statsd/tests/e2e/GaugeMetric_e2e_push_test.cpp
+++ b/cmds/statsd/tests/e2e/GaugeMetric_e2e_push_test.cpp
@@ -173,7 +173,7 @@
         if (sampling_type == GaugeMetric::ALL_CONDITION_CHANGES) {
             EXPECT_EQ(2, data.bucket_info(0).atom_size());
             EXPECT_EQ(2, data.bucket_info(0).elapsed_timestamp_nanos_size());
-            EXPECT_EQ(2, data.bucket_info(0).wall_clock_timestamp_nanos_size());
+            EXPECT_EQ(0, data.bucket_info(0).wall_clock_timestamp_nanos_size());
             EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
             EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
                       data.bucket_info(0).end_bucket_elapsed_nanos());
@@ -192,7 +192,6 @@
 
             EXPECT_EQ(1, data.bucket_info(1).atom_size());
             EXPECT_EQ(1, data.bucket_info(1).elapsed_timestamp_nanos_size());
-            EXPECT_EQ(1, data.bucket_info(1).wall_clock_timestamp_nanos_size());
             EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
                       data.bucket_info(1).start_bucket_elapsed_nanos());
             EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
@@ -206,7 +205,6 @@
 
             EXPECT_EQ(2, data.bucket_info(2).atom_size());
             EXPECT_EQ(2, data.bucket_info(2).elapsed_timestamp_nanos_size());
-            EXPECT_EQ(2, data.bucket_info(2).wall_clock_timestamp_nanos_size());
             EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
                       data.bucket_info(2).start_bucket_elapsed_nanos());
             EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs,
@@ -226,7 +224,6 @@
         } else {
             EXPECT_EQ(1, data.bucket_info(0).atom_size());
             EXPECT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size());
-            EXPECT_EQ(1, data.bucket_info(0).wall_clock_timestamp_nanos_size());
             EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
             EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
                       data.bucket_info(0).end_bucket_elapsed_nanos());
@@ -239,7 +236,6 @@
 
             EXPECT_EQ(1, data.bucket_info(1).atom_size());
             EXPECT_EQ(1, data.bucket_info(1).elapsed_timestamp_nanos_size());
-            EXPECT_EQ(1, data.bucket_info(1).wall_clock_timestamp_nanos_size());
             EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
                       data.bucket_info(1).start_bucket_elapsed_nanos());
             EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
@@ -253,7 +249,6 @@
 
             EXPECT_EQ(1, data.bucket_info(2).atom_size());
             EXPECT_EQ(1, data.bucket_info(2).elapsed_timestamp_nanos_size());
-            EXPECT_EQ(1, data.bucket_info(2).wall_clock_timestamp_nanos_size());
             EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
                       data.bucket_info(2).start_bucket_elapsed_nanos());
             EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs,
@@ -276,7 +271,6 @@
         EXPECT_EQ(1, data.bucket_info_size());
         EXPECT_EQ(1, data.bucket_info(0).atom_size());
         EXPECT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size());
-        EXPECT_EQ(1, data.bucket_info(0).wall_clock_timestamp_nanos_size());
         EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
                   data.bucket_info(0).start_bucket_elapsed_nanos());
         EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs,
diff --git a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
index 9471faa..bf58b9c 100644
--- a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
@@ -95,6 +95,8 @@
                 data->clear();
                 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
                 event->write(3);
+                event->write("some value");
+                event->write(11);
                 event->init();
                 data->push_back(event);
                 return true;
@@ -600,9 +602,109 @@
     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);
+    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);
+}
+
+TEST(GaugeMetricProducerTest, TestRemoveDimensionInOutput) {
+    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(true);
+    auto dimensionMatcher = metric.mutable_dimensions_in_what();
+    // use field 1 as dimension.
+    dimensionMatcher->set_field(tagId);
+    dimensionMatcher->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->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 + 10);
+                event->write(4);
+                event->write(5);
+                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(4);
+                event->write(6);
+                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->size());
+    EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->begin()->second.size());
+    trigger.setElapsedTimestampNs(bucketStartTimeNs + 20);
+    gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, trigger);
+    EXPECT_EQ(2UL, gaugeProducer.mCurrentSlicedBucket->begin()->second.size());
+
+    allData.clear();
+    shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+    event->write(4);
+    event->write(11);
+    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(11, it->mValue.int_value);
+    EXPECT_EQ(2UL, gaugeProducer.mPastBuckets.size());
+    auto bucketIt = gaugeProducer.mPastBuckets.begin();
+    EXPECT_EQ(1UL, bucketIt->second.back().mGaugeAtoms.size());
+    EXPECT_EQ(3, bucketIt->first.getDimensionKeyInWhat().getValues().begin()->mValue.int_value);
+    EXPECT_EQ(4, bucketIt->second.back().mGaugeAtoms[0].mFields->begin()->mValue.int_value);
+    bucketIt++;
+    EXPECT_EQ(2UL, bucketIt->second.back().mGaugeAtoms.size());
+    EXPECT_EQ(4, bucketIt->first.getDimensionKeyInWhat().getValues().begin()->mValue.int_value);
+    EXPECT_EQ(5, bucketIt->second.back().mGaugeAtoms[0].mFields->begin()->mValue.int_value);
+    EXPECT_EQ(6, bucketIt->second.back().mGaugeAtoms[1].mFields->begin()->mValue.int_value);
 }
 
 }  // namespace statsd
diff --git a/config/boot-image-profile.txt b/config/boot-image-profile.txt
index cdcdc46..b683138 100644
--- a/config/boot-image-profile.txt
+++ b/config/boot-image-profile.txt
@@ -11818,6 +11818,7 @@
 HPLlibcore/io/BlockGuardOs;->rename(Ljava/lang/String;Ljava/lang/String;)V
 HPLlibcore/io/BlockGuardOs;->sendto(Ljava/io/FileDescriptor;[BIIILjava/net/SocketAddress;)I
 HPLlibcore/io/BlockGuardOs;->write(Ljava/io/FileDescriptor;Ljava/nio/ByteBuffer;)I
+HPLlibcore/io/ForwardingOs;->android_fdsan_exchange_owner_tag(Ljava/io/FileDescriptor;JJ)V
 HPLlibcore/io/ForwardingOs;->munlock(JJ)V
 HPLlibcore/io/ForwardingOs;->munmap(JJ)V
 HPLlibcore/io/ForwardingOs;->setsockoptByte(Ljava/io/FileDescriptor;III)V
@@ -15604,7 +15605,6 @@
 HSPLandroid/app/admin/IDevicePolicyManager;->getLockTaskPackages(Landroid/content/ComponentName;)[Ljava/lang/String;
 HSPLandroid/app/admin/IDevicePolicyManager;->getLongSupportMessage(Landroid/content/ComponentName;)Ljava/lang/CharSequence;
 HSPLandroid/app/admin/IDevicePolicyManager;->getLongSupportMessageForUser(Landroid/content/ComponentName;I)Ljava/lang/CharSequence;
-HSPLandroid/app/admin/IDevicePolicyManager;->getMandatoryBackupTransport()Landroid/content/ComponentName;
 HSPLandroid/app/admin/IDevicePolicyManager;->getMaximumFailedPasswordsForWipe(Landroid/content/ComponentName;IZ)I
 HSPLandroid/app/admin/IDevicePolicyManager;->getMaximumTimeToLock(Landroid/content/ComponentName;IZ)J
 HSPLandroid/app/admin/IDevicePolicyManager;->getMeteredDataDisabledPackages(Landroid/content/ComponentName;)Ljava/util/List;
@@ -15746,7 +15746,6 @@
 HSPLandroid/app/admin/IDevicePolicyManager;->setLockTaskPackages(Landroid/content/ComponentName;[Ljava/lang/String;)V
 HSPLandroid/app/admin/IDevicePolicyManager;->setLogoutEnabled(Landroid/content/ComponentName;Z)V
 HSPLandroid/app/admin/IDevicePolicyManager;->setLongSupportMessage(Landroid/content/ComponentName;Ljava/lang/CharSequence;)V
-HSPLandroid/app/admin/IDevicePolicyManager;->setMandatoryBackupTransport(Landroid/content/ComponentName;Landroid/content/ComponentName;)Z
 HSPLandroid/app/admin/IDevicePolicyManager;->setMasterVolumeMuted(Landroid/content/ComponentName;Z)V
 HSPLandroid/app/admin/IDevicePolicyManager;->setMaximumFailedPasswordsForWipe(Landroid/content/ComponentName;IZ)V
 HSPLandroid/app/admin/IDevicePolicyManager;->setMaximumTimeToLock(Landroid/content/ComponentName;JZ)V
@@ -24287,7 +24286,6 @@
 HSPLandroid/inputmethodservice/IInputMethodSessionWrapper;->getInternalInputMethodSession()Landroid/view/inputmethod/InputMethodSession;
 HSPLandroid/inputmethodservice/IInputMethodWrapper$InputMethodSessionCallbackWrapper;->sessionCreated(Landroid/view/inputmethod/InputMethodSession;)V
 HSPLandroid/inputmethodservice/IInputMethodWrapper;-><init>(Landroid/inputmethodservice/AbstractInputMethodService;Landroid/view/inputmethod/InputMethod;)V
-HSPLandroid/inputmethodservice/IInputMethodWrapper;->attachToken(Landroid/os/IBinder;)V
 HSPLandroid/inputmethodservice/IInputMethodWrapper;->bindInput(Landroid/view/inputmethod/InputBinding;)V
 HSPLandroid/inputmethodservice/IInputMethodWrapper;->createSession(Landroid/view/InputChannel;Lcom/android/internal/view/IInputSessionCallback;)V
 HSPLandroid/inputmethodservice/IInputMethodWrapper;->executeMessage(Landroid/os/Message;)V
@@ -42279,11 +42277,9 @@
 HSPLcom/android/internal/view/IInputContextCallback;->setTextAfterCursor(Ljava/lang/CharSequence;I)V
 HSPLcom/android/internal/view/IInputContextCallback;->setTextBeforeCursor(Ljava/lang/CharSequence;I)V
 HSPLcom/android/internal/view/IInputMethod$Stub$Proxy;->asBinder()Landroid/os/IBinder;
-HSPLcom/android/internal/view/IInputMethod$Stub$Proxy;->attachToken(Landroid/os/IBinder;)V
 HSPLcom/android/internal/view/IInputMethod$Stub;-><init>()V
 HSPLcom/android/internal/view/IInputMethod$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/view/IInputMethod;
 HSPLcom/android/internal/view/IInputMethod$Stub;->onTransact(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z
-HSPLcom/android/internal/view/IInputMethod;->attachToken(Landroid/os/IBinder;)V
 HSPLcom/android/internal/view/IInputMethod;->bindInput(Landroid/view/inputmethod/InputBinding;)V
 HSPLcom/android/internal/view/IInputMethod;->changeInputMethodSubtype(Landroid/view/inputmethod/InputMethodSubtype;)V
 HSPLcom/android/internal/view/IInputMethod;->createSession(Landroid/view/InputChannel;Lcom/android/internal/view/IInputSessionCallback;)V
@@ -51619,6 +51615,7 @@
 HSPLlibcore/io/IoUtils$FileReader;-><init>(Ljava/lang/String;)V
 HSPLlibcore/io/IoUtils$FileReader;->readFully()Llibcore/io/IoUtils$FileReader;
 HSPLlibcore/io/IoUtils$FileReader;->toByteArray()[B
+HSPLlibcore/io/IoUtils;->acquireRawFd(Ljava/io/FileDescriptor;)I
 HSPLlibcore/io/IoUtils;->canOpenReadOnly(Ljava/lang/String;)Z
 HSPLlibcore/io/IoUtils;->close(Ljava/io/FileDescriptor;)V
 HSPLlibcore/io/IoUtils;->closeQuietly(Ljava/io/FileDescriptor;)V
@@ -51626,6 +51623,7 @@
 HSPLlibcore/io/IoUtils;->readFileAsByteArray(Ljava/lang/String;)[B
 HSPLlibcore/io/IoUtils;->readFileAsString(Ljava/lang/String;)Ljava/lang/String;
 HSPLlibcore/io/IoUtils;->setBlocking(Ljava/io/FileDescriptor;Z)V
+HSPLlibcore/io/IoUtils;->setFdOwner(Ljava/io/FileDescriptor;Ljava/lang/Object;)V
 HSPLlibcore/io/Linux;->read(Ljava/io/FileDescriptor;[BII)I
 HSPLlibcore/io/Linux;->recvfrom(Ljava/io/FileDescriptor;[BIIILjava/net/InetSocketAddress;)I
 HSPLlibcore/io/Linux;->sendto(Ljava/io/FileDescriptor;[BIIILjava/net/InetAddress;I)I
diff --git a/config/hiddenapi-light-greylist.txt b/config/hiddenapi-light-greylist.txt
index a4f13a0..5d37c5f 100644
--- a/config/hiddenapi-light-greylist.txt
+++ b/config/hiddenapi-light-greylist.txt
@@ -728,8 +728,6 @@
 Landroid/os/Environment;->buildExternalStorageAppObbDirs(Ljava/lang/String;)[Ljava/io/File;
 Landroid/os/Environment;->getDataSystemDirectory()Ljava/io/File;
 Landroid/os/Environment;->getLegacyExternalStorageObbDirectory()Ljava/io/File;
-Landroid/os/Environment;->getOemDirectory()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;
 Landroid/os/Environment;->sCurrentUser:Landroid/os/Environment$UserEnvironment;
@@ -1001,8 +999,6 @@
 Landroid/os/UserHandle;->AID_CACHE_GID_START:I
 Landroid/os/UserHandle;->AID_ROOT:I
 Landroid/os/UserHandle;->AID_SHARED_GID_START:I
-Landroid/os/UserHandle;->ALL:Landroid/os/UserHandle;
-Landroid/os/UserHandle;->CURRENT:Landroid/os/UserHandle;
 Landroid/os/UserHandle;->CURRENT_OR_SELF:Landroid/os/UserHandle;
 Landroid/os/UserHandle;->ERR_GID:I
 Landroid/os/UserHandle;->formatUid(Ljava/io/PrintWriter;I)V
diff --git a/config/hiddenapi-p-light-greylist.txt b/config/hiddenapi-p-light-greylist.txt
deleted file mode 100644
index e26a4c7..0000000
--- a/config/hiddenapi-p-light-greylist.txt
+++ /dev/null
@@ -1,5992 +0,0 @@
-Landroid/R$styleable;->ActionBar:[I
-Landroid/R$styleable;->ActionBar_background:I
-Landroid/R$styleable;->ActionBar_backgroundSplit:I
-Landroid/R$styleable;->ActionBar_backgroundStacked:I
-Landroid/R$styleable;->ActionBar_divider:I
-Landroid/R$styleable;->ActionBar_itemPadding:I
-Landroid/R$styleable;->CalendarView:[I
-Landroid/R$styleable;->CalendarView_dateTextAppearance:I
-Landroid/R$styleable;->CalendarView_firstDayOfWeek:I
-Landroid/R$styleable;->CalendarView_focusedMonthDateColor:I
-Landroid/R$styleable;->CalendarView_selectedDateVerticalBar:I
-Landroid/R$styleable;->CalendarView_selectedWeekBackgroundColor:I
-Landroid/R$styleable;->CalendarView_showWeekNumber:I
-Landroid/R$styleable;->CalendarView_shownWeekCount:I
-Landroid/R$styleable;->CalendarView_unfocusedMonthDateColor:I
-Landroid/R$styleable;->CalendarView_weekDayTextAppearance:I
-Landroid/R$styleable;->CalendarView_weekNumberColor:I
-Landroid/R$styleable;->CalendarView_weekSeparatorLineColor:I
-Landroid/R$styleable;->CheckBoxPreference:[I
-Landroid/R$styleable;->CheckedTextView:[I
-Landroid/R$styleable;->CheckedTextView_checkMark:I
-Landroid/R$styleable;->CompoundButton:[I
-Landroid/R$styleable;->CompoundButton_button:I
-Landroid/R$styleable;->DrawableStates:[I
-Landroid/R$styleable;->ImageView:[I
-Landroid/R$styleable;->ImageView_adjustViewBounds:I
-Landroid/R$styleable;->ImageView_baselineAlignBottom:I
-Landroid/R$styleable;->ImageView_cropToPadding:I
-Landroid/R$styleable;->ImageView_maxHeight:I
-Landroid/R$styleable;->ImageView_maxWidth:I
-Landroid/R$styleable;->ImageView_scaleType:I
-Landroid/R$styleable;->ImageView_src:I
-Landroid/R$styleable;->ImageView_tint:I
-Landroid/R$styleable;->LinearLayout:[I
-Landroid/R$styleable;->LinearLayout_divider:I
-Landroid/R$styleable;->LinearLayout_dividerPadding:I
-Landroid/R$styleable;->LinearLayout_showDividers:I
-Landroid/R$styleable;->ListView:[I
-Landroid/R$styleable;->ListView_divider:I
-Landroid/R$styleable;->ListView_dividerHeight:I
-Landroid/R$styleable;->ProgressBar:[I
-Landroid/R$styleable;->ProgressBar_indeterminateDrawable:I
-Landroid/R$styleable;->ProgressBar_indeterminateDuration:I
-Landroid/R$styleable;->ProgressBar_maxHeight:I
-Landroid/R$styleable;->ProgressBar_maxWidth:I
-Landroid/R$styleable;->ProgressBar_minHeight:I
-Landroid/R$styleable;->ProgressBar_minWidth:I
-Landroid/R$styleable;->ProgressBar_progressDrawable:I
-Landroid/R$styleable;->SeekBar:[I
-Landroid/R$styleable;->SeekBar_thumb:I
-Landroid/R$styleable;->SeekBar_thumbOffset:I
-Landroid/R$styleable;->Switch:[I
-Landroid/R$styleable;->Switch_showText:I
-Landroid/R$styleable;->Switch_splitTrack:I
-Landroid/R$styleable;->Switch_switchMinWidth:I
-Landroid/R$styleable;->Switch_switchPadding:I
-Landroid/R$styleable;->Switch_switchTextAppearance:I
-Landroid/R$styleable;->Switch_textOff:I
-Landroid/R$styleable;->Switch_textOn:I
-Landroid/R$styleable;->Switch_thumb:I
-Landroid/R$styleable;->Switch_thumbTextPadding:I
-Landroid/R$styleable;->Switch_track:I
-Landroid/R$styleable;->TextAppearance:[I
-Landroid/R$styleable;->TextAppearance_textAllCaps:I
-Landroid/R$styleable;->TextAppearance_textColor:I
-Landroid/R$styleable;->TextAppearance_textColorHighlight:I
-Landroid/R$styleable;->TextAppearance_textColorHint:I
-Landroid/R$styleable;->TextAppearance_textColorLink:I
-Landroid/R$styleable;->TextAppearance_textSize:I
-Landroid/R$styleable;->TextAppearance_textStyle:I
-Landroid/R$styleable;->TextAppearance_typeface:I
-Landroid/R$styleable;->TextView:[I
-Landroid/R$styleable;->TextView_autoLink:I
-Landroid/R$styleable;->TextView_autoText:I
-Landroid/R$styleable;->TextView_bufferType:I
-Landroid/R$styleable;->TextView_capitalize:I
-Landroid/R$styleable;->TextView_cursorVisible:I
-Landroid/R$styleable;->TextView_digits:I
-Landroid/R$styleable;->TextView_drawableBottom:I
-Landroid/R$styleable;->TextView_drawableEnd:I
-Landroid/R$styleable;->TextView_drawableLeft:I
-Landroid/R$styleable;->TextView_drawablePadding:I
-Landroid/R$styleable;->TextView_drawableRight:I
-Landroid/R$styleable;->TextView_drawableStart:I
-Landroid/R$styleable;->TextView_drawableTop:I
-Landroid/R$styleable;->TextView_editable:I
-Landroid/R$styleable;->TextView_ellipsize:I
-Landroid/R$styleable;->TextView_ems:I
-Landroid/R$styleable;->TextView_enabled:I
-Landroid/R$styleable;->TextView_freezesText:I
-Landroid/R$styleable;->TextView_gravity:I
-Landroid/R$styleable;->TextView_height:I
-Landroid/R$styleable;->TextView_hint:I
-Landroid/R$styleable;->TextView_imeActionId:I
-Landroid/R$styleable;->TextView_imeActionLabel:I
-Landroid/R$styleable;->TextView_imeOptions:I
-Landroid/R$styleable;->TextView_includeFontPadding:I
-Landroid/R$styleable;->TextView_inputMethod:I
-Landroid/R$styleable;->TextView_inputType:I
-Landroid/R$styleable;->TextView_lineSpacingExtra:I
-Landroid/R$styleable;->TextView_lineSpacingMultiplier:I
-Landroid/R$styleable;->TextView_lines:I
-Landroid/R$styleable;->TextView_linksClickable:I
-Landroid/R$styleable;->TextView_marqueeRepeatLimit:I
-Landroid/R$styleable;->TextView_maxEms:I
-Landroid/R$styleable;->TextView_maxHeight:I
-Landroid/R$styleable;->TextView_maxLength:I
-Landroid/R$styleable;->TextView_maxLines:I
-Landroid/R$styleable;->TextView_maxWidth:I
-Landroid/R$styleable;->TextView_minEms:I
-Landroid/R$styleable;->TextView_minHeight:I
-Landroid/R$styleable;->TextView_minLines:I
-Landroid/R$styleable;->TextView_minWidth:I
-Landroid/R$styleable;->TextView_numeric:I
-Landroid/R$styleable;->TextView_password:I
-Landroid/R$styleable;->TextView_phoneNumber:I
-Landroid/R$styleable;->TextView_privateImeOptions:I
-Landroid/R$styleable;->TextView_scrollHorizontally:I
-Landroid/R$styleable;->TextView_selectAllOnFocus:I
-Landroid/R$styleable;->TextView_shadowColor:I
-Landroid/R$styleable;->TextView_shadowDx:I
-Landroid/R$styleable;->TextView_shadowDy:I
-Landroid/R$styleable;->TextView_shadowRadius:I
-Landroid/R$styleable;->TextView_singleLine:I
-Landroid/R$styleable;->TextView_text:I
-Landroid/R$styleable;->TextView_textAllCaps:I
-Landroid/R$styleable;->TextView_textAppearance:I
-Landroid/R$styleable;->TextView_textColor:I
-Landroid/R$styleable;->TextView_textColorHighlight:I
-Landroid/R$styleable;->TextView_textColorHint:I
-Landroid/R$styleable;->TextView_textColorLink:I
-Landroid/R$styleable;->TextView_textCursorDrawable:I
-Landroid/R$styleable;->TextView_textIsSelectable:I
-Landroid/R$styleable;->TextView_textScaleX:I
-Landroid/R$styleable;->TextView_textSelectHandle:I
-Landroid/R$styleable;->TextView_textSelectHandleLeft:I
-Landroid/R$styleable;->TextView_textSelectHandleRight:I
-Landroid/R$styleable;->TextView_textSize:I
-Landroid/R$styleable;->TextView_textStyle:I
-Landroid/R$styleable;->TextView_typeface:I
-Landroid/R$styleable;->TextView_width:I
-Landroid/R$styleable;->View:[I
-Landroid/R$styleable;->ViewDrawableStates:[I
-Landroid/R$styleable;->ViewGroup_Layout:[I
-Landroid/R$styleable;->ViewGroup_MarginLayout:[I
-Landroid/R$styleable;->View_background:I
-Landroid/R$styleable;->View_clickable:I
-Landroid/R$styleable;->View_contentDescription:I
-Landroid/R$styleable;->View_drawingCacheQuality:I
-Landroid/R$styleable;->View_duplicateParentState:I
-Landroid/R$styleable;->View_fadingEdge:I
-Landroid/R$styleable;->View_filterTouchesWhenObscured:I
-Landroid/R$styleable;->View_fitsSystemWindows:I
-Landroid/R$styleable;->View_focusable:I
-Landroid/R$styleable;->View_focusableInTouchMode:I
-Landroid/R$styleable;->View_hapticFeedbackEnabled:I
-Landroid/R$styleable;->View_id:I
-Landroid/R$styleable;->View_isScrollContainer:I
-Landroid/R$styleable;->View_keepScreenOn:I
-Landroid/R$styleable;->View_longClickable:I
-Landroid/R$styleable;->View_minHeight:I
-Landroid/R$styleable;->View_minWidth:I
-Landroid/R$styleable;->View_nextFocusDown:I
-Landroid/R$styleable;->View_nextFocusLeft:I
-Landroid/R$styleable;->View_nextFocusRight:I
-Landroid/R$styleable;->View_nextFocusUp:I
-Landroid/R$styleable;->View_onClick:I
-Landroid/R$styleable;->View_overScrollMode:I
-Landroid/R$styleable;->View_padding:I
-Landroid/R$styleable;->View_paddingBottom:I
-Landroid/R$styleable;->View_paddingEnd:I
-Landroid/R$styleable;->View_paddingLeft:I
-Landroid/R$styleable;->View_paddingRight:I
-Landroid/R$styleable;->View_paddingStart:I
-Landroid/R$styleable;->View_paddingTop:I
-Landroid/R$styleable;->View_saveEnabled:I
-Landroid/R$styleable;->View_scrollX:I
-Landroid/R$styleable;->View_scrollY:I
-Landroid/R$styleable;->View_scrollbarDefaultDelayBeforeFade:I
-Landroid/R$styleable;->View_scrollbarFadeDuration:I
-Landroid/R$styleable;->View_scrollbarSize:I
-Landroid/R$styleable;->View_scrollbarStyle:I
-Landroid/R$styleable;->View_scrollbarThumbHorizontal:I
-Landroid/R$styleable;->View_scrollbarThumbVertical:I
-Landroid/R$styleable;->View_scrollbarTrackHorizontal:I
-Landroid/R$styleable;->View_scrollbarTrackVertical:I
-Landroid/R$styleable;->View_scrollbars:I
-Landroid/R$styleable;->View_soundEffectsEnabled:I
-Landroid/R$styleable;->View_tag:I
-Landroid/R$styleable;->View_visibility:I
-Landroid/R$styleable;->Window:[I
-Landroid/R$styleable;->Window_windowBackground:I
-Landroid/R$styleable;->Window_windowFrame:I
-Landroid/accounts/AccountManager;-><init>(Landroid/content/Context;Landroid/accounts/IAccountManager;Landroid/os/Handler;)V
-Landroid/accounts/AccountManager;->mContext:Landroid/content/Context;
-Landroid/accounts/IAccountAuthenticator$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-Landroid/accounts/IAccountAuthenticator$Stub$Proxy;->mRemote:Landroid/os/IBinder;
-Landroid/accounts/IAccountAuthenticator$Stub;->asInterface(Landroid/os/IBinder;)Landroid/accounts/IAccountAuthenticator;
-Landroid/accounts/IAccountAuthenticator;->addAccount(Landroid/accounts/IAccountAuthenticatorResponse;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;Landroid/os/Bundle;)V
-Landroid/accounts/IAccountAuthenticator;->confirmCredentials(Landroid/accounts/IAccountAuthenticatorResponse;Landroid/accounts/Account;Landroid/os/Bundle;)V
-Landroid/accounts/IAccountAuthenticator;->editProperties(Landroid/accounts/IAccountAuthenticatorResponse;Ljava/lang/String;)V
-Landroid/accounts/IAccountAuthenticator;->getAccountRemovalAllowed(Landroid/accounts/IAccountAuthenticatorResponse;Landroid/accounts/Account;)V
-Landroid/accounts/IAccountAuthenticator;->getAuthToken(Landroid/accounts/IAccountAuthenticatorResponse;Landroid/accounts/Account;Ljava/lang/String;Landroid/os/Bundle;)V
-Landroid/accounts/IAccountAuthenticator;->getAuthTokenLabel(Landroid/accounts/IAccountAuthenticatorResponse;Ljava/lang/String;)V
-Landroid/accounts/IAccountAuthenticator;->hasFeatures(Landroid/accounts/IAccountAuthenticatorResponse;Landroid/accounts/Account;[Ljava/lang/String;)V
-Landroid/accounts/IAccountAuthenticator;->updateCredentials(Landroid/accounts/IAccountAuthenticatorResponse;Landroid/accounts/Account;Ljava/lang/String;Landroid/os/Bundle;)V
-Landroid/accounts/IAccountAuthenticatorResponse$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-Landroid/accounts/IAccountAuthenticatorResponse$Stub$Proxy;->mRemote:Landroid/os/IBinder;
-Landroid/accounts/IAccountAuthenticatorResponse$Stub;-><init>()V
-Landroid/accounts/IAccountAuthenticatorResponse$Stub;->asInterface(Landroid/os/IBinder;)Landroid/accounts/IAccountAuthenticatorResponse;
-Landroid/accounts/IAccountManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-Landroid/accounts/IAccountManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/accounts/IAccountManager;
-Landroid/accounts/IAccountManagerResponse$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-Landroid/accounts/IAccountManagerResponse$Stub$Proxy;->mRemote:Landroid/os/IBinder;
-Landroid/accounts/IAccountManagerResponse$Stub;-><init>()V
-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/LayoutTransition;->cancel()V
-Landroid/animation/LayoutTransition;->cancel(I)V
-Landroid/animation/ValueAnimator;->animateValue(F)V
-Landroid/animation/ValueAnimator;->sDurationScale:F
-Landroid/app/ActionBar;->setShowHideAnimationEnabled(Z)V
-Landroid/app/Activity;->enterPictureInPictureMode(Landroid/app/PictureInPictureArgs;)Z
-Landroid/app/Activity;->getActivityOptions()Landroid/app/ActivityOptions;
-Landroid/app/Activity;->getActivityToken()Landroid/os/IBinder;
-Landroid/app/Activity;->mActivityInfo:Landroid/content/pm/ActivityInfo;
-Landroid/app/Activity;->mApplication:Landroid/app/Application;
-Landroid/app/Activity;->mComponent:Landroid/content/ComponentName;
-Landroid/app/Activity;->mFinished:Z
-Landroid/app/Activity;->mFragments:Landroid/app/FragmentController;
-Landroid/app/Activity;->mHandler:Landroid/os/Handler;
-Landroid/app/Activity;->mInstrumentation:Landroid/app/Instrumentation;
-Landroid/app/Activity;->mMainThread:Landroid/app/ActivityThread;
-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;->mToken:Landroid/os/IBinder;
-Landroid/app/Activity;->mWindow:Landroid/view/Window;
-Landroid/app/Activity;->mWindowManager:Landroid/view/WindowManager;
-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/Activity;->setDisablePreviewScreenshots(Z)V
-Landroid/app/Activity;->setPersistent(Z)V
-Landroid/app/Activity;->setPictureInPictureArgs(Landroid/app/PictureInPictureArgs;)V
-Landroid/app/ActivityGroup;->mLocalActivityManager:Landroid/app/LocalActivityManager;
-Landroid/app/ActivityManager$RecentTaskInfo;->configuration:Landroid/content/res/Configuration;
-Landroid/app/ActivityManager$RecentTaskInfo;->firstActiveTime:J
-Landroid/app/ActivityManager$RecentTaskInfo;->lastActiveTime:J
-Landroid/app/ActivityManager$RecentTaskInfo;->resizeMode:I
-Landroid/app/ActivityManager$RecentTaskInfo;->supportsSplitScreenMultiWindow:Z
-Landroid/app/ActivityManager$RecentTaskInfo;->userId:I
-Landroid/app/ActivityManager$RunningAppProcessInfo;->flags:I
-Landroid/app/ActivityManager$RunningAppProcessInfo;->processState:I
-Landroid/app/ActivityManager$TaskDescription;->getBackgroundColor()I
-Landroid/app/ActivityManager$TaskDescription;->getInMemoryIcon()Landroid/graphics/Bitmap;
-Landroid/app/ActivityManager$TaskDescription;->loadTaskDescriptionIcon(Ljava/lang/String;I)Landroid/graphics/Bitmap;
-Landroid/app/ActivityManager$TaskSnapshot;->getContentInsets()Landroid/graphics/Rect;
-Landroid/app/ActivityManager$TaskSnapshot;->getOrientation()I
-Landroid/app/ActivityManager$TaskSnapshot;->getScale()F
-Landroid/app/ActivityManager$TaskSnapshot;->getSnapshot()Landroid/graphics/GraphicBuffer;
-Landroid/app/ActivityManager$TaskSnapshot;->isRealSnapshot()Z
-Landroid/app/ActivityManager$TaskSnapshot;->isReducedResolution()Z
-Landroid/app/ActivityManager;->IActivityManagerSingleton:Landroid/util/Singleton;
-Landroid/app/ActivityManager;->PROCESS_STATE_IMPORTANT_BACKGROUND:I
-Landroid/app/ActivityManager;->PROCESS_STATE_TOP:I
-Landroid/app/ActivityManager;->clearApplicationUserData(Ljava/lang/String;Landroid/content/pm/IPackageDataObserver;)Z
-Landroid/app/ActivityManager;->getMaxNumPictureInPictureActions()I
-Landroid/app/ActivityManager;->getMaxRecentTasksStatic()I
-Landroid/app/ActivityManager;->getService()Landroid/app/IActivityManager;
-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;->setPersistentVrThread(I)V
-Landroid/app/ActivityManagerNative;->asInterface(Landroid/os/IBinder;)Landroid/app/IActivityManager;
-Landroid/app/ActivityManagerNative;->broadcastStickyIntent(Landroid/content/Intent;Ljava/lang/String;I)V
-Landroid/app/ActivityManagerNative;->getDefault()Landroid/app/IActivityManager;
-Landroid/app/ActivityOptions;->makeMultiThumbFutureAspectScaleAnimation(Landroid/content/Context;Landroid/os/Handler;Landroid/view/IAppTransitionAnimationSpecsFuture;Landroid/app/ActivityOptions$OnAnimationStartedListener;Z)Landroid/app/ActivityOptions;
-Landroid/app/ActivityOptions;->makeRemoteAnimation(Landroid/view/RemoteAnimationAdapter;)Landroid/app/ActivityOptions;
-Landroid/app/ActivityOptions;->setSplitScreenCreateMode(I)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;->appInfo:Landroid/content/pm/ApplicationInfo;
-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;->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;->getPackageInfo(Landroid/content/pm/ApplicationInfo;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;->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;->mActivities:Landroid/util/ArrayMap;
-Landroid/app/ActivityThread;->mAllApplications:Ljava/util/ArrayList;
-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;->mLocalProviders:Landroid/util/ArrayMap;
-Landroid/app/ActivityThread;->mLocalProvidersByName:Landroid/util/ArrayMap;
-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;->mResourcePackages:Landroid/util/ArrayMap;
-Landroid/app/ActivityThread;->mResourcesManager:Landroid/app/ResourcesManager;
-Landroid/app/ActivityThread;->mServices:Landroid/util/ArrayMap;
-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;->sCurrentActivityThread:Landroid/app/ActivityThread;
-Landroid/app/ActivityThread;->sPackageManager:Landroid/content/pm/IPackageManager;
-Landroid/app/ActivityThread;->sendActivityResult(Landroid/os/IBinder;Ljava/lang/String;IILandroid/content/Intent;)V
-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/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/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;->WINDOW_EXACT:J
-Landroid/app/AlarmManager;->WINDOW_HEURISTIC:J
-Landroid/app/AlarmManager;->mService:Landroid/app/IAlarmManager;
-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/AppOpsManager$OpEntry;->getDuration()I
-Landroid/app/AppOpsManager$OpEntry;->getOp()I
-Landroid/app/AppOpsManager$OpEntry;->getRejectTime()J
-Landroid/app/AppOpsManager$OpEntry;->getTime()J
-Landroid/app/AppOpsManager;->OP_AUDIO_NOTIFICATION_VOLUME:I
-Landroid/app/AppOpsManager;->OP_COARSE_LOCATION:I
-Landroid/app/AppOpsManager;->OP_FINE_LOCATION:I
-Landroid/app/AppOpsManager;->OP_GET_USAGE_STATS:I
-Landroid/app/AppOpsManager;->OP_POST_NOTIFICATION:I
-Landroid/app/AppOpsManager;->OP_PROJECT_MEDIA:I
-Landroid/app/AppOpsManager;->OP_READ_CONTACTS:I
-Landroid/app/AppOpsManager;->OP_READ_PHONE_STATE:I
-Landroid/app/AppOpsManager;->OP_READ_SMS:I
-Landroid/app/AppOpsManager;->OP_RUN_IN_BACKGROUND:I
-Landroid/app/AppOpsManager;->OP_VIBRATE:I
-Landroid/app/AppOpsManager;->OP_WIFI_SCAN:I
-Landroid/app/AppOpsManager;->OP_WRITE_CONTACTS:I
-Landroid/app/AppOpsManager;->OP_WRITE_SMS:I
-Landroid/app/AppOpsManager;->checkOp(IILjava/lang/String;)I
-Landroid/app/AppOpsManager;->checkOpNoThrow(IILjava/lang/String;)I
-Landroid/app/AppOpsManager;->getOpsForPackage(ILjava/lang/String;[I)Ljava/util/List;
-Landroid/app/AppOpsManager;->getPackagesForOps([I)Ljava/util/List;
-Landroid/app/AppOpsManager;->getToken(Lcom/android/internal/app/IAppOpsService;)Landroid/os/IBinder;
-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;->permissionToOpCode(Ljava/lang/String;)I
-Landroid/app/AppOpsManager;->sOpPerms:[Ljava/lang/String;
-Landroid/app/AppOpsManager;->setRestriction(III[Ljava/lang/String;)V
-Landroid/app/AppOpsManager;->strOpToOp(Ljava/lang/String;)I
-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;->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;->setInstantAppCookie([B)Z
-Landroid/app/ApplicationPackageManager;->shouldShowRequestPermissionRationale(Ljava/lang/String;)Z
-Landroid/app/ContentProviderHolder;-><init>(Landroid/content/pm/ProviderInfo;)V
-Landroid/app/ContentProviderHolder;->info:Landroid/content/pm/ProviderInfo;
-Landroid/app/ContentProviderHolder;->provider:Landroid/content/IContentProvider;
-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;->getActivityToken()Landroid/os/IBinder;
-Landroid/app/ContextImpl;->getDisplay()Landroid/view/Display;
-Landroid/app/ContextImpl;->getPreferencesDir()Ljava/io/File;
-Landroid/app/ContextImpl;->getReceiverRestrictedContext()Landroid/content/Context;
-Landroid/app/ContextImpl;->getSharedPreferences(Ljava/io/File;I)Landroid/content/SharedPreferences;
-Landroid/app/ContextImpl;->getSharedPreferencesPath(Ljava/lang/String;)Ljava/io/File;
-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;->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;->mResources:Landroid/content/res/Resources;
-Landroid/app/ContextImpl;->mServiceCache:[Ljava/lang/Object;
-Landroid/app/ContextImpl;->mTheme:Landroid/content/res/Resources$Theme;
-Landroid/app/ContextImpl;->mThemeResource:I
-Landroid/app/ContextImpl;->sSharedPrefsCache:Landroid/util/ArrayMap;
-Landroid/app/ContextImpl;->scheduleFinalCleanup(Ljava/lang/String;Ljava/lang/String;)V
-Landroid/app/ContextImpl;->setOuterContext(Landroid/content/Context;)V
-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;->mDismissMessage:Landroid/os/Message;
-Landroid/app/Dialog;->mListenersHandler:Landroid/os/Handler;
-Landroid/app/Dialog;->mOwnerActivity:Landroid/app/Activity;
-Landroid/app/Dialog;->mShowMessage:Landroid/os/Message;
-Landroid/app/DialogFragment;->showAllowingStateLoss(Landroid/app/FragmentManager;Ljava/lang/String;)V
-Landroid/app/DownloadManager$Request;->mUri:Landroid/net/Uri;
-Landroid/app/DownloadManager;->setAccessFilename(Z)V
-Landroid/app/Fragment;->mChildFragmentManager:Landroid/app/FragmentManagerImpl;
-Landroid/app/Fragment;->mWho:Ljava/lang/String;
-Landroid/app/FragmentManagerImpl;->mAdded:Ljava/util/ArrayList;
-Landroid/app/FragmentManagerImpl;->mStateSaved:Z
-Landroid/app/FragmentManagerImpl;->noteStateNotSaved()V
-Landroid/app/IActivityController$Stub;-><init>()V
-Landroid/app/IActivityManager$Stub$Proxy;->getConfiguration()Landroid/content/res/Configuration;
-Landroid/app/IActivityManager$Stub$Proxy;->getLaunchedFromUid(Landroid/os/IBinder;)I
-Landroid/app/IActivityManager$Stub$Proxy;->getProcessLimit()I
-Landroid/app/IActivityManager$Stub$Proxy;->getProcessPss([I)[J
-Landroid/app/IActivityManager$Stub$Proxy;->isAppForeground(I)Z
-Landroid/app/IActivityManager$Stub$Proxy;->mRemote:Landroid/os/IBinder;
-Landroid/app/IActivityManager;->bindService(Landroid/app/IApplicationThread;Landroid/os/IBinder;Landroid/content/Intent;Ljava/lang/String;Landroid/app/IServiceConnection;ILjava/lang/String;I)I
-Landroid/app/IActivityManager;->broadcastIntent(Landroid/app/IApplicationThread;Landroid/content/Intent;Ljava/lang/String;Landroid/content/IIntentReceiver;ILjava/lang/String;Landroid/os/Bundle;[Ljava/lang/String;ILandroid/os/Bundle;ZZI)I
-Landroid/app/IActivityManager;->cancelRecentsAnimation(Z)V
-Landroid/app/IActivityManager;->cancelTaskWindowTransition(I)V
-Landroid/app/IActivityManager;->closeSystemDialogs(Ljava/lang/String;)V
-Landroid/app/IActivityManager;->finishActivity(Landroid/os/IBinder;ILandroid/content/Intent;I)Z
-Landroid/app/IActivityManager;->finishReceiver(Landroid/os/IBinder;ILjava/lang/String;Landroid/os/Bundle;ZI)V
-Landroid/app/IActivityManager;->forceStopPackage(Ljava/lang/String;I)V
-Landroid/app/IActivityManager;->getConfiguration()Landroid/content/res/Configuration;
-Landroid/app/IActivityManager;->getCurrentUser()Landroid/content/pm/UserInfo;
-Landroid/app/IActivityManager;->getFilteredTasks(III)Ljava/util/List;
-Landroid/app/IActivityManager;->getIntentSender(ILjava/lang/String;Landroid/os/IBinder;Ljava/lang/String;I[Landroid/content/Intent;[Ljava/lang/String;ILandroid/os/Bundle;I)Landroid/content/IIntentSender;
-Landroid/app/IActivityManager;->getLaunchedFromPackage(Landroid/os/IBinder;)Ljava/lang/String;
-Landroid/app/IActivityManager;->getLockTaskModeState()I
-Landroid/app/IActivityManager;->getProcessMemoryInfo([I)[Landroid/os/Debug$MemoryInfo;
-Landroid/app/IActivityManager;->getProviderMimeType(Landroid/net/Uri;I)Ljava/lang/String;
-Landroid/app/IActivityManager;->getRecentTasks(III)Landroid/content/pm/ParceledListSlice;
-Landroid/app/IActivityManager;->getRunningAppProcesses()Ljava/util/List;
-Landroid/app/IActivityManager;->getTaskForActivity(Landroid/os/IBinder;Z)I
-Landroid/app/IActivityManager;->getTaskSnapshot(IZ)Landroid/app/ActivityManager$TaskSnapshot;
-Landroid/app/IActivityManager;->moveActivityTaskToBack(Landroid/os/IBinder;Z)Z
-Landroid/app/IActivityManager;->moveTaskToFront(IILandroid/os/Bundle;)V
-Landroid/app/IActivityManager;->publishContentProviders(Landroid/app/IApplicationThread;Ljava/util/List;)V
-Landroid/app/IActivityManager;->registerTaskStackListener(Landroid/app/ITaskStackListener;)V
-Landroid/app/IActivityManager;->removeTask(I)Z
-Landroid/app/IActivityManager;->requestBugReport(I)V
-Landroid/app/IActivityManager;->resumeAppSwitches()V
-Landroid/app/IActivityManager;->setActivityController(Landroid/app/IActivityController;Z)V
-Landroid/app/IActivityManager;->setRequestedOrientation(Landroid/os/IBinder;I)V
-Landroid/app/IActivityManager;->setTaskResizeable(II)V
-Landroid/app/IActivityManager;->startActivity(Landroid/app/IApplicationThread;Ljava/lang/String;Landroid/content/Intent;Ljava/lang/String;Landroid/os/IBinder;Ljava/lang/String;IILandroid/app/ProfilerInfo;Landroid/os/Bundle;)I
-Landroid/app/IActivityManager;->startActivityAsUser(Landroid/app/IApplicationThread;Ljava/lang/String;Landroid/content/Intent;Ljava/lang/String;Landroid/os/IBinder;Ljava/lang/String;IILandroid/app/ProfilerInfo;Landroid/os/Bundle;I)I
-Landroid/app/IActivityManager;->startActivityFromRecents(ILandroid/os/Bundle;)I
-Landroid/app/IActivityManager;->startRecentsActivity(Landroid/content/Intent;Landroid/app/IAssistDataReceiver;Landroid/view/IRecentsAnimationRunner;)V
-Landroid/app/IActivityManager;->stopService(Landroid/app/IApplicationThread;Landroid/content/Intent;Ljava/lang/String;I)I
-Landroid/app/IActivityManager;->unbindService(Landroid/app/IServiceConnection;)Z
-Landroid/app/IActivityManager;->unstableProviderDied(Landroid/os/IBinder;)V
-Landroid/app/IAlarmManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-Landroid/app/IAlarmManager$Stub;->TRANSACTION_remove:I
-Landroid/app/IAlarmManager$Stub;->TRANSACTION_set:I
-Landroid/app/IAlarmManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/app/IAlarmManager;
-Landroid/app/IAlarmManager;->setTime(J)Z
-Landroid/app/IAppTask;->getTaskInfo()Landroid/app/ActivityManager$RecentTaskInfo;
-Landroid/app/IApplicationThread;->scheduleTrimMemory(I)V
-Landroid/app/IAssistDataReceiver$Stub;-><init>()V
-Landroid/app/IAssistDataReceiver;->onHandleAssistData(Landroid/os/Bundle;)V
-Landroid/app/IAssistDataReceiver;->onHandleAssistScreenshot(Landroid/graphics/Bitmap;)V
-Landroid/app/INotificationManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-Landroid/app/INotificationManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/app/INotificationManager;
-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;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;
-Landroid/app/ISearchManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/app/ISearchManager;
-Landroid/app/IServiceConnection$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-Landroid/app/IServiceConnection$Stub$Proxy;->mRemote:Landroid/os/IBinder;
-Landroid/app/IServiceConnection$Stub;-><init>()V
-Landroid/app/IServiceConnection$Stub;->asInterface(Landroid/os/IBinder;)Landroid/app/IServiceConnection;
-Landroid/app/IStopUserCallback$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-Landroid/app/IStopUserCallback$Stub$Proxy;->mRemote:Landroid/os/IBinder;
-Landroid/app/IStopUserCallback$Stub;-><init>()V
-Landroid/app/IStopUserCallback;->userStopped(I)V
-Landroid/app/IUiModeManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-Landroid/app/IWallpaperManager;->getWallpaper(Ljava/lang/String;Landroid/app/IWallpaperManagerCallback;ILandroid/os/Bundle;I)Landroid/os/ParcelFileDescriptor;
-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;->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/IntentService;->mServiceHandler:Landroid/app/IntentService$ServiceHandler;
-Landroid/app/KeyguardManager;->dismissKeyguard(Landroid/app/Activity;Landroid/app/KeyguardManager$KeyguardDismissCallback;Landroid/os/Handler;)V
-Landroid/app/KeyguardManager;->isDeviceLocked(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;->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;->getResources()Landroid/content/res/Resources;
-Landroid/app/LoadedApk;->mActivityThread:Landroid/app/ActivityThread;
-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;->makeApplication(ZLandroid/app/Instrumentation;)Landroid/app/Application;
-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;->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;->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;->mActions:Ljava/util/ArrayList;
-Landroid/app/Notification$Builder;->makePublicContentView()Landroid/widget/RemoteViews;
-Landroid/app/Notification$Builder;->setChannel(Ljava/lang/String;)Landroid/app/Notification$Builder;
-Landroid/app/Notification$Builder;->setTimeout(J)Landroid/app/Notification$Builder;
-Landroid/app/Notification$TvExtender;->getChannel()Ljava/lang/String;
-Landroid/app/Notification;-><init>(Landroid/content/Context;ILjava/lang/CharSequence;JLjava/lang/CharSequence;Ljava/lang/CharSequence;Landroid/content/Intent;)V
-Landroid/app/Notification;->getChannel()Ljava/lang/String;
-Landroid/app/Notification;->getNotificationStyleClass(Ljava/lang/String;)Ljava/lang/Class;
-Landroid/app/Notification;->getTimeout()J
-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;->setLatestEventInfo(Landroid/content/Context;Ljava/lang/CharSequence;Ljava/lang/CharSequence;Landroid/app/PendingIntent;)V
-Landroid/app/Notification;->setSmallIcon(Landroid/graphics/drawable/Icon;)V
-Landroid/app/NotificationManager;->cancelAsUser(Ljava/lang/String;ILandroid/os/UserHandle;)V
-Landroid/app/NotificationManager;->getService()Landroid/app/INotificationManager;
-Landroid/app/NotificationManager;->notifyAsUser(Ljava/lang/String;ILandroid/app/Notification;Landroid/os/UserHandle;)V
-Landroid/app/NotificationManager;->sService:Landroid/app/INotificationManager;
-Landroid/app/PendingIntent;->getActivityAsUser(Landroid/content/Context;ILandroid/content/Intent;ILandroid/os/Bundle;Landroid/os/UserHandle;)Landroid/app/PendingIntent;
-Landroid/app/PendingIntent;->getIntent()Landroid/content/Intent;
-Landroid/app/PendingIntent;->isActivity()Z
-Landroid/app/PictureInPictureArgs$Builder;
-Landroid/app/PictureInPictureArgs$Builder;-><init>()V
-Landroid/app/PictureInPictureArgs$Builder;->build()Landroid/app/PictureInPictureArgs;
-Landroid/app/PictureInPictureArgs$Builder;->setActions(Ljava/util/List;)Landroid/app/PictureInPictureArgs$Builder;
-Landroid/app/PictureInPictureArgs$Builder;->setAspectRatio(Landroid/util/Rational;)Landroid/app/PictureInPictureArgs$Builder;
-Landroid/app/PictureInPictureArgs$Builder;->setSourceRectHint(Landroid/graphics/Rect;)Landroid/app/PictureInPictureArgs$Builder;
-Landroid/app/PictureInPictureArgs;
-Landroid/app/PictureInPictureArgs;->CREATOR:Landroid/os/Parcelable$Creator;
-Landroid/app/PictureInPictureArgs;->convert(Landroid/app/PictureInPictureArgs;)Landroid/app/PictureInPictureParams;
-Landroid/app/PictureInPictureArgs;->convert(Landroid/app/PictureInPictureParams;)Landroid/app/PictureInPictureArgs;
-Landroid/app/PictureInPictureParams;->getAspectRatio()F
-Landroid/app/Presentation;->createPresentationContext(Landroid/content/Context;Landroid/view/Display;I)Landroid/content/Context;
-Landroid/app/ProgressDialog;->mProgressNumber:Landroid/widget/TextView;
-Landroid/app/QueuedWork;->addFinisher(Ljava/lang/Runnable;)V
-Landroid/app/QueuedWork;->removeFinisher(Ljava/lang/Runnable;)V
-Landroid/app/QueuedWork;->sFinishers:Ljava/util/LinkedList;
-Landroid/app/ResourcesManager;->appendLibAssetForMainAssetPath(Ljava/lang/String;Ljava/lang/String;)V
-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;->mData:Landroid/content/Intent;
-Landroid/app/ResultInfo;->mResultWho:Ljava/lang/String;
-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/SharedPreferencesImpl;-><init>(Ljava/io/File;I)V
-Landroid/app/SharedPreferencesImpl;->mFile:Ljava/io/File;
-Landroid/app/SharedPreferencesImpl;->startReloadIfChangedUnexpectedly()V
-Landroid/app/StatusBarManager;->collapsePanels()V
-Landroid/app/StatusBarManager;->disable(I)V
-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;->removeIcon(Ljava/lang/String;)V
-Landroid/app/StatusBarManager;->setIcon(Ljava/lang/String;IILjava/lang/String;)V
-Landroid/app/TaskStackListener;-><init>()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/TimePickerDialog;->mTimePicker:Landroid/widget/TimePicker;
-Landroid/app/Vr2dDisplayProperties$Builder;-><init>()V
-Landroid/app/Vr2dDisplayProperties$Builder;->build()Landroid/app/Vr2dDisplayProperties;
-Landroid/app/Vr2dDisplayProperties$Builder;->setEnabled(Z)Landroid/app/Vr2dDisplayProperties$Builder;
-Landroid/app/Vr2dDisplayProperties;-><init>(III)V
-Landroid/app/VrManager;->getPersistentVrModeEnabled()Z
-Landroid/app/VrManager;->mService:Landroid/service/vr/IVrManager;
-Landroid/app/VrManager;->registerVrStateCallback(Landroid/app/VrStateCallback;Landroid/os/Handler;)V
-Landroid/app/VrManager;->setVr2dDisplayProperties(Landroid/app/Vr2dDisplayProperties;)V
-Landroid/app/VrManager;->unregisterVrStateCallback(Landroid/app/VrStateCallback;)V
-Landroid/app/VrStateCallback;-><init>()V
-Landroid/app/VrStateCallback;->onPersistentVrStateChanged(Z)V
-Landroid/app/WallpaperColors;-><init>(Landroid/graphics/Color;Landroid/graphics/Color;Landroid/graphics/Color;I)V
-Landroid/app/WallpaperColors;->getColorHints()I
-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;->openDefaultWallpaper(Landroid/content/Context;I)Ljava/io/InputStream;
-Landroid/app/WallpaperManager;->sGlobals:Landroid/app/WallpaperManager$Globals;
-Landroid/app/WallpaperManager;->setBitmap(Landroid/graphics/Bitmap;Landroid/graphics/Rect;ZII)I
-Landroid/app/admin/DevicePolicyManager;->createAndInitializeUser(Landroid/content/ComponentName;Ljava/lang/String;Ljava/lang/String;Landroid/content/ComponentName;Landroid/os/Bundle;)Landroid/os/UserHandle;
-Landroid/app/admin/DevicePolicyManager;->createUser(Landroid/content/ComponentName;Ljava/lang/String;)Landroid/os/UserHandle;
-Landroid/app/admin/DevicePolicyManager;->getDeviceInitializerApp()Ljava/lang/String;
-Landroid/app/admin/DevicePolicyManager;->getDeviceInitializerComponent()Landroid/content/ComponentName;
-Landroid/app/admin/DevicePolicyManager;->getMandatoryBackupTransport()Landroid/content/ComponentName;
-Landroid/app/admin/DevicePolicyManager;->getProfileOwnerAsUser(I)Landroid/content/ComponentName;
-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;->setActiveAdmin(Landroid/content/ComponentName;Z)V
-Landroid/app/admin/DevicePolicyManager;->setActiveAdmin(Landroid/content/ComponentName;ZI)V
-Landroid/app/admin/DevicePolicyManager;->setDefaultSmsApplication(Landroid/content/ComponentName;Ljava/lang/String;)V
-Landroid/app/admin/DevicePolicyManager;->throwIfParentInstance(Ljava/lang/String;)V
-Landroid/app/admin/IDevicePolicyManager$Stub;->TRANSACTION_packageHasActiveAdmins:I
-Landroid/app/admin/IDevicePolicyManager$Stub;->TRANSACTION_removeActiveAdmin:I
-Landroid/app/admin/IDevicePolicyManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/app/admin/IDevicePolicyManager;
-Landroid/app/admin/SecurityLog$SecurityEvent;-><init>([B)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/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;->mData:Landroid/app/backup/BackupDataOutput;
-Landroid/app/backup/IBackupManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/app/backup/IBackupManager;
-Landroid/app/job/IJobCallback$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-Landroid/app/job/IJobCallback$Stub$Proxy;->mRemote:Landroid/os/IBinder;
-Landroid/app/job/IJobCallback$Stub;-><init>()V
-Landroid/app/job/IJobCallback$Stub;->asInterface(Landroid/os/IBinder;)Landroid/app/job/IJobCallback;
-Landroid/app/job/IJobCallback;->acknowledgeStartMessage(IZ)V
-Landroid/app/job/IJobCallback;->acknowledgeStopMessage(IZ)V
-Landroid/app/job/IJobCallback;->jobFinished(IZ)V
-Landroid/app/job/IJobScheduler$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-Landroid/app/job/IJobScheduler$Stub;->asInterface(Landroid/os/IBinder;)Landroid/app/job/IJobScheduler;
-Landroid/app/job/IJobService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-Landroid/app/job/IJobService$Stub$Proxy;->mRemote:Landroid/os/IBinder;
-Landroid/app/job/IJobService$Stub;-><init>()V
-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;->setEstimatedNetworkBytes(J)Landroid/app/job/JobInfo$Builder;
-Landroid/app/job/JobInfo$Builder;->setIsPrefetch(Z)Landroid/app/job/JobInfo$Builder;
-Landroid/app/job/JobInfo;->flags:I
-Landroid/app/job/JobInfo;->getEstimatedNetworkBytes()J
-Landroid/app/job/JobInfo;->jobId:I
-Landroid/app/job/JobInfo;->service:Landroid/content/ComponentName;
-Landroid/app/job/JobParameters;->callback:Landroid/os/IBinder;
-Landroid/app/job/JobParameters;->jobId:I
-Landroid/app/job/JobWorkItem;-><init>(Landroid/content/Intent;J)V
-Landroid/app/job/JobWorkItem;->getEstimatedNetworkBytes()J
-Landroid/app/slice/Slice$Builder;-><init>(Landroid/net/Uri;)V
-Landroid/app/slice/Slice$Builder;->addTimestamp(JLjava/lang/String;Ljava/util/List;)Landroid/app/slice/Slice$Builder;
-Landroid/app/slice/Slice$Builder;->setSpec(Landroid/app/slice/SliceSpec;)Landroid/app/slice/Slice$Builder;
-Landroid/app/slice/Slice;->EXTRA_SLIDER_VALUE:Ljava/lang/String;
-Landroid/app/slice/Slice;->SUBTYPE_SLIDER:Ljava/lang/String;
-Landroid/app/slice/SliceItem;->FORMAT_TIMESTAMP:Ljava/lang/String;
-Landroid/app/slice/SliceItem;->getTimestamp()J
-Landroid/app/slice/SliceManager;->bindSlice(Landroid/content/Intent;Ljava/util/List;)Landroid/app/slice/Slice;
-Landroid/app/slice/SliceManager;->bindSlice(Landroid/net/Uri;Ljava/util/List;)Landroid/app/slice/Slice;
-Landroid/app/slice/SliceManager;->pinSlice(Landroid/net/Uri;Ljava/util/List;)V
-Landroid/app/slice/SliceProvider;->onBindSlice(Landroid/net/Uri;Ljava/util/List;)Landroid/app/slice/Slice;
-Landroid/app/trust/ITrustManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-Landroid/app/usage/StorageStats;->getCodeBytes()J
-Landroid/app/usage/StorageStatsManager;->getFreeBytes(Ljava/lang/String;)J
-Landroid/app/usage/StorageStatsManager;->getTotalBytes(Ljava/lang/String;)J
-Landroid/app/usage/StorageStatsManager;->isQuotaSupported(Ljava/lang/String;)Z
-Landroid/app/usage/StorageStatsManager;->queryExternalStatsForUser(Ljava/lang/String;Landroid/os/UserHandle;)Landroid/app/usage/ExternalStorageStats;
-Landroid/app/usage/StorageStatsManager;->queryStatsForPackage(Ljava/lang/String;Ljava/lang/String;Landroid/os/UserHandle;)Landroid/app/usage/StorageStats;
-Landroid/app/usage/StorageStatsManager;->queryStatsForUid(Ljava/lang/String;I)Landroid/app/usage/StorageStats;
-Landroid/app/usage/StorageStatsManager;->queryStatsForUser(Ljava/lang/String;Landroid/os/UserHandle;)Landroid/app/usage/StorageStats;
-Landroid/app/usage/UsageStats;->mLastEvent:I
-Landroid/app/usage/UsageStats;->mLaunchCount:I
-Landroid/app/usage/UsageStats;->mTotalTimeInForeground:J
-Landroid/app/usage/UsageStatsManager;->mService:Landroid/app/usage/IUsageStatsManager;
-Landroid/appwidget/AppWidgetHost;->sService:Lcom/android/internal/appwidget/IAppWidgetService;
-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;->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;->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;->connect(Landroid/bluetooth/BluetoothDevice;)Z
-Landroid/bluetooth/BluetoothA2dp;->disableOptionalCodecs(Landroid/bluetooth/BluetoothDevice;)V
-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;->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;->supportsOptionalCodecs(Landroid/bluetooth/BluetoothDevice;)I
-Landroid/bluetooth/BluetoothAdapter;->disable(Z)Z
-Landroid/bluetooth/BluetoothAdapter;->factoryReset()Z
-Landroid/bluetooth/BluetoothAdapter;->getDiscoverableTimeout()I
-Landroid/bluetooth/BluetoothAdapter;->getLeState()I
-Landroid/bluetooth/BluetoothAdapter;->mService:Landroid/bluetooth/IBluetooth;
-Landroid/bluetooth/BluetoothAdapter;->setScanMode(I)Z
-Landroid/bluetooth/BluetoothAdapter;->setScanMode(II)Z
-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;->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;->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/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;->setCodecPriority(I)V
-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;->createBond(I)Z
-Landroid/bluetooth/BluetoothDevice;->getAlias()Ljava/lang/String;
-Landroid/bluetooth/BluetoothDevice;->getAliasName()Ljava/lang/String;
-Landroid/bluetooth/BluetoothGatt;->mAuthRetryState:I
-Landroid/bluetooth/BluetoothGatt;->mClientIf:I
-Landroid/bluetooth/BluetoothGatt;->refresh()Z
-Landroid/bluetooth/BluetoothGattCharacteristic;->mInstance:I
-Landroid/bluetooth/BluetoothGattCharacteristic;->mService:Landroid/bluetooth/BluetoothGattService;
-Landroid/bluetooth/BluetoothGattDescriptor;->mCharacteristic:Landroid/bluetooth/BluetoothGattCharacteristic;
-Landroid/bluetooth/BluetoothGattDescriptor;->mInstance:I
-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;->phoneStateChanged(IIILjava/lang/String;I)V
-Landroid/bluetooth/BluetoothHeadset;->setActiveDevice(Landroid/bluetooth/BluetoothDevice;)Z
-Landroid/bluetooth/BluetoothHeadset;->startScoUsingVirtualVoiceCall()Z
-Landroid/bluetooth/BluetoothHeadset;->stopScoUsingVirtualVoiceCall()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/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/BluetoothProfile;->PAN:I
-Landroid/bluetooth/BluetoothSocket;->mPfd:Landroid/os/ParcelFileDescriptor;
-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;->asInterface(Landroid/os/IBinder;)Landroid/bluetooth/IBluetooth;
-Landroid/bluetooth/IBluetooth;->getAddress()Ljava/lang/String;
-Landroid/bluetooth/IBluetooth;->sendConnectionStateChange(Landroid/bluetooth/BluetoothDevice;III)V
-Landroid/bluetooth/IBluetoothManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-Landroid/bluetooth/IBluetoothManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/bluetooth/IBluetoothManager;
-Landroid/bluetooth/le/ScanRecord;->parseFromBytes([B)Landroid/bluetooth/le/ScanRecord;
-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/AsyncTaskLoader;->mExecutor:Ljava/util/concurrent/Executor;
-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;->setPendingResult(Landroid/content/BroadcastReceiver$PendingResult;)V
-Landroid/content/ClipData$Item;->mUri:Landroid/net/Uri;
-Landroid/content/ClipData;->addItem(Landroid/content/ClipData$Item;Landroid/content/ContentResolver;)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;->coerceToLocalContentProvider(Landroid/content/IContentProvider;)Landroid/content/ContentProvider;
-Landroid/content/ContentProvider;->getIContentProvider()Landroid/content/IContentProvider;
-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/ContentProviderOperation;->TYPE_DELETE:I
-Landroid/content/ContentProviderOperation;->TYPE_INSERT:I
-Landroid/content/ContentProviderOperation;->TYPE_UPDATE:I
-Landroid/content/ContentProviderOperation;->mSelection:Ljava/lang/String;
-Landroid/content/ContentProviderOperation;->mType:I
-Landroid/content/ContentProviderOperation;->mUri:Landroid/net/Uri;
-Landroid/content/ContentResolver;->acquireExistingProvider(Landroid/content/Context;Ljava/lang/String;)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;->getContentService()Landroid/content/IContentService;
-Landroid/content/ContentResolver;->getSyncStatus(Landroid/accounts/Account;Ljava/lang/String;)Landroid/content/SyncStatusInfo;
-Landroid/content/ContentResolver;->mContext:Landroid/content/Context;
-Landroid/content/ContentResolver;->mPackageName:Ljava/lang/String;
-Landroid/content/ContentResolver;->registerContentObserver(Landroid/net/Uri;ZLandroid/database/ContentObserver;I)V
-Landroid/content/ContentResolver;->releaseProvider(Landroid/content/IContentProvider;)Z
-Landroid/content/ContentResolver;->releaseUnstableProvider(Landroid/content/IContentProvider;)Z
-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;->getStringArrayList(Ljava/lang/String;)Ljava/util/ArrayList;
-Landroid/content/ContentValues;->mValues:Ljava/util/HashMap;
-Landroid/content/ContentValues;->putStringArrayList(Ljava/lang/String;Ljava/util/ArrayList;)V
-Landroid/content/Context;->getBasePackageName()Ljava/lang/String;
-Landroid/content/Context;->getOpPackageName()Ljava/lang/String;
-Landroid/content/Context;->getSharedPreferences(Ljava/io/File;I)Landroid/content/SharedPreferences;
-Landroid/content/Context;->getSharedPreferencesPath(Ljava/lang/String;)Ljava/io/File;
-Landroid/content/Context;->getSharedPrefsFile(Ljava/lang/String;)Ljava/io/File;
-Landroid/content/Context;->getThemeResId()I
-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;->sendBroadcastAsUser(Landroid/content/Intent;Landroid/os/UserHandle;Ljava/lang/String;I)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/UserHandle;)V
-Landroid/content/Context;->startServiceAsUser(Landroid/content/Intent;Landroid/os/UserHandle;)Landroid/content/ComponentName;
-Landroid/content/ContextWrapper;->getDisplay()Landroid/view/Display;
-Landroid/content/ContextWrapper;->getSharedPreferences(Ljava/io/File;I)Landroid/content/SharedPreferences;
-Landroid/content/ContextWrapper;->getSharedPreferencesPath(Ljava/lang/String;)Ljava/io/File;
-Landroid/content/ContextWrapper;->getThemeResId()I
-Landroid/content/ContextWrapper;->mBase:Landroid/content/Context;
-Landroid/content/CursorLoader;->mCancellationSignal:Landroid/os/CancellationSignal;
-Landroid/content/CursorLoader;->mObserver:Landroid/content/Loader$ForceLoadContentObserver;
-Landroid/content/IClipboard$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-Landroid/content/IClipboard$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/IClipboard;
-Landroid/content/IContentProvider;->call(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Landroid/os/Bundle;)Landroid/os/Bundle;
-Landroid/content/IContentService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-Landroid/content/IContentService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/IContentService;
-Landroid/content/IContentService;->cancelSync(Landroid/accounts/Account;Ljava/lang/String;Landroid/content/ComponentName;)V
-Landroid/content/IContentService;->getMasterSyncAutomatically()Z
-Landroid/content/IContentService;->setMasterSyncAutomatically(Z)V
-Landroid/content/IIntentReceiver$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-Landroid/content/IIntentReceiver$Stub$Proxy;->mRemote:Landroid/os/IBinder;
-Landroid/content/IIntentReceiver$Stub;-><init>()V
-Landroid/content/IIntentReceiver;->performReceive(Landroid/content/Intent;ILjava/lang/String;Landroid/os/Bundle;ZZI)V
-Landroid/content/IRestrictionsManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/IRestrictionsManager;
-Landroid/content/ISyncAdapter$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-Landroid/content/ISyncAdapter$Stub$Proxy;->mRemote:Landroid/os/IBinder;
-Landroid/content/ISyncContext$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-Landroid/content/ISyncContext$Stub$Proxy;->mRemote:Landroid/os/IBinder;
-Landroid/content/ISyncContext$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/ISyncContext;
-Landroid/content/ISyncStatusObserver$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-Landroid/content/ISyncStatusObserver$Stub$Proxy;->mRemote:Landroid/os/IBinder;
-Landroid/content/Intent;->ACTION_ALARM_CHANGED:Ljava/lang/String;
-Landroid/content/Intent;->ACTION_DEVICE_INITIALIZATION_WIZARD:Ljava/lang/String;
-Landroid/content/Intent;->ACTION_MASTER_CLEAR:Ljava/lang/String;
-Landroid/content/Intent;->ACTION_SERVICE_STATE:Ljava/lang/String;
-Landroid/content/Intent;->EXTRA_CDMA_DEFAULT_ROAMING_INDICATOR:Ljava/lang/String;
-Landroid/content/Intent;->EXTRA_CDMA_ROAMING_INDICATOR:Ljava/lang/String;
-Landroid/content/Intent;->EXTRA_CSS_INDICATOR:Ljava/lang/String;
-Landroid/content/Intent;->EXTRA_DATA_OPERATOR_ALPHA_LONG:Ljava/lang/String;
-Landroid/content/Intent;->EXTRA_DATA_OPERATOR_ALPHA_SHORT:Ljava/lang/String;
-Landroid/content/Intent;->EXTRA_DATA_OPERATOR_NUMERIC:Ljava/lang/String;
-Landroid/content/Intent;->EXTRA_DATA_RADIO_TECH:Ljava/lang/String;
-Landroid/content/Intent;->EXTRA_DATA_REG_STATE:Ljava/lang/String;
-Landroid/content/Intent;->EXTRA_DATA_ROAMING_TYPE:Ljava/lang/String;
-Landroid/content/Intent;->EXTRA_EMERGENCY_ONLY:Ljava/lang/String;
-Landroid/content/Intent;->EXTRA_IS_DATA_ROAMING_FROM_REGISTRATION:Ljava/lang/String;
-Landroid/content/Intent;->EXTRA_IS_USING_CARRIER_AGGREGATION:Ljava/lang/String;
-Landroid/content/Intent;->EXTRA_LTE_EARFCN_RSRP_BOOST:Ljava/lang/String;
-Landroid/content/Intent;->EXTRA_MANUAL:Ljava/lang/String;
-Landroid/content/Intent;->EXTRA_NETWORK_ID:Ljava/lang/String;
-Landroid/content/Intent;->EXTRA_OPERATOR_ALPHA_LONG:Ljava/lang/String;
-Landroid/content/Intent;->EXTRA_OPERATOR_ALPHA_SHORT:Ljava/lang/String;
-Landroid/content/Intent;->EXTRA_OPERATOR_NUMERIC:Ljava/lang/String;
-Landroid/content/Intent;->EXTRA_QUICK_VIEW_ADVANCED:Ljava/lang/String;
-Landroid/content/Intent;->EXTRA_SYSTEM_ID:Ljava/lang/String;
-Landroid/content/Intent;->EXTRA_VOICE_RADIO_TECH:Ljava/lang/String;
-Landroid/content/Intent;->EXTRA_VOICE_REG_STATE:Ljava/lang/String;
-Landroid/content/Intent;->EXTRA_VOICE_ROAMING_TYPE:Ljava/lang/String;
-Landroid/content/Intent;->getExtra(Ljava/lang/String;)Ljava/lang/Object;
-Landroid/content/Intent;->getIBinderExtra(Ljava/lang/String;)Landroid/os/IBinder;
-Landroid/content/Intent;->mExtras:Landroid/os/Bundle;
-Landroid/content/Intent;->prepareToLeaveProcess(Landroid/content/Context;)V
-Landroid/content/Intent;->putExtra(Ljava/lang/String;Landroid/os/IBinder;)Landroid/content/Intent;
-Landroid/content/Intent;->resolveSystemService(Landroid/content/pm/PackageManager;I)Landroid/content/ComponentName;
-Landroid/content/Intent;->setAllowFds(Z)V
-Landroid/content/Intent;->toInsecureString()Ljava/lang/String;
-Landroid/content/IntentFilter;->mActions:Ljava/util/ArrayList;
-Landroid/content/IntentSender;-><init>(Landroid/content/IIntentSender;)V
-Landroid/content/IntentSender;->mTarget:Landroid/content/IIntentSender;
-Landroid/content/RestrictionsManager;->mService:Landroid/content/IRestrictionsManager;
-Landroid/content/SearchRecentSuggestionsProvider;->mSuggestionProjection:[Ljava/lang/String;
-Landroid/content/SyncAdapterType;->allowParallelSyncs:Z
-Landroid/content/SyncAdapterType;->isAlwaysSyncable:Z
-Landroid/content/SyncAdapterType;->settingsActivity:Ljava/lang/String;
-Landroid/content/SyncContext;->setStatusText(Ljava/lang/String;)V
-Landroid/content/SyncInfo;-><init>(ILandroid/accounts/Account;Ljava/lang/String;J)V
-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>(Landroid/os/Parcel;)V
-Landroid/content/SyncStatusInfo;->CREATOR:Landroid/os/Parcelable$Creator;
-Landroid/content/SyncStatusInfo;->authorityId:I
-Landroid/content/SyncStatusInfo;->ensurePeriodicSyncTimeSize(I)V
-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/UriMatcher;->mChildren:Ljava/util/ArrayList;
-Landroid/content/UriMatcher;->mText:Ljava/lang/String;
-Landroid/content/pm/ActivityInfo;->isResizeableMode(I)Z
-Landroid/content/pm/ActivityInfo;->resizeMode:I
-Landroid/content/pm/ActivityInfo;->supportsPictureInPicture()Z
-Landroid/content/pm/ApplicationInfo;->enabledSetting:I
-Landroid/content/pm/ApplicationInfo;->getBaseResourcePath()Ljava/lang/String;
-Landroid/content/pm/ApplicationInfo;->installLocation:I
-Landroid/content/pm/ApplicationInfo;->isForwardLocked()Z
-Landroid/content/pm/ApplicationInfo;->primaryCpuAbi:Ljava/lang/String;
-Landroid/content/pm/ApplicationInfo;->privateFlags:I
-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/ApplicationInfo;->volumeUuid:Ljava/lang/String;
-Landroid/content/pm/ComponentInfo;->encryptionAware:Z
-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;-><init>()V
-Landroid/content/pm/IPackageDataObserver$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/pm/IPackageDataObserver;
-Landroid/content/pm/IPackageDataObserver;->onRemoveCompleted(Ljava/lang/String;Z)V
-Landroid/content/pm/IPackageDeleteObserver$Stub;-><init>()V
-Landroid/content/pm/IPackageDeleteObserver$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/pm/IPackageDeleteObserver;
-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;->onPackageDeleted(Ljava/lang/String;ILjava/lang/String;)V
-Landroid/content/pm/IPackageDeleteObserver;->packageDeleted(Ljava/lang/String;I)V
-Landroid/content/pm/IPackageInstallObserver2$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-Landroid/content/pm/IPackageInstallObserver2$Stub$Proxy;->mRemote:Landroid/os/IBinder;
-Landroid/content/pm/IPackageInstallObserver2$Stub;-><init>()V
-Landroid/content/pm/IPackageInstallObserver2;->onPackageInstalled(Ljava/lang/String;ILjava/lang/String;Landroid/os/Bundle;)V
-Landroid/content/pm/IPackageInstallerCallback$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-Landroid/content/pm/IPackageInstallerCallback$Stub$Proxy;->mRemote:Landroid/os/IBinder;
-Landroid/content/pm/IPackageInstallerCallback$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/pm/IPackageInstallerCallback;
-Landroid/content/pm/IPackageInstallerCallback;->onSessionActiveChanged(IZ)V
-Landroid/content/pm/IPackageInstallerCallback;->onSessionBadgingChanged(I)V
-Landroid/content/pm/IPackageInstallerCallback;->onSessionCreated(I)V
-Landroid/content/pm/IPackageInstallerCallback;->onSessionFinished(IZ)V
-Landroid/content/pm/IPackageInstallerCallback;->onSessionProgressChanged(IF)V
-Landroid/content/pm/IPackageInstallerSession$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-Landroid/content/pm/IPackageInstallerSession$Stub$Proxy;->mRemote:Landroid/os/IBinder;
-Landroid/content/pm/IPackageInstallerSession$Stub;-><init>()V
-Landroid/content/pm/IPackageInstallerSession$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/pm/IPackageInstallerSession;
-Landroid/content/pm/IPackageManager$Stub$Proxy;->getInstalledPackages(II)Landroid/content/pm/ParceledListSlice;
-Landroid/content/pm/IPackageManager$Stub$Proxy;->getPackageInfo(Ljava/lang/String;II)Landroid/content/pm/PackageInfo;
-Landroid/content/pm/IPackageManager$Stub$Proxy;->getPackagesForUid(I)[Ljava/lang/String;
-Landroid/content/pm/IPackageManager$Stub$Proxy;->getSystemSharedLibraryNames()[Ljava/lang/String;
-Landroid/content/pm/IPackageManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/pm/IPackageManager;
-Landroid/content/pm/IPackageManager;->addPermission(Landroid/content/pm/PermissionInfo;)Z
-Landroid/content/pm/IPackageManager;->addPermissionAsync(Landroid/content/pm/PermissionInfo;)Z
-Landroid/content/pm/IPackageManager;->getActivityInfo(Landroid/content/ComponentName;II)Landroid/content/pm/ActivityInfo;
-Landroid/content/pm/IPackageManager;->getApplicationInfo(Ljava/lang/String;II)Landroid/content/pm/ApplicationInfo;
-Landroid/content/pm/IPackageManager;->getComponentEnabledSetting(Landroid/content/ComponentName;I)I
-Landroid/content/pm/IPackageManager;->getHomeActivities(Ljava/util/List;)Landroid/content/ComponentName;
-Landroid/content/pm/IPackageManager;->getInstallLocation()I
-Landroid/content/pm/IPackageManager;->getInstalledPackages(II)Landroid/content/pm/ParceledListSlice;
-Landroid/content/pm/IPackageManager;->getInstallerPackageName(Ljava/lang/String;)Ljava/lang/String;
-Landroid/content/pm/IPackageManager;->getLastChosenActivity(Landroid/content/Intent;Ljava/lang/String;I)Landroid/content/pm/ResolveInfo;
-Landroid/content/pm/IPackageManager;->getPackageInfo(Ljava/lang/String;II)Landroid/content/pm/PackageInfo;
-Landroid/content/pm/IPackageManager;->getProviderInfo(Landroid/content/ComponentName;II)Landroid/content/pm/ProviderInfo;
-Landroid/content/pm/IPackageManager;->getReceiverInfo(Landroid/content/ComponentName;II)Landroid/content/pm/ActivityInfo;
-Landroid/content/pm/IPackageManager;->getServiceInfo(Landroid/content/ComponentName;II)Landroid/content/pm/ServiceInfo;
-Landroid/content/pm/IPackageManager;->setApplicationEnabledSetting(Ljava/lang/String;IIILjava/lang/String;)V
-Landroid/content/pm/IPackageManager;->setComponentEnabledSetting(Landroid/content/ComponentName;III)V
-Landroid/content/pm/IPackageManager;->setInstallerPackageName(Ljava/lang/String;Ljava/lang/String;)V
-Landroid/content/pm/IPackageManager;->setLastChosenActivity(Landroid/content/Intent;Ljava/lang/String;ILandroid/content/IntentFilter;ILandroid/content/ComponentName;)V
-Landroid/content/pm/IPackageMoveObserver$Stub;-><init>()V
-Landroid/content/pm/IPackageMoveObserver$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/pm/IPackageMoveObserver;
-Landroid/content/pm/IPackageStatsObserver$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-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;->onGetStatsCompleted(Landroid/content/pm/PackageStats;Z)V
-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;->startShortcut(Ljava/lang/String;Ljava/lang/String;Landroid/graphics/Rect;Landroid/os/Bundle;I)V
-Landroid/content/pm/PackageInfo;->INSTALL_LOCATION_UNSPECIFIED:I
-Landroid/content/pm/PackageInfo;->REQUESTED_PERMISSION_REQUIRED:I
-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;->sizeBytes:J
-Landroid/content/pm/PackageItemInfo;->setForceSafeLabels(Z)V
-Landroid/content/pm/PackageManager;->NO_NATIVE_LIBRARIES:I
-Landroid/content/pm/PackageManager;->buildRequestPermissionsIntent([Ljava/lang/String;)Landroid/content/Intent;
-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;->getApplicationInfoAsUser(Ljava/lang/String;II)Landroid/content/pm/ApplicationInfo;
-Landroid/content/pm/PackageManager;->getHomeActivities(Ljava/util/List;)Landroid/content/ComponentName;
-Landroid/content/pm/PackageManager;->getPackageCandidateVolumes(Landroid/content/pm/ApplicationInfo;)Ljava/util/List;
-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;->getResourcesForApplicationAsUser(Ljava/lang/String;I)Landroid/content/res/Resources;
-Landroid/content/pm/PackageManager;->movePackage(Ljava/lang/String;Landroid/os/storage/VolumeInfo;)I
-Landroid/content/pm/PackageManager;->queryBroadcastReceivers(Landroid/content/Intent;II)Ljava/util/List;
-Landroid/content/pm/PackageManager;->setInstantAppCookie([B)Z
-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$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$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;->instrumentation:Ljava/util/ArrayList;
-Landroid/content/pm/PackageParser$Package;->mAppMetaData:Landroid/os/Bundle;
-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;->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;->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;->usesLibraries:Ljava/util/ArrayList;
-Landroid/content/pm/PackageParser$Package;->usesOptionalLibraries:Ljava/util/ArrayList;
-Landroid/content/pm/PackageParser$Provider;->info:Landroid/content/pm/ProviderInfo;
-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;-><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;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;->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;->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/PackageUserState;-><init>()V
-Landroid/content/pm/ParceledListSlice;-><init>(Ljava/util/List;)V
-Landroid/content/pm/ResolveInfo;->instantAppAvailable:Z
-Landroid/content/pm/SharedLibraryInfo;->isBuiltin()Z
-Landroid/content/pm/SharedLibraryInfo;->isDynamic()Z
-Landroid/content/pm/SharedLibraryInfo;->isStatic()Z
-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;->FLAG_PRIMARY:I
-Landroid/content/pm/UserInfo;->id:I
-Landroid/content/pm/UserInfo;->isPrimary()Z
-Landroid/content/pm/UserInfo;->serialNumber:I
-Landroid/content/res/AssetFileDescriptor;->mFd:Landroid/os/ParcelFileDescriptor;
-Landroid/content/res/AssetFileDescriptor;->mLength:J
-Landroid/content/res/AssetFileDescriptor;->mStartOffset: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;->applyStyle(JIILandroid/content/res/XmlBlock$Parser;[IJJ)V
-Landroid/content/res/AssetManager;->createTheme()J
-Landroid/content/res/AssetManager;->getAssignedPackageIdentifiers()Landroid/util/SparseArray;
-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;->getResourceTypeName(I)Ljava/lang/String;
-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/ColorStateList$ColorStateListFactory;-><init>(Landroid/content/res/ColorStateList;)V
-Landroid/content/res/ColorStateList;->getColors()[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;->onColorsChanged()V
-Landroid/content/res/CompatibilityInfo;-><init>(Landroid/content/pm/ApplicationInfo;IIZ)V
-Landroid/content/res/CompatibilityInfo;->DEFAULT_COMPATIBILITY_INFO:Landroid/content/res/CompatibilityInfo;
-Landroid/content/res/CompatibilityInfo;->applicationScale:F
-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;->getCompatibilityInfo()Landroid/content/res/CompatibilityInfo;
-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;->updateSystemConfiguration(Landroid/content/res/Configuration;Landroid/util/DisplayMetrics;Landroid/content/res/CompatibilityInfo;)V
-Landroid/content/res/ResourcesImpl;->TRACE_FOR_MISS_PRELOAD:Z
-Landroid/content/res/ResourcesImpl;->TRACE_FOR_PRELOAD:Z
-Landroid/content/res/ResourcesImpl;->getAssets()Landroid/content/res/AssetManager;
-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/ResourcesKey;->mSplitResDirs:[Ljava/lang/String;
-Landroid/content/res/StringBlock;-><init>(JZ)V
-Landroid/content/res/ThemedResourceCache;->onConfigurationChange(I)V
-Landroid/content/res/TypedArray;->extractThemeAttrs()[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/database/AbstractCursor;->mCurrentRowID:Ljava/lang/Long;
-Landroid/database/AbstractCursor;->mExtras:Landroid/os/Bundle;
-Landroid/database/AbstractCursor;->mNotifyUri:Landroid/net/Uri;
-Landroid/database/AbstractCursor;->mRowIdColumnIndex:I
-Landroid/database/AbstractCursor;->mUpdatedRows:Ljava/util/HashMap;
-Landroid/database/AbstractWindowedCursor;->clearOrCreateWindow(Ljava/lang/String;)V
-Landroid/database/CursorWindow;->mWindowPtr:J
-Landroid/database/CursorWindow;->sCursorWindowSize:I
-Landroid/database/CursorWindow;->sWindowToPidMap:Landroid/util/LongSparseArray;
-Landroid/database/CursorWrapper;->mCursor:Landroid/database/Cursor;
-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;->CONFLICT_VALUES:[Ljava/lang/String;
-Landroid/database/sqlite/SQLiteDatabase;->mConfigurationLocked:Landroid/database/sqlite/SQLiteDatabaseConfiguration;
-Landroid/database/sqlite/SQLiteDatabase;->mConnectionPoolLocked:Landroid/database/sqlite/SQLiteConnectionPool;
-Landroid/database/sqlite/SQLiteDatabase;->reopenReadWrite()V
-Landroid/database/sqlite/SQLiteDatabaseConfiguration;->maxSqlCacheSize:I
-Landroid/database/sqlite/SQLiteDebug$PagerStats;->largestMemAlloc:I
-Landroid/database/sqlite/SQLiteDebug$PagerStats;->memoryUsed:I
-Landroid/database/sqlite/SQLiteDebug$PagerStats;->pageCacheOverflow:I
-Landroid/database/sqlite/SQLiteOpenHelper;->mName:Ljava/lang/String;
-Landroid/database/sqlite/SQLiteStatement;-><init>(Landroid/database/sqlite/SQLiteDatabase;Ljava/lang/String;[Ljava/lang/Object;)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/ddm/DdmHandleAppName;->getAppName()Ljava/lang/String;
-Landroid/ddm/DdmHandleAppName;->setAppName(Ljava/lang/String;I)V
-Landroid/graphics/AvoidXfermode$Mode;
-Landroid/graphics/AvoidXfermode$Mode;->AVOID:Landroid/graphics/AvoidXfermode$Mode;
-Landroid/graphics/AvoidXfermode$Mode;->TARGET:Landroid/graphics/AvoidXfermode$Mode;
-Landroid/graphics/AvoidXfermode$Mode;->valueOf(Ljava/lang/String;)Landroid/graphics/AvoidXfermode$Mode;
-Landroid/graphics/AvoidXfermode$Mode;->values()[Landroid/graphics/AvoidXfermode$Mode;
-Landroid/graphics/AvoidXfermode;
-Landroid/graphics/AvoidXfermode;-><init>(IILandroid/graphics/AvoidXfermode$Mode;)V
-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>(JIIIZZ[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;->createGraphicBufferHandle()Landroid/graphics/GraphicBuffer;
-Landroid/graphics/Bitmap;->createHardwareBitmap(Landroid/graphics/GraphicBuffer;)Landroid/graphics/Bitmap;
-Landroid/graphics/Bitmap;->getDefaultDensity()I
-Landroid/graphics/Bitmap;->mNativePtr:J
-Landroid/graphics/Bitmap;->mNinePatchChunk:[B
-Landroid/graphics/Bitmap;->mNinePatchInsets:Landroid/graphics/NinePatch$InsetStruct;
-Landroid/graphics/Bitmap;->reinit(IIZ)V
-Landroid/graphics/Bitmap;->setDefaultDensity(I)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/Camera;->native_instance:J
-Landroid/graphics/Canvas;-><init>(J)V
-Landroid/graphics/Canvas;->CLIP_SAVE_FLAG:I
-Landroid/graphics/Canvas;->CLIP_TO_LAYER_SAVE_FLAG:I
-Landroid/graphics/Canvas;->FULL_COLOR_LAYER_SAVE_FLAG:I
-Landroid/graphics/Canvas;->HAS_ALPHA_LAYER_SAVE_FLAG:I
-Landroid/graphics/Canvas;->MATRIX_SAVE_FLAG:I
-Landroid/graphics/Canvas;->clipRegion(Landroid/graphics/Region;)Z
-Landroid/graphics/Canvas;->clipRegion(Landroid/graphics/Region;Landroid/graphics/Region$Op;)Z
-Landroid/graphics/Canvas;->release()V
-Landroid/graphics/Canvas;->save(I)I
-Landroid/graphics/ColorMatrixColorFilter;->setColorMatrix(Landroid/graphics/ColorMatrix;)V
-Landroid/graphics/FontFamily;-><init>()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/GraphicBuffer;-><init>(IIIIJ)V
-Landroid/graphics/GraphicBuffer;->CREATOR:Landroid/os/Parcelable$Creator;
-Landroid/graphics/GraphicBuffer;->createFromExisting(IIIIJ)Landroid/graphics/GraphicBuffer;
-Landroid/graphics/GraphicBuffer;->mNativeObject:J
-Landroid/graphics/ImageDecoder$IncompleteException;
-Landroid/graphics/ImageDecoder$IncompleteException;-><init>()V
-Landroid/graphics/ImageDecoder;->ERROR_SOURCE_ERROR:I
-Landroid/graphics/ImageDecoder;->ERROR_SOURCE_EXCEPTION:I
-Landroid/graphics/ImageDecoder;->ERROR_SOURCE_INCOMPLETE:I
-Landroid/graphics/ImageDecoder;->getAsAlphaMask()Z
-Landroid/graphics/ImageDecoder;->getConserveMemory()Z
-Landroid/graphics/ImageDecoder;->getDecodeAsAlphaMask()Z
-Landroid/graphics/ImageDecoder;->getMutable()Z
-Landroid/graphics/ImageDecoder;->getRequireUnpremultiplied()Z
-Landroid/graphics/ImageDecoder;->postProcessAndRelease(Landroid/graphics/Canvas;)I
-Landroid/graphics/ImageDecoder;->setAsAlphaMask(Z)Landroid/graphics/ImageDecoder;
-Landroid/graphics/ImageDecoder;->setConserveMemory(Z)V
-Landroid/graphics/ImageDecoder;->setDecodeAsAlphaMask(Z)Landroid/graphics/ImageDecoder;
-Landroid/graphics/ImageDecoder;->setMutable(Z)Landroid/graphics/ImageDecoder;
-Landroid/graphics/ImageDecoder;->setRequireUnpremultiplied(Z)Landroid/graphics/ImageDecoder;
-Landroid/graphics/ImageDecoder;->setResize(I)Landroid/graphics/ImageDecoder;
-Landroid/graphics/ImageDecoder;->setResize(II)Landroid/graphics/ImageDecoder;
-Landroid/graphics/Insets;->left:I
-Landroid/graphics/Insets;->right:I
-Landroid/graphics/LayerRasterizer;
-Landroid/graphics/LayerRasterizer;-><init>()V
-Landroid/graphics/LayerRasterizer;->addLayer(Landroid/graphics/Paint;)V
-Landroid/graphics/LayerRasterizer;->addLayer(Landroid/graphics/Paint;FF)V
-Landroid/graphics/LinearGradient;->mColors:[I
-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/Paint;->getRasterizer()Landroid/graphics/Rasterizer;
-Landroid/graphics/Paint;->setRasterizer(Landroid/graphics/Rasterizer;)Landroid/graphics/Rasterizer;
-Landroid/graphics/Picture;->mNativePicture:J
-Landroid/graphics/PixelXorXfermode;
-Landroid/graphics/PixelXorXfermode;-><init>(I)V
-Landroid/graphics/PorterDuffColorFilter;->getColor()I
-Landroid/graphics/PorterDuffColorFilter;->setColor(I)V
-Landroid/graphics/PorterDuffColorFilter;->setMode(Landroid/graphics/PorterDuff$Mode;)V
-Landroid/graphics/Rasterizer;
-Landroid/graphics/Rasterizer;-><init>()V
-Landroid/graphics/Rect;->scale(F)V
-Landroid/graphics/Region;-><init>(JI)V
-Landroid/graphics/Region;->mNativeRegion:J
-Landroid/graphics/SurfaceTexture;->mFrameAvailableListener:J
-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/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;->sDefaults:[Landroid/graphics/Typeface;
-Landroid/graphics/Typeface;->sSystemFontMap:Ljava/util/Map;
-Landroid/graphics/Typeface;->setDefault(Landroid/graphics/Typeface;)V
-Landroid/graphics/drawable/AnimatedImageDrawable;->LOOP_INFINITE:I
-Landroid/graphics/drawable/AnimatedImageDrawable;->getLoopCount(I)I
-Landroid/graphics/drawable/AnimatedImageDrawable;->onAnimationEnd()V
-Landroid/graphics/drawable/AnimatedImageDrawable;->setLoopCount(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/AnimationDrawable;->mCurFrame:I
-Landroid/graphics/drawable/BitmapDrawable;->getOpticalInsets()Landroid/graphics/Insets;
-Landroid/graphics/drawable/BitmapDrawable;->getTint()Landroid/content/res/ColorStateList;
-Landroid/graphics/drawable/BitmapDrawable;->getTintMode()Landroid/graphics/PorterDuff$Mode;
-Landroid/graphics/drawable/BitmapDrawable;->mTargetDensity:I
-Landroid/graphics/drawable/BitmapDrawable;->setBitmap(Landroid/graphics/Bitmap;)V
-Landroid/graphics/drawable/ColorDrawable$ColorState;->mUseColor:I
-Landroid/graphics/drawable/Drawable;->getOpticalInsets()Landroid/graphics/Insets;
-Landroid/graphics/drawable/Drawable;->inflateWithAttributes(Landroid/content/res/Resources;Lorg/xmlpull/v1/XmlPullParser;Landroid/content/res/TypedArray;I)V
-Landroid/graphics/drawable/Drawable;->isProjected()Z
-Landroid/graphics/drawable/Drawable;->mCallback:Ljava/lang/ref/WeakReference;
-Landroid/graphics/drawable/Drawable;->parseTintMode(ILandroid/graphics/PorterDuff$Mode;)Landroid/graphics/PorterDuff$Mode;
-Landroid/graphics/drawable/Drawable;->updateTintFilter(Landroid/graphics/PorterDuffColorFilter;Landroid/content/res/ColorStateList;Landroid/graphics/PorterDuff$Mode;)Landroid/graphics/PorterDuffColorFilter;
-Landroid/graphics/drawable/DrawableContainer$DrawableContainerState;->mConstantPadding:Landroid/graphics/Rect;
-Landroid/graphics/drawable/DrawableContainer$DrawableContainerState;->mDrawables:[Landroid/graphics/drawable/Drawable;
-Landroid/graphics/drawable/DrawableContainer;->getOpticalInsets()Landroid/graphics/Insets;
-Landroid/graphics/drawable/DrawableContainer;->mDrawableContainerState:Landroid/graphics/drawable/DrawableContainer$DrawableContainerState;
-Landroid/graphics/drawable/DrawableInflater;->mClassLoader:Ljava/lang/ClassLoader;
-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;->getOpticalInsets()Landroid/graphics/Insets;
-Landroid/graphics/drawable/GradientDrawable;->mGradientState:Landroid/graphics/drawable/GradientDrawable$GradientState;
-Landroid/graphics/drawable/GradientDrawable;->mPadding:Landroid/graphics/Rect;
-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;->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;->mState:Landroid/graphics/drawable/RippleDrawable$RippleState;
-Landroid/graphics/drawable/StateListDrawable;->extractStateSet(Landroid/util/AttributeSet;)[I
-Landroid/graphics/drawable/StateListDrawable;->getStateCount()I
-Landroid/graphics/drawable/StateListDrawable;->getStateDrawable(I)Landroid/graphics/drawable/Drawable;
-Landroid/graphics/drawable/StateListDrawable;->getStateDrawableIndex([I)I
-Landroid/graphics/drawable/StateListDrawable;->getStateSet(I)[I
-Landroid/graphics/drawable/StateListDrawable;->mStateListState:Landroid/graphics/drawable/StateListDrawable$StateListState;
-Landroid/graphics/drawable/StateListDrawable;->updateStateFromTypedArray(Landroid/content/res/TypedArray;)V
-Landroid/graphics/drawable/VectorDrawable$VGroup;->setRotation(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/fonts/FontVariationAxis;->mStyleValue:F
-Landroid/graphics/fonts/FontVariationAxis;->mTag:I
-Landroid/hardware/Camera;->addCallbackBuffer([BI)V
-Landroid/hardware/Camera;->mNativeContext:J
-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/HardwareBuffer;-><init>(J)V
-Landroid/hardware/HardwareBuffer;->destroy()V
-Landroid/hardware/HardwareBuffer;->isDestroyed()Z
-Landroid/hardware/HardwareBuffer;->mNativeObject:J
-Landroid/hardware/ICameraService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/hardware/ICameraService;
-Landroid/hardware/SensorDirectChannel;->isValid()Z
-Landroid/hardware/SensorManager;->configureDirectChannel(Landroid/hardware/SensorDirectChannel;Landroid/hardware/Sensor;I)I
-Landroid/hardware/SerialPort;->mNativeContext: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/camera2/CameraAccessException;->serialVersionUID:J
-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;->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$Key;-><init>(Ljava/lang/String;Landroid/hardware/camera2/utils/TypeReference;)V
-Landroid/hardware/camera2/CaptureRequest$Key;-><init>(Ljava/lang/String;Ljava/lang/Class;)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;->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;->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;->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/utils/TypeReference;->createSpecializedTypeReference(Ljava/lang/reflect/Type;)Landroid/hardware/camera2/utils/TypeReference;
-Landroid/hardware/display/DisplayManagerGlobal;->getInstance()Landroid/hardware/display/DisplayManagerGlobal;
-Landroid/hardware/display/DisplayManagerGlobal;->getRealDisplay(I)Landroid/view/Display;
-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/WifiDisplayStatus;->mActiveDisplay:Landroid/hardware/display/WifiDisplay;
-Landroid/hardware/display/WifiDisplayStatus;->mDisplays:[Landroid/hardware/display/WifiDisplay;
-Landroid/hardware/fingerprint/IFingerprintService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-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/InputManager;->INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH:I
-Landroid/hardware/input/InputManager;->getInstance()Landroid/hardware/input/InputManager;
-Landroid/hardware/input/InputManager;->injectInputEvent(Landroid/view/InputEvent;I)Z
-Landroid/hardware/input/InputManager;->mIm:Landroid/hardware/input/IInputManager;
-Landroid/hardware/location/GeofenceHardware;-><init>(Landroid/hardware/location/IGeofenceHardware;)V
-Landroid/hardware/location/IActivityRecognitionHardwareClient$Stub;-><init>()V
-Landroid/hardware/location/IActivityRecognitionHardwareClient;->onAvailabilityChanged(ZLandroid/hardware/location/IActivityRecognitionHardware;)V
-Landroid/hardware/location/IContextHubService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/hardware/location/IContextHubService;
-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;->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$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;->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$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;->data:[B
-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/SoundTriggerModule;->mId:I
-Landroid/hardware/soundtrigger/SoundTriggerModule;->mNativeContext:J
-Landroid/hardware/soundtrigger/SoundTriggerModule;->postEventFromNative(Ljava/lang/Object;IIILjava/lang/Object;)V
-Landroid/hardware/usb/IUsbManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-Landroid/hardware/usb/UsbDeviceConnection;->mNativeContext:J
-Landroid/hardware/usb/UsbManager;->getPortStatus(Landroid/hardware/usb/UsbPort;)Landroid/hardware/usb/UsbPortStatus;
-Landroid/hardware/usb/UsbManager;->getPorts()[Landroid/hardware/usb/UsbPort;
-Landroid/hardware/usb/UsbManager;->setCurrentFunction(Ljava/lang/String;Z)V
-Landroid/hardware/usb/UsbManager;->setPortRoles(Landroid/hardware/usb/UsbPort;II)V
-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/impl/TimeZoneGenericNames;->readObject(Ljava/io/ObjectInputStream;)V
-Landroid/icu/impl/TimeZoneGenericNames;->serialVersionUID:J
-Landroid/icu/impl/locale/LocaleSyntaxException;->serialVersionUID:J
-Landroid/icu/impl/number/DecimalFormatProperties;->readObject(Ljava/io/ObjectInputStream;)V
-Landroid/icu/impl/number/DecimalFormatProperties;->serialVersionUID:J
-Landroid/icu/impl/number/DecimalFormatProperties;->writeObject(Ljava/io/ObjectOutputStream;)V
-Landroid/icu/math/BigDecimal;->serialVersionUID:J
-Landroid/icu/math/MathContext;->serialVersionUID:J
-Landroid/icu/text/ArabicShaping;->isAlefMaksouraChar(C)Z
-Landroid/icu/text/ArabicShaping;->isSeenTailFamilyChar(C)I
-Landroid/icu/text/ArabicShaping;->isTailChar(C)Z
-Landroid/icu/text/ArabicShaping;->isYehHamzaChar(C)Z
-Landroid/icu/text/ArabicShapingException;->serialVersionUID:J
-Landroid/icu/text/ChineseDateFormat$Field;->serialVersionUID:J
-Landroid/icu/text/ChineseDateFormat;->serialVersionUID:J
-Landroid/icu/text/ChineseDateFormatSymbols;->serialVersionUID:J
-Landroid/icu/text/CompactDecimalFormat;->serialVersionUID:J
-Landroid/icu/text/CurrencyPluralInfo;->serialVersionUID:J
-Landroid/icu/text/DateFormat$Field;->serialVersionUID:J
-Landroid/icu/text/DateFormat;->readObject(Ljava/io/ObjectInputStream;)V
-Landroid/icu/text/DateFormat;->serialVersionUID:J
-Landroid/icu/text/DateFormatSymbols;->getLocale(Landroid/icu/util/ULocale$Type;)Landroid/icu/util/ULocale;
-Landroid/icu/text/DateFormatSymbols;->readObject(Ljava/io/ObjectInputStream;)V
-Landroid/icu/text/DateFormatSymbols;->serialVersionUID:J
-Landroid/icu/text/DateIntervalFormat;-><init>()V
-Landroid/icu/text/DateIntervalFormat;->readObject(Ljava/io/ObjectInputStream;)V
-Landroid/icu/text/DateIntervalFormat;->serialVersionUID:J
-Landroid/icu/text/DateIntervalInfo$PatternInfo;->serialVersionUID:J
-Landroid/icu/text/DateIntervalInfo;->serialVersionUID:J
-Landroid/icu/text/DateTimePatternGenerator$DistanceInfo;-><init>()V
-Landroid/icu/text/DecimalFormat;->readObject(Ljava/io/ObjectInputStream;)V
-Landroid/icu/text/DecimalFormat;->serialVersionUID:J
-Landroid/icu/text/DecimalFormat;->writeObject(Ljava/io/ObjectOutputStream;)V
-Landroid/icu/text/DecimalFormatSymbols;->getLocale(Landroid/icu/util/ULocale$Type;)Landroid/icu/util/ULocale;
-Landroid/icu/text/DecimalFormatSymbols;->readObject(Ljava/io/ObjectInputStream;)V
-Landroid/icu/text/DecimalFormatSymbols;->serialVersionUID:J
-Landroid/icu/text/DecimalFormat_ICU58_Android;->readObject(Ljava/io/ObjectInputStream;)V
-Landroid/icu/text/DecimalFormat_ICU58_Android;->serialVersionUID:J
-Landroid/icu/text/DecimalFormat_ICU58_Android;->writeObject(Ljava/io/ObjectOutputStream;)V
-Landroid/icu/text/DurationFormat;->serialVersionUID:J
-Landroid/icu/text/MeasureFormat$MeasureProxy;->readResolve()Ljava/lang/Object;
-Landroid/icu/text/MeasureFormat$MeasureProxy;->serialVersionUID:J
-Landroid/icu/text/MeasureFormat;->serialVersionUID:J
-Landroid/icu/text/MeasureFormat;->writeReplace()Ljava/lang/Object;
-Landroid/icu/text/MessageFormat$Field;->serialVersionUID:J
-Landroid/icu/text/MessageFormat;->readObject(Ljava/io/ObjectInputStream;)V
-Landroid/icu/text/MessageFormat;->serialVersionUID:J
-Landroid/icu/text/MessageFormat;->writeObject(Ljava/io/ObjectOutputStream;)V
-Landroid/icu/text/NumberFormat$Field;->serialVersionUID:J
-Landroid/icu/text/NumberFormat;->readObject(Ljava/io/ObjectInputStream;)V
-Landroid/icu/text/NumberFormat;->serialVersionUID:J
-Landroid/icu/text/NumberFormat;->writeObject(Ljava/io/ObjectOutputStream;)V
-Landroid/icu/text/PluralFormat;->readObject(Ljava/io/ObjectInputStream;)V
-Landroid/icu/text/PluralFormat;->serialVersionUID:J
-Landroid/icu/text/PluralRules$AndConstraint;->serialVersionUID:J
-Landroid/icu/text/PluralRules$BinaryConstraint;->serialVersionUID:J
-Landroid/icu/text/PluralRules$FixedDecimal;->readObject(Ljava/io/ObjectInputStream;)V
-Landroid/icu/text/PluralRules$FixedDecimal;->serialVersionUID:J
-Landroid/icu/text/PluralRules$FixedDecimal;->writeObject(Ljava/io/ObjectOutputStream;)V
-Landroid/icu/text/PluralRules$OrConstraint;->serialVersionUID:J
-Landroid/icu/text/PluralRules$RangeConstraint;->serialVersionUID:J
-Landroid/icu/text/PluralRules$Rule;->serialVersionUID:J
-Landroid/icu/text/PluralRules$RuleList;->serialVersionUID:J
-Landroid/icu/text/PluralRules;->readObject(Ljava/io/ObjectInputStream;)V
-Landroid/icu/text/PluralRules;->serialVersionUID:J
-Landroid/icu/text/PluralRules;->writeObject(Ljava/io/ObjectOutputStream;)V
-Landroid/icu/text/PluralRules;->writeReplace()Ljava/lang/Object;
-Landroid/icu/text/RuleBasedCollator;->getLocale(Landroid/icu/util/ULocale$Type;)Landroid/icu/util/ULocale;
-Landroid/icu/text/RuleBasedNumberFormat;->readObject(Ljava/io/ObjectInputStream;)V
-Landroid/icu/text/RuleBasedNumberFormat;->serialVersionUID:J
-Landroid/icu/text/RuleBasedNumberFormat;->writeObject(Ljava/io/ObjectOutputStream;)V
-Landroid/icu/text/SelectFormat;->readObject(Ljava/io/ObjectInputStream;)V
-Landroid/icu/text/SelectFormat;->serialVersionUID:J
-Landroid/icu/text/SimpleDateFormat;->readObject(Ljava/io/ObjectInputStream;)V
-Landroid/icu/text/SimpleDateFormat;->serialVersionUID:J
-Landroid/icu/text/SimpleDateFormat;->writeObject(Ljava/io/ObjectOutputStream;)V
-Landroid/icu/text/SpoofChecker$ScriptSet;-><init>()V
-Landroid/icu/text/SpoofChecker$ScriptSet;->and(I)V
-Landroid/icu/text/SpoofChecker$ScriptSet;->isFull()Z
-Landroid/icu/text/SpoofChecker$ScriptSet;->serialVersionUID:J
-Landroid/icu/text/SpoofChecker$ScriptSet;->setAll()V
-Landroid/icu/text/StringPrepParseException;->serialVersionUID:J
-Landroid/icu/text/TimeUnitFormat;->readResolve()Ljava/lang/Object;
-Landroid/icu/text/TimeUnitFormat;->serialVersionUID:J
-Landroid/icu/text/TimeUnitFormat;->writeReplace()Ljava/lang/Object;
-Landroid/icu/text/TimeZoneFormat;->readObject(Ljava/io/ObjectInputStream;)V
-Landroid/icu/text/TimeZoneFormat;->serialPersistentFields:[Ljava/io/ObjectStreamField;
-Landroid/icu/text/TimeZoneFormat;->serialVersionUID:J
-Landroid/icu/text/TimeZoneFormat;->writeObject(Ljava/io/ObjectOutputStream;)V
-Landroid/icu/text/TimeZoneNames$DefaultTimeZoneNames$FactoryImpl;-><init>()V
-Landroid/icu/text/TimeZoneNames$DefaultTimeZoneNames;->serialVersionUID:J
-Landroid/icu/text/TimeZoneNames;->serialVersionUID:J
-Landroid/icu/text/Transliterator;->createFromRules(Ljava/lang/String;Ljava/lang/String;I)Landroid/icu/text/Transliterator;
-Landroid/icu/text/Transliterator;->getInstance(Ljava/lang/String;)Landroid/icu/text/Transliterator;
-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/UFormat;->serialVersionUID:J
-Landroid/icu/util/AnnualTimeZoneRule;->serialVersionUID:J
-Landroid/icu/util/BasicTimeZone;->serialVersionUID:J
-Landroid/icu/util/BuddhistCalendar;->serialVersionUID:J
-Landroid/icu/util/CECalendar;->serialVersionUID:J
-Landroid/icu/util/Calendar;->getLocale(Landroid/icu/util/ULocale$Type;)Landroid/icu/util/ULocale;
-Landroid/icu/util/Calendar;->readObject(Ljava/io/ObjectInputStream;)V
-Landroid/icu/util/Calendar;->serialVersionUID:J
-Landroid/icu/util/Calendar;->writeObject(Ljava/io/ObjectOutputStream;)V
-Landroid/icu/util/ChineseCalendar;->readObject(Ljava/io/ObjectInputStream;)V
-Landroid/icu/util/ChineseCalendar;->serialVersionUID:J
-Landroid/icu/util/CopticCalendar;->serialVersionUID:J
-Landroid/icu/util/Currency;->readResolve()Ljava/lang/Object;
-Landroid/icu/util/Currency;->serialVersionUID:J
-Landroid/icu/util/Currency;->writeReplace()Ljava/lang/Object;
-Landroid/icu/util/DangiCalendar;->serialVersionUID:J
-Landroid/icu/util/DateInterval;->serialVersionUID:J
-Landroid/icu/util/DateTimeRule;->serialVersionUID:J
-Landroid/icu/util/EthiopicCalendar;->serialVersionUID:J
-Landroid/icu/util/GregorianCalendar;->serialVersionUID:J
-Landroid/icu/util/HebrewCalendar;->serialVersionUID:J
-Landroid/icu/util/ICUCloneNotSupportedException;->serialVersionUID:J
-Landroid/icu/util/ICUException;->serialVersionUID:J
-Landroid/icu/util/ICUUncheckedIOException;->serialVersionUID:J
-Landroid/icu/util/IllformedLocaleException;->serialVersionUID:J
-Landroid/icu/util/IndianCalendar;->serialVersionUID:J
-Landroid/icu/util/InitialTimeZoneRule;->serialVersionUID:J
-Landroid/icu/util/IslamicCalendar;->readObject(Ljava/io/ObjectInputStream;)V
-Landroid/icu/util/IslamicCalendar;->serialVersionUID:J
-Landroid/icu/util/JapaneseCalendar;->serialVersionUID:J
-Landroid/icu/util/MeasureUnit$MeasureUnitProxy;->readResolve()Ljava/lang/Object;
-Landroid/icu/util/MeasureUnit$MeasureUnitProxy;->serialVersionUID:J
-Landroid/icu/util/MeasureUnit;->serialVersionUID:J
-Landroid/icu/util/MeasureUnit;->writeReplace()Ljava/lang/Object;
-Landroid/icu/util/NoUnit;->serialVersionUID:J
-Landroid/icu/util/PersianCalendar;->serialVersionUID:J
-Landroid/icu/util/RuleBasedTimeZone;->serialVersionUID:J
-Landroid/icu/util/STZInfo;->serialVersionUID:J
-Landroid/icu/util/SimpleTimeZone;->readObject(Ljava/io/ObjectInputStream;)V
-Landroid/icu/util/SimpleTimeZone;->serialVersionUID:J
-Landroid/icu/util/TaiwanCalendar;->serialVersionUID:J
-Landroid/icu/util/TimeArrayTimeZoneRule;->serialVersionUID:J
-Landroid/icu/util/TimeUnit;->readResolve()Ljava/lang/Object;
-Landroid/icu/util/TimeUnit;->serialVersionUID:J
-Landroid/icu/util/TimeUnit;->writeReplace()Ljava/lang/Object;
-Landroid/icu/util/TimeZone$ConstantZone;->serialVersionUID:J
-Landroid/icu/util/TimeZone;->serialVersionUID:J
-Landroid/icu/util/TimeZoneRule;->serialVersionUID:J
-Landroid/icu/util/ULocale;->serialVersionUID:J
-Landroid/icu/util/UResourceTypeMismatchException;->serialVersionUID:J
-Landroid/icu/util/VTimeZone;->serialVersionUID:J
-Landroid/inputmethodservice/InputMethodService$SettingsObserver;->shouldShowImeWithHardKeyboard()Z
-Landroid/inputmethodservice/InputMethodService;->mExtractEditText:Landroid/inputmethodservice/ExtractEditText;
-Landroid/inputmethodservice/InputMethodService;->mRootView:Landroid/view/View;
-Landroid/inputmethodservice/InputMethodService;->mSettingsObserver:Landroid/inputmethodservice/InputMethodService$SettingsObserver;
-Landroid/location/Country;->getCountryIso()Ljava/lang/String;
-Landroid/location/Country;->getSource()I
-Landroid/location/CountryDetector;->detectCountry()Landroid/location/Country;
-Landroid/location/GeocoderParams;->getClientPackage()Ljava/lang/String;
-Landroid/location/GeocoderParams;->getLocale()Ljava/util/Locale;
-Landroid/location/IGeocodeProvider$Stub;-><init>()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;
-Landroid/location/IGeofenceProvider$Stub;-><init>()V
-Landroid/location/IGeofenceProvider;->setGeofenceHardware(Landroid/hardware/location/IGeofenceHardware;)V
-Landroid/location/ILocationListener$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-Landroid/location/ILocationListener$Stub$Proxy;->mRemote:Landroid/os/IBinder;
-Landroid/location/ILocationListener;->onLocationChanged(Landroid/location/Location;)V
-Landroid/location/ILocationManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-Landroid/location/ILocationManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/location/ILocationManager;
-Landroid/location/ILocationManager;->getNetworkProviderPackage()Ljava/lang/String;
-Landroid/location/ILocationManager;->reportLocation(Landroid/location/Location;Z)V
-Landroid/location/INetInitiatedListener$Stub;-><init>()V
-Landroid/location/INetInitiatedListener;->sendNiResponse(II)Z
-Landroid/location/Location;->mElapsedRealtimeNanos:J
-Landroid/location/Location;->removeBearingAccuracy()V
-Landroid/location/Location;->removeSpeedAccuracy()V
-Landroid/location/Location;->removeVerticalAccuracy()V
-Landroid/location/Location;->setExtraLocation(Ljava/lang/String;Landroid/location/Location;)V
-Landroid/location/LocationManager;->mService:Landroid/location/ILocationManager;
-Landroid/location/LocationRequest;->mHideFromAppOps:Z
-Landroid/location/LocationRequest;->mInterval:J
-Landroid/location/LocationRequest;->mProvider:Ljava/lang/String;
-Landroid/location/LocationRequest;->mWorkSource:Landroid/os/WorkSource;
-Landroid/media/AudioAttributes$Builder;->addTag(Ljava/lang/String;)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/AudioDevicePortConfig;-><init>(Landroid/media/AudioDevicePort;IIILandroid/media/AudioGainConfig;)V
-Landroid/media/AudioFormat;-><init>()V
-Landroid/media/AudioFormat;-><init>(IIII)V
-Landroid/media/AudioFormat;->mChannelMask:I
-Landroid/media/AudioFormat;->mEncoding:I
-Landroid/media/AudioFormat;->mSampleRate: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>(Landroid/content/Context;)V
-Landroid/media/AudioManager;->STREAM_BLUETOOTH_SCO:I
-Landroid/media/AudioManager;->STREAM_SYSTEM_ENFORCED:I
-Landroid/media/AudioManager;->STREAM_TTS:I
-Landroid/media/AudioManager;->forceVolumeControlStream(I)V
-Landroid/media/AudioManager;->getOutputLatency(I)I
-Landroid/media/AudioManager;->getService()Landroid/media/IAudioService;
-Landroid/media/AudioManager;->mAudioFocusIdListenerMap:Ljava/util/concurrent/ConcurrentHashMap;
-Landroid/media/AudioManager;->registerAudioPortUpdateListener(Landroid/media/AudioManager$OnAudioPortUpdateListener;)V
-Landroid/media/AudioManager;->setMasterMute(ZI)V
-Landroid/media/AudioManager;->setRingerModeInternal(I)V
-Landroid/media/AudioManager;->startBluetoothScoVirtualCall()V
-Landroid/media/AudioManager;->unregisterAudioPortUpdateListener(Landroid/media/AudioManager$OnAudioPortUpdateListener;)V
-Landroid/media/AudioMixPort;-><init>(Landroid/media/AudioHandle;IILjava/lang/String;[I[I[I[I[Landroid/media/AudioGain;)V
-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/AudioPort;-><init>(Landroid/media/AudioHandle;ILjava/lang/String;[I[I[I[I[Landroid/media/AudioGain;)V
-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/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/AudioPortEventHandler;->mJniCallback:J
-Landroid/media/AudioPortEventHandler;->postEventFromNative(Ljava/lang/Object;IIILjava/lang/Object;)V
-Landroid/media/AudioRecord;->mNativeCallbackCookie:J
-Landroid/media/AudioRecord;->mNativeDeviceCallback:J
-Landroid/media/AudioRecord;->mNativeRecorderInJavaObj:J
-Landroid/media/AudioRecord;->native_release()V
-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;->checkAudioFlinger()I
-Landroid/media/AudioSystem;->dynamicPolicyCallbackFromNative(ILjava/lang/String;I)V
-Landroid/media/AudioSystem;->errorCallbackFromNative(I)V
-Landroid/media/AudioSystem;->getForceUse(I)I
-Landroid/media/AudioSystem;->getParameters(Ljava/lang/String;)Ljava/lang/String;
-Landroid/media/AudioSystem;->getPrimaryOutputFrameCount()I
-Landroid/media/AudioSystem;->getPrimaryOutputSamplingRate()I
-Landroid/media/AudioSystem;->isSourceActive(I)Z
-Landroid/media/AudioSystem;->isStreamActive(II)Z
-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;->setForceUse(II)I
-Landroid/media/AudioSystem;->setParameters(Ljava/lang/String;)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/ExifInterface;->getDateTime()J
-Landroid/media/IAudioService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-Landroid/media/IAudioService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/media/IAudioService;
-Landroid/media/IAudioService;->getStreamMaxVolume(I)I
-Landroid/media/IAudioService;->getStreamVolume(I)I
-Landroid/media/IAudioService;->setStreamVolume(IIILjava/lang/String;)V
-Landroid/media/IMediaRouterService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/media/IMediaRouterService;
-Landroid/media/IMediaScannerService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/media/IMediaScannerService;
-Landroid/media/IMediaScannerService;->scanFile(Ljava/lang/String;Ljava/lang/String;)V
-Landroid/media/IRemoteDisplayCallback;->onStateChanged(Landroid/media/RemoteDisplayState;)V
-Landroid/media/IVolumeController$Stub;->asInterface(Landroid/os/IBinder;)Landroid/media/IVolumeController;
-Landroid/media/Image;-><init>()V
-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;->releaseOutputBuffer(IZZJ)V
-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/MediaFile$MediaFileType;->fileType:I
-Landroid/media/MediaFile$MediaFileType;->mimeType:Ljava/lang/String;
-Landroid/media/MediaFile;-><init>()V
-Landroid/media/MediaFile;->FIRST_AUDIO_FILE_TYPE:I
-Landroid/media/MediaFile;->LAST_AUDIO_FILE_TYPE:I
-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;->isImageFileType(I)Z
-Landroid/media/MediaFile;->isPlayListFileType(I)Z
-Landroid/media/MediaFile;->isVideoFileType(I)Z
-Landroid/media/MediaFile;->sFileTypeMap:Ljava/util/HashMap;
-Landroid/media/MediaFormat;->getMap()Ljava/util/Map;
-Landroid/media/MediaHTTPService;->createHttpServiceBinderIfNecessary(Ljava/lang/String;)Landroid/os/IBinder;
-Landroid/media/MediaMetadataRetriever;->getEmbeddedPicture(I)[B
-Landroid/media/MediaPlayer;->getMetadata(ZZ)Landroid/media/Metadata;
-Landroid/media/MediaPlayer;->invoke(Landroid/os/Parcel;Landroid/os/Parcel;)V
-Landroid/media/MediaPlayer;->mEventHandler:Landroid/media/MediaPlayer$EventHandler;
-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;->setRetransmitEndpoint(Ljava/net/InetSocketAddress;)V
-Landroid/media/MediaRecorder;->setParameter(Ljava/lang/String;)V
-Landroid/media/MediaRouter$RouteInfo;->STATUS_CONNECTING:I
-Landroid/media/MediaRouter$RouteInfo;->getStatusCode()I
-Landroid/media/MediaRouter;->selectRouteInt(ILandroid/media/MediaRouter$RouteInfo;Z)V
-Landroid/media/MediaScanner;->isNoMediaPath(Ljava/lang/String;)Z
-Landroid/media/MediaScanner;->mClient:Landroid/media/MediaScanner$MyMediaScannerClient;
-Landroid/media/MediaScanner;->scanSingleFile(Ljava/lang/String;Ljava/lang/String;)Landroid/net/Uri;
-Landroid/media/Metadata;->PAUSE_AVAILABLE:I
-Landroid/media/Metadata;->SEEK_BACKWARD_AVAILABLE:I
-Landroid/media/Metadata;->SEEK_FORWARD_AVAILABLE:I
-Landroid/media/Metadata;->getBoolean(I)Z
-Landroid/media/Metadata;->has(I)Z
-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;->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/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/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/RingtoneManager;->getRingtone(Landroid/content/Context;Landroid/net/Uri;I)Landroid/media/Ringtone;
-Landroid/media/SubtitleController;->mHandler:Landroid/os/Handler;
-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;->createImageThumbnail(Ljava/lang/String;I)Landroid/graphics/Bitmap;
-Landroid/media/ToneGenerator;->mNativeContext:J
-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/audiofx/AudioEffect;-><init>(Ljava/util/UUID;Ljava/util/UUID;II)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/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/session/ISessionManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/media/session/ISessionManager;
-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/soundtrigger/SoundTriggerDetector$EventPayload;->getCaptureSession()Ljava/lang/Integer;
-Landroid/media/soundtrigger/SoundTriggerDetector$EventPayload;->getData()[B
-Landroid/media/soundtrigger/SoundTriggerManager;->loadSoundModel(Landroid/hardware/soundtrigger/SoundTrigger$SoundModel;)I
-Landroid/media/soundtrigger/SoundTriggerManager;->startRecognition(Ljava/util/UUID;Landroid/app/PendingIntent;Landroid/hardware/soundtrigger/SoundTrigger$RecognitionConfig;)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/tv/ITvRemoteProvider$Stub;-><init>()V
-Landroid/media/tv/ITvRemoteServiceInput;->clearInputBridge(Landroid/os/IBinder;)V
-Landroid/media/tv/ITvRemoteServiceInput;->closeInputBridge(Landroid/os/IBinder;)V
-Landroid/media/tv/ITvRemoteServiceInput;->openInputBridge(Landroid/os/IBinder;Ljava/lang/String;III)V
-Landroid/media/tv/ITvRemoteServiceInput;->sendKeyDown(Landroid/os/IBinder;I)V
-Landroid/media/tv/ITvRemoteServiceInput;->sendKeyUp(Landroid/os/IBinder;I)V
-Landroid/media/tv/ITvRemoteServiceInput;->sendPointerDown(Landroid/os/IBinder;III)V
-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/media/tv/TvInputManager$Hardware;->dispatchKeyEventToHdmi(Landroid/view/KeyEvent;)Z
-Landroid/media/tv/TvInputManager;->acquireTvInputHardware(ILandroid/media/tv/TvInputManager$HardwareCallback;Landroid/media/tv/TvInputInfo;)Landroid/media/tv/TvInputManager$Hardware;
-Landroid/media/tv/TvView;->requestUnblockContent(Landroid/media/tv/TvContentRating;)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;->ACTION_TETHER_STATE_CHANGED:Ljava/lang/String;
-Landroid/net/ConnectivityManager;->EXTRA_ACTIVE_TETHER:Ljava/lang/String;
-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;->getActiveLinkProperties()Landroid/net/LinkProperties;
-Landroid/net/ConnectivityManager;->getActiveNetworkQuotaInfo()Landroid/net/NetworkQuotaInfo;
-Landroid/net/ConnectivityManager;->getLinkProperties(I)Landroid/net/LinkProperties;
-Landroid/net/ConnectivityManager;->getMobileDataEnabled()Z
-Landroid/net/ConnectivityManager;->getTetherableUsbRegexs()[Ljava/lang/String;
-Landroid/net/ConnectivityManager;->getTetherableWifiRegexs()[Ljava/lang/String;
-Landroid/net/ConnectivityManager;->getTetheredIfaces()[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;->registerNetworkFactory(Landroid/os/Messenger;Ljava/lang/String;)V
-Landroid/net/ConnectivityManager;->requestRouteToHost(II)Z
-Landroid/net/ConnectivityManager;->requestRouteToHostAddress(ILjava/net/InetAddress;)Z
-Landroid/net/ConnectivityManager;->setAirplaneMode(Z)V
-Landroid/net/ConnectivityManager;->setBackgroundDataSetting(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;->startUsingNetworkFeature(ILjava/lang/String;)I
-Landroid/net/ConnectivityManager;->stopUsingNetworkFeature(ILjava/lang/String;)I
-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$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;
-Landroid/net/IConnectivityManager$Stub$Proxy;->getAllNetworkInfo()[Landroid/net/NetworkInfo;
-Landroid/net/IConnectivityManager$Stub$Proxy;->getAllNetworks()[Landroid/net/Network;
-Landroid/net/IConnectivityManager$Stub$Proxy;->getTetherableIfaces()[Ljava/lang/String;
-Landroid/net/IConnectivityManager$Stub$Proxy;->getTetherableUsbRegexs()[Ljava/lang/String;
-Landroid/net/IConnectivityManager$Stub$Proxy;->getTetheredIfaces()[Ljava/lang/String;
-Landroid/net/IConnectivityManager$Stub$Proxy;->mRemote:Landroid/os/IBinder;
-Landroid/net/IConnectivityManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/IConnectivityManager;
-Landroid/net/IConnectivityManager;->getActiveLinkProperties()Landroid/net/LinkProperties;
-Landroid/net/IConnectivityManager;->getActiveNetworkInfo()Landroid/net/NetworkInfo;
-Landroid/net/IConnectivityManager;->getAllNetworkInfo()[Landroid/net/NetworkInfo;
-Landroid/net/IConnectivityManager;->getAllNetworkState()[Landroid/net/NetworkState;
-Landroid/net/IConnectivityManager;->getTetheredIfaces()[Ljava/lang/String;
-Landroid/net/INetd$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/INetd;
-Landroid/net/INetd;->interfaceAddAddress(Ljava/lang/String;Ljava/lang/String;I)V
-Landroid/net/INetworkPolicyManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/INetworkPolicyManager;
-Landroid/net/INetworkPolicyManager;->getNetworkQuotaInfo(Landroid/net/NetworkState;)Landroid/net/NetworkQuotaInfo;
-Landroid/net/INetworkScoreService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/INetworkScoreService;
-Landroid/net/INetworkStatsService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-Landroid/net/INetworkStatsService$Stub$Proxy;->getMobileIfaces()[Ljava/lang/String;
-Landroid/net/INetworkStatsService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/INetworkStatsService;
-Landroid/net/INetworkStatsService;->openSession()Landroid/net/INetworkStatsSession;
-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/IpConfiguration;->httpProxy:Landroid/net/ProxyInfo;
-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;->isIPv6Provisioned()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;->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;->setHttpProxy(Landroid/net/ProxyInfo;)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/LocalSocketImpl;->inboundFileDescriptors:[Ljava/io/FileDescriptor;
-Landroid/net/LocalSocketImpl;->outboundFileDescriptors:[Ljava/io/FileDescriptor;
-Landroid/net/MacAddress;->ALL_ZEROS_ADDRESS:Landroid/net/MacAddress;
-Landroid/net/Network;-><init>(I)V
-Landroid/net/Network;->netId:I
-Landroid/net/NetworkBadging$Badging;
-Landroid/net/NetworkBadging;
-Landroid/net/NetworkBadging;->BADGING_4K:I
-Landroid/net/NetworkBadging;->BADGING_HD:I
-Landroid/net/NetworkBadging;->BADGING_NONE:I
-Landroid/net/NetworkBadging;->BADGING_SD:I
-Landroid/net/NetworkBadging;->getWifiIcon(IILandroid/content/res/Resources$Theme;)Landroid/graphics/drawable/Drawable;
-Landroid/net/NetworkCapabilities;->getCapabilities()[I
-Landroid/net/NetworkCapabilities;->getNetworkSpecifier()Landroid/net/NetworkSpecifier;
-Landroid/net/NetworkCapabilities;->getSignalStrength()I
-Landroid/net/NetworkCapabilities;->getTransportTypes()[I
-Landroid/net/NetworkCapabilities;->hasSignalStrength()Z
-Landroid/net/NetworkCapabilities;->transportNamesOf([I)Ljava/lang/String;
-Landroid/net/NetworkPolicyManager;->mService:Landroid/net/INetworkPolicyManager;
-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;->capacity:I
-Landroid/net/NetworkStats;->combineValues(Landroid/net/NetworkStats$Entry;)Landroid/net/NetworkStats;
-Landroid/net/NetworkStats;->defaultNetwork:[I
-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;->tag:[I
-Landroid/net/NetworkStats;->txBytes:[J
-Landroid/net/NetworkStats;->txPackets:[J
-Landroid/net/NetworkStats;->uid:[I
-Landroid/net/NetworkStatsHistory$Entry;->rxBytes:J
-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/NetworkTemplate;->buildTemplateWifi()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/Proxy;->getProxy(Landroid/content/Context;Ljava/lang/String;)Ljava/net/Proxy;
-Landroid/net/ProxyInfo;-><init>(Ljava/lang/String;ILjava/lang/String;)V
-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/SSLCertificateSocketFactory;-><init>(ILandroid/net/SSLSessionCache;Z)V
-Landroid/net/SSLCertificateSocketFactory;->INSECURE_TRUST_MANAGER:[Ljavax/net/ssl/TrustManager;
-Landroid/net/SSLCertificateSocketFactory;->TAG:Ljava/lang/String;
-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;->getHttpSocketFactory(ILandroid/net/SSLSessionCache;)Lorg/apache/http/conn/ssl/SSLSocketFactory;
-Landroid/net/SSLCertificateSocketFactory;->isSslCheckRelaxed()Z
-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;->makeSocketFactory([Ljavax/net/ssl/KeyManager;[Ljavax/net/ssl/TrustManager;)Ljavax/net/ssl/SSLSocketFactory;
-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;->verifyHostname(Ljava/net/Socket;Ljava/lang/String;)V
-Landroid/net/SSLSessionCache;->mSessionCache:Lcom/android/org/conscrypt/SSLClientSessionCache;
-Landroid/net/SntpClient;-><init>()V
-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;-><init>()V
-Landroid/net/StaticIpConfiguration;->dnsServers:Ljava/util/ArrayList;
-Landroid/net/StaticIpConfiguration;->domains:Ljava/lang/String;
-Landroid/net/StaticIpConfiguration;->gateway:Ljava/net/InetAddress;
-Landroid/net/StaticIpConfiguration;->getRoutes(Ljava/lang/String;)Ljava/util/List;
-Landroid/net/StaticIpConfiguration;->ipAddress:Landroid/net/LinkAddress;
-Landroid/net/StringNetworkSpecifier;->specifier:Ljava/lang/String;
-Landroid/net/TrafficStats;->getMobileIfaces()[Ljava/lang/String;
-Landroid/net/TrafficStats;->getMobileTcpRxPackets()J
-Landroid/net/TrafficStats;->getMobileTcpTxPackets()J
-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/TrafficStats;->setThreadStatsUidSelf()V
-Landroid/net/Uri;-><init>()V
-Landroid/net/http/SslError;->mCertificate:Landroid/net/http/SslCertificate;
-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;->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/DhcpErrorEvent;->errorCodeWithOption(II)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/sip/SipProfile;->readResolve()Ljava/lang/Object;
-Landroid/net/sip/SipProfile;->serialVersionUID:J
-Landroid/net/wifi/BatchedScanResult;
-Landroid/net/wifi/BatchedScanResult;-><init>()V
-Landroid/net/wifi/BatchedScanResult;-><init>(Landroid/net/wifi/BatchedScanResult;)V
-Landroid/net/wifi/BatchedScanResult;->scanResults:Ljava/util/List;
-Landroid/net/wifi/BatchedScanResult;->truncated:Z
-Landroid/net/wifi/IWifiManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-Landroid/net/wifi/IWifiManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/wifi/IWifiManager;
-Landroid/net/wifi/IWifiScanner$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-Landroid/net/wifi/IWifiScanner$Stub$Proxy;->mRemote:Landroid/os/IBinder;
-Landroid/net/wifi/IWifiScanner$Stub;-><init>()V
-Landroid/net/wifi/IWifiScanner$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/wifi/IWifiScanner;
-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;->bytes:[B
-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;->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;->numUsage:I
-Landroid/net/wifi/ScanResult;->seen:J
-Landroid/net/wifi/ScanResult;->untrusted:Z
-Landroid/net/wifi/ScanResult;->wifiSsid:Landroid/net/wifi/WifiSsid;
-Landroid/net/wifi/WifiConfiguration;->apBand:I
-Landroid/net/wifi/WifiConfiguration;->apChannel:I
-Landroid/net/wifi/WifiConfiguration;->defaultGwMacAddress:Ljava/lang/String;
-Landroid/net/wifi/WifiConfiguration;->lastConnectUid:I
-Landroid/net/wifi/WifiConfiguration;->mIpConfiguration:Landroid/net/IpConfiguration;
-Landroid/net/wifi/WifiConfiguration;->setIpAssignment(Landroid/net/IpConfiguration$IpAssignment;)V
-Landroid/net/wifi/WifiConfiguration;->setStaticIpConfiguration(Landroid/net/StaticIpConfiguration;)V
-Landroid/net/wifi/WifiConfiguration;->validatedInternetAccess:Z
-Landroid/net/wifi/WifiEnterpriseConfig;->getCaCertificateAlias()Ljava/lang/String;
-Landroid/net/wifi/WifiEnterpriseConfig;->getClientCertificateAlias()Ljava/lang/String;
-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;->is5GHz()Z
-Landroid/net/wifi/WifiInfo;->mMacAddress:Ljava/lang/String;
-Landroid/net/wifi/WifiInfo;->removeDoubleQuotes(Ljava/lang/String;)Ljava/lang/String;
-Landroid/net/wifi/WifiInfo;->score:I
-Landroid/net/wifi/WifiManager;->cancelLocalOnlyHotspotRequest()V
-Landroid/net/wifi/WifiManager;->connect(ILandroid/net/wifi/WifiManager$ActionListener;)V
-Landroid/net/wifi/WifiManager;->forget(ILandroid/net/wifi/WifiManager$ActionListener;)V
-Landroid/net/wifi/WifiManager;->isDualBandSupported()Z
-Landroid/net/wifi/WifiManager;->mService:Landroid/net/wifi/IWifiManager;
-Landroid/net/wifi/WifiManager;->save(Landroid/net/wifi/WifiConfiguration;Landroid/net/wifi/WifiManager$ActionListener;)V
-Landroid/net/wifi/WifiSsid;->NONE:Ljava/lang/String;
-Landroid/net/wifi/WifiSsid;->getOctets()[B
-Landroid/net/wifi/p2p/WifiP2pGroup;->TEMPORARY_NET_ID:I
-Landroid/net/wifi/p2p/WifiP2pGroup;->getNetworkId()I
-Landroid/net/wifi/p2p/WifiP2pGroupList;->getGroupList()Ljava/util/Collection;
-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;->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;->setWifiP2pChannels(Landroid/net/wifi/p2p/WifiP2pManager$Channel;IILandroid/net/wifi/p2p/WifiP2pManager$ActionListener;)V
-Landroid/nfc/NfcAdapter;->getAdapterState()I
-Landroid/nfc/NfcAdapter;->getDefaultAdapter()Landroid/nfc/NfcAdapter;
-Landroid/nfc/NfcAdapter;->getNfcAdapter(Landroid/content/Context;)Landroid/nfc/NfcAdapter;
-Landroid/nfc/NfcAdapter;->setNdefPushMessageCallback(Landroid/nfc/NfcAdapter$CreateNdefMessageCallback;Landroid/app/Activity;I)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;-><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;
-Landroid/os/AsyncResult;->result:Ljava/lang/Object;
-Landroid/os/AsyncResult;->userObj:Ljava/lang/Object;
-Landroid/os/AsyncTask;->mFuture:Ljava/util/concurrent/FutureTask;
-Landroid/os/AsyncTask;->mStatus:Landroid/os/AsyncTask$Status;
-Landroid/os/AsyncTask;->mTaskInvoked:Ljava/util/concurrent/atomic/AtomicBoolean;
-Landroid/os/AsyncTask;->mWorker:Landroid/os/AsyncTask$WorkerRunnable;
-Landroid/os/AsyncTask;->sDefaultExecutor:Ljava/util/concurrent/Executor;
-Landroid/os/AsyncTask;->setDefaultExecutor(Ljava/util/concurrent/Executor;)V
-Landroid/os/BatteryManager;-><init>()V
-Landroid/os/BatteryStats$Counter;->getCountLocked(I)I
-Landroid/os/BatteryStats$HistoryItem;-><init>()V
-Landroid/os/BatteryStats$HistoryItem;->CMD_UPDATE:B
-Landroid/os/BatteryStats$HistoryItem;->batteryLevel:B
-Landroid/os/BatteryStats$HistoryItem;->cmd:B
-Landroid/os/BatteryStats$HistoryItem;->states2:I
-Landroid/os/BatteryStats$HistoryItem;->states:I
-Landroid/os/BatteryStats$HistoryItem;->time:J
-Landroid/os/BatteryStats$Timer;->getCountLocked(I)I
-Landroid/os/BatteryStats$Timer;->getTotalTimeLocked(JI)J
-Landroid/os/BatteryStats$Uid$Pkg$Serv;->getLaunches(I)I
-Landroid/os/BatteryStats$Uid$Pkg$Serv;->getStartTime(JI)J
-Landroid/os/BatteryStats$Uid$Pkg;->getServiceStats()Landroid/util/ArrayMap;
-Landroid/os/BatteryStats$Uid$Pkg;->getWakeupAlarmStats()Landroid/util/ArrayMap;
-Landroid/os/BatteryStats$Uid$Proc$ExcessivePower;->overTime:J
-Landroid/os/BatteryStats$Uid$Proc$ExcessivePower;->type:I
-Landroid/os/BatteryStats$Uid$Proc$ExcessivePower;->usedTime:J
-Landroid/os/BatteryStats$Uid$Proc;->countExcessivePowers()I
-Landroid/os/BatteryStats$Uid$Proc;->getExcessivePower(I)Landroid/os/BatteryStats$Uid$Proc$ExcessivePower;
-Landroid/os/BatteryStats$Uid$Proc;->getForegroundTime(I)J
-Landroid/os/BatteryStats$Uid$Proc;->getStarts(I)I
-Landroid/os/BatteryStats$Uid$Proc;->getSystemTime(I)J
-Landroid/os/BatteryStats$Uid$Proc;->getUserTime(I)J
-Landroid/os/BatteryStats$Uid$Sensor;->getHandle()I
-Landroid/os/BatteryStats$Uid$Sensor;->getSensorTime()Landroid/os/BatteryStats$Timer;
-Landroid/os/BatteryStats$Uid$Wakelock;->getWakeTime(I)Landroid/os/BatteryStats$Timer;
-Landroid/os/BatteryStats$Uid;-><init>()V
-Landroid/os/BatteryStats$Uid;->getAudioTurnedOnTimer()Landroid/os/BatteryStats$Timer;
-Landroid/os/BatteryStats$Uid;->getFullWifiLockTime(JI)J
-Landroid/os/BatteryStats$Uid;->getPackageStats()Landroid/util/ArrayMap;
-Landroid/os/BatteryStats$Uid;->getProcessStats()Landroid/util/ArrayMap;
-Landroid/os/BatteryStats$Uid;->getSensorStats()Landroid/util/SparseArray;
-Landroid/os/BatteryStats$Uid;->getUid()I
-Landroid/os/BatteryStats$Uid;->getVideoTurnedOnTimer()Landroid/os/BatteryStats$Timer;
-Landroid/os/BatteryStats$Uid;->getWifiMulticastTime(JI)J
-Landroid/os/BatteryStats$Uid;->getWifiRunningTime(JI)J
-Landroid/os/BatteryStats$Uid;->getWifiScanTime(JI)J
-Landroid/os/BatteryStats;->NUM_DATA_CONNECTION_TYPES:I
-Landroid/os/BatteryStats;->getNextHistoryLocked(Landroid/os/BatteryStats$HistoryItem;)Z
-Landroid/os/BatteryStats;->getUidStats()Landroid/util/SparseArray;
-Landroid/os/BatteryStats;->startIteratingHistoryLocked()Z
-Landroid/os/Binder;->execTransact(IJJI)Z
-Landroid/os/Binder;->mObject:J
-Landroid/os/Broadcaster;-><init>()V
-Landroid/os/Broadcaster;->broadcast(Landroid/os/Message;)V
-Landroid/os/Broadcaster;->cancelRequest(ILandroid/os/Handler;I)V
-Landroid/os/Broadcaster;->request(ILandroid/os/Handler;I)V
-Landroid/os/Build$VERSION;->ACTIVE_CODENAMES:[Ljava/lang/String;
-Landroid/os/Build;->IS_DEBUGGABLE:Z
-Landroid/os/Build;->IS_EMULATOR:Z
-Landroid/os/Build;->PERMISSIONS_REVIEW_REQUIRED:Z
-Landroid/os/Build;->getString(Ljava/lang/String;)Ljava/lang/String;
-Landroid/os/Bundle;->getIBinder(Ljava/lang/String;)Landroid/os/IBinder;
-Landroid/os/Bundle;->putIBinder(Ljava/lang/String;Landroid/os/IBinder;)V
-Landroid/os/Debug$MemoryInfo;->NUM_DVK_STATS:I
-Landroid/os/Debug$MemoryInfo;->NUM_OTHER_STATS:I
-Landroid/os/Debug$MemoryInfo;->dalvikPrivateClean:I
-Landroid/os/Debug$MemoryInfo;->dalvikRss:I
-Landroid/os/Debug$MemoryInfo;->dalvikSharedClean:I
-Landroid/os/Debug$MemoryInfo;->dalvikSwappablePss:I
-Landroid/os/Debug$MemoryInfo;->dalvikSwappedOut:I
-Landroid/os/Debug$MemoryInfo;->dalvikSwappedOutPss:I
-Landroid/os/Debug$MemoryInfo;->getOtherLabel(I)Ljava/lang/String;
-Landroid/os/Debug$MemoryInfo;->getOtherPrivate(I)I
-Landroid/os/Debug$MemoryInfo;->getOtherPrivateDirty(I)I
-Landroid/os/Debug$MemoryInfo;->getOtherPss(I)I
-Landroid/os/Debug$MemoryInfo;->getOtherSharedDirty(I)I
-Landroid/os/Debug$MemoryInfo;->getTotalUss()I
-Landroid/os/Debug$MemoryInfo;->hasSwappedOutPss:Z
-Landroid/os/Debug$MemoryInfo;->nativePrivateClean:I
-Landroid/os/Debug$MemoryInfo;->nativeRss:I
-Landroid/os/Debug$MemoryInfo;->nativeSharedClean:I
-Landroid/os/Debug$MemoryInfo;->nativeSwappablePss:I
-Landroid/os/Debug$MemoryInfo;->nativeSwappedOut:I
-Landroid/os/Debug$MemoryInfo;->nativeSwappedOutPss:I
-Landroid/os/Debug$MemoryInfo;->otherPrivateClean:I
-Landroid/os/Debug$MemoryInfo;->otherRss:I
-Landroid/os/Debug$MemoryInfo;->otherSharedClean:I
-Landroid/os/Debug$MemoryInfo;->otherStats:[I
-Landroid/os/Debug$MemoryInfo;->otherSwappablePss:I
-Landroid/os/Debug$MemoryInfo;->otherSwappedOut:I
-Landroid/os/Debug$MemoryInfo;->otherSwappedOutPss:I
-Landroid/os/Debug;-><init>()V
-Landroid/os/Debug;->countInstancesOfClass(Ljava/lang/Class;)J
-Landroid/os/Debug;->dumpReferenceTables()V
-Landroid/os/DropBoxManager;->mService:Lcom/android/internal/os/IDropBoxManagerService;
-Landroid/os/Environment;->buildExternalStorageAppDataDirs(Ljava/lang/String;)[Ljava/io/File;
-Landroid/os/Environment;->getLegacyExternalStorageDirectory()Ljava/io/File;
-Landroid/os/Environment;->getStorageDirectory()Ljava/io/File;
-Landroid/os/Environment;->getVendorDirectory()Ljava/io/File;
-Landroid/os/Environment;->maybeTranslateEmulatedPathToInternal(Ljava/io/File;)Ljava/io/File;
-Landroid/os/FileObserver$ObserverThread;->onEvent(IILjava/lang/String;)V
-Landroid/os/FileUtils;->checksumCrc32(Ljava/io/File;)J
-Landroid/os/FileUtils;->copyFile(Ljava/io/File;Ljava/io/File;)Z
-Landroid/os/FileUtils;->copyToFile(Ljava/io/InputStream;Ljava/io/File;)Z
-Landroid/os/FileUtils;->deleteOlderFiles(Ljava/io/File;IJ)Z
-Landroid/os/FileUtils;->readTextFile(Ljava/io/File;ILjava/lang/String;)Ljava/lang/String;
-Landroid/os/FileUtils;->setPermissions(Ljava/io/File;III)I
-Landroid/os/FileUtils;->setPermissions(Ljava/io/FileDescriptor;III)I
-Landroid/os/FileUtils;->setPermissions(Ljava/lang/String;III)I
-Landroid/os/FileUtils;->stringToFile(Ljava/io/File;Ljava/lang/String;)V
-Landroid/os/FileUtils;->stringToFile(Ljava/lang/String;Ljava/lang/String;)V
-Landroid/os/FileUtils;->sync(Ljava/io/FileOutputStream;)Z
-Landroid/os/Handler;-><init>(Landroid/os/Looper;Landroid/os/Handler$Callback;Z)V
-Landroid/os/Handler;-><init>(Z)V
-Landroid/os/Handler;->getIMessenger()Landroid/os/IMessenger;
-Landroid/os/Handler;->getMain()Landroid/os/Handler;
-Landroid/os/Handler;->hasCallbacks(Ljava/lang/Runnable;)Z
-Landroid/os/Handler;->mCallback:Landroid/os/Handler$Callback;
-Landroid/os/Handler;->mMessenger:Landroid/os/IMessenger;
-Landroid/os/HwBinder;->reportSyspropChanged()V
-Landroid/os/HwParcel;-><init>(Z)V
-Landroid/os/HwRemoteBinder;-><init>()V
-Landroid/os/IBatteryPropertiesRegistrar$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-Landroid/os/INetworkManagementService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/os/INetworkManagementService;
-Landroid/os/INetworkManagementService;->clearInterfaceAddresses(Ljava/lang/String;)V
-Landroid/os/INetworkManagementService;->disableIpv6(Ljava/lang/String;)V
-Landroid/os/INetworkManagementService;->enableIpv6(Ljava/lang/String;)V
-Landroid/os/INetworkManagementService;->isBandwidthControlEnabled()Z
-Landroid/os/INetworkManagementService;->registerObserver(Landroid/net/INetworkManagementEventObserver;)V
-Landroid/os/INetworkManagementService;->setIPv6AddrGenMode(Ljava/lang/String;I)V
-Landroid/os/INetworkManagementService;->setInterfaceConfig(Ljava/lang/String;Landroid/net/InterfaceConfiguration;)V
-Landroid/os/INetworkManagementService;->setInterfaceIpv6PrivacyExtensions(Ljava/lang/String;Z)V
-Landroid/os/INetworkManagementService;->unregisterObserver(Landroid/net/INetworkManagementEventObserver;)V
-Landroid/os/IPermissionController$Stub$Proxy;->checkPermission(Ljava/lang/String;II)Z
-Landroid/os/IPermissionController$Stub;->asInterface(Landroid/os/IBinder;)Landroid/os/IPermissionController;
-Landroid/os/IPowerManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-Landroid/os/IPowerManager$Stub$Proxy;->isLightDeviceIdleMode()Z
-Landroid/os/IPowerManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/os/IPowerManager;
-Landroid/os/IPowerManager;->goToSleep(JII)V
-Landroid/os/IPowerManager;->reboot(ZLjava/lang/String;Z)V
-Landroid/os/IPowerManager;->releaseWakeLock(Landroid/os/IBinder;I)V
-Landroid/os/IPowerManager;->userActivity(JII)V
-Landroid/os/IRecoverySystem$Stub;->asInterface(Landroid/os/IBinder;)Landroid/os/IRecoverySystem;
-Landroid/os/IRemoteCallback$Stub;-><init>()V
-Landroid/os/IServiceManager;->checkService(Ljava/lang/String;)Landroid/os/IBinder;
-Landroid/os/IServiceManager;->getService(Ljava/lang/String;)Landroid/os/IBinder;
-Landroid/os/IUserManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-Landroid/os/IUserManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/os/IUserManager;
-Landroid/os/IVibratorService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/os/IVibratorService;
-Landroid/os/LocaleList;->setDefault(Landroid/os/LocaleList;I)V
-Landroid/os/Looper;->mQueue:Landroid/os/MessageQueue;
-Landroid/os/Looper;->sThreadLocal:Ljava/lang/ThreadLocal;
-Landroid/os/Looper;->setTraceTag(J)V
-Landroid/os/MemoryFile;->getFileDescriptor()Ljava/io/FileDescriptor;
-Landroid/os/Message;->callback:Ljava/lang/Runnable;
-Landroid/os/Message;->flags:I
-Landroid/os/Message;->markInUse()V
-Landroid/os/Message;->next:Landroid/os/Message;
-Landroid/os/Message;->recycleUnchecked()V
-Landroid/os/Message;->setCallback(Ljava/lang/Runnable;)Landroid/os/Message;
-Landroid/os/Message;->target:Landroid/os/Handler;
-Landroid/os/Message;->when:J
-Landroid/os/MessageQueue;->dispatchEvents(II)I
-Landroid/os/MessageQueue;->mIdleHandlers:Ljava/util/ArrayList;
-Landroid/os/MessageQueue;->mMessages:Landroid/os/Message;
-Landroid/os/MessageQueue;->mPtr:J
-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;->mNativePtr:J
-Landroid/os/Parcel;->readArrayMap(Landroid/util/ArrayMap;Ljava/lang/ClassLoader;)V
-Landroid/os/Parcel;->readBlob()[B
-Landroid/os/Parcel;->readParcelableList(Ljava/util/List;Ljava/lang/ClassLoader;)Ljava/util/List;
-Landroid/os/Parcel;->readStringArray()[Ljava/lang/String;
-Landroid/os/Parcel;->writeArrayMap(Landroid/util/ArrayMap;)V
-Landroid/os/Parcel;->writeBlob([B)V
-Landroid/os/Parcel;->writeParcelableList(Ljava/util/List;I)V
-Landroid/os/ParcelFileDescriptor$FileDescriptorDetachedException;->serialVersionUID:J
-Landroid/os/ParcelFileDescriptor;-><init>(Ljava/io/FileDescriptor;)V
-Landroid/os/ParcelFileDescriptor;->fromData([BLjava/lang/String;)Landroid/os/ParcelFileDescriptor;
-Landroid/os/PowerManager;->ACTION_SCREEN_BRIGHTNESS_BOOST_CHANGED:Ljava/lang/String;
-Landroid/os/PowerManager;->getDefaultScreenBrightnessSetting()I
-Landroid/os/PowerManager;->getMaximumScreenBrightnessSetting()I
-Landroid/os/PowerManager;->getMinimumScreenBrightnessSetting()I
-Landroid/os/PowerManager;->goToSleep(J)V
-Landroid/os/PowerManager;->isLightDeviceIdleMode()Z
-Landroid/os/PowerManager;->isScreenBrightnessBoosted()Z
-Landroid/os/PowerManager;->mService:Landroid/os/IPowerManager;
-Landroid/os/PowerManager;->userActivity(JZ)V
-Landroid/os/PowerManager;->validateWakeLockParameters(ILjava/lang/String;)V
-Landroid/os/PowerManager;->wakeUp(J)V
-Landroid/os/PowerManager;->wakeUp(JLjava/lang/String;)V
-Landroid/os/Process;->getFreeMemory()J
-Landroid/os/Process;->getParentPid(I)I
-Landroid/os/Process;->getPids(Ljava/lang/String;[I)[I
-Landroid/os/Process;->getTotalMemory()J
-Landroid/os/Process;->getUidForPid(I)I
-Landroid/os/Process;->isIsolated(I)Z
-Landroid/os/Process;->readProcFile(Ljava/lang/String;[I[Ljava/lang/String;[J[F)Z
-Landroid/os/Process;->readProcLines(Ljava/lang/String;[Ljava/lang/String;[J)V
-Landroid/os/Process;->setArgV0(Ljava/lang/String;)V
-Landroid/os/RecoverySystem;-><init>()V
-Landroid/os/Registrant;-><init>(Landroid/os/Handler;ILjava/lang/Object;)V
-Landroid/os/Registrant;->clear()V
-Landroid/os/Registrant;->notifyRegistrant()V
-Landroid/os/Registrant;->notifyRegistrant(Landroid/os/AsyncResult;)V
-Landroid/os/RegistrantList;-><init>()V
-Landroid/os/RegistrantList;->add(Landroid/os/Registrant;)V
-Landroid/os/RegistrantList;->addUnique(Landroid/os/Handler;ILjava/lang/Object;)V
-Landroid/os/RegistrantList;->notifyRegistrants()V
-Landroid/os/RegistrantList;->notifyRegistrants(Landroid/os/AsyncResult;)V
-Landroid/os/RegistrantList;->remove(Landroid/os/Handler;)V
-Landroid/os/RegistrantList;->removeCleared()V
-Landroid/os/RemoteException;->rethrowFromSystemServer()Ljava/lang/RuntimeException;
-Landroid/os/SELinux;->checkSELinuxAccess(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z
-Landroid/os/SELinux;->getFileContext(Ljava/lang/String;)Ljava/lang/String;
-Landroid/os/SELinux;->getPidContext(I)Ljava/lang/String;
-Landroid/os/SELinux;->isSELinuxEnabled()Z
-Landroid/os/SELinux;->isSELinuxEnforced()Z
-Landroid/os/ServiceManager;-><init>()V
-Landroid/os/ServiceManager;->addService(Ljava/lang/String;Landroid/os/IBinder;)V
-Landroid/os/ServiceManager;->checkService(Ljava/lang/String;)Landroid/os/IBinder;
-Landroid/os/ServiceManager;->getIServiceManager()Landroid/os/IServiceManager;
-Landroid/os/ServiceManager;->getService(Ljava/lang/String;)Landroid/os/IBinder;
-Landroid/os/ServiceManager;->listServices()[Ljava/lang/String;
-Landroid/os/ServiceManager;->sCache:Ljava/util/HashMap;
-Landroid/os/ServiceManager;->sServiceManager:Landroid/os/IServiceManager;
-Landroid/os/ServiceManagerNative;->asInterface(Landroid/os/IBinder;)Landroid/os/IServiceManager;
-Landroid/os/ServiceSpecificException;->errorCode:I
-Landroid/os/SharedMemory;->getFd()I
-Landroid/os/StrictMode$Span;->finish()V
-Landroid/os/StrictMode$ThreadPolicy$Builder;->penaltyListener(Landroid/os/StrictMode$OnThreadViolationListener;Ljava/util/concurrent/Executor;)Landroid/os/StrictMode$ThreadPolicy$Builder;
-Landroid/os/StrictMode$VmPolicy$Builder;->penaltyListener(Landroid/os/StrictMode$OnVmViolationListener;Ljava/util/concurrent/Executor;)Landroid/os/StrictMode$VmPolicy$Builder;
-Landroid/os/StrictMode;->conditionallyCheckInstanceCounts()V
-Landroid/os/StrictMode;->disableDeathOnFileUriExposure()V
-Landroid/os/StrictMode;->enterCriticalSpan(Ljava/lang/String;)Landroid/os/StrictMode$Span;
-Landroid/os/StrictMode;->getThreadPolicyMask()I
-Landroid/os/StrictMode;->onBinderStrictModePolicyChange(I)V
-Landroid/os/StrictMode;->violationsBeingTimed:Ljava/lang/ThreadLocal;
-Landroid/os/SystemClock;->elapsedRealtimeClock()Ljava/time/Clock;
-Landroid/os/SystemClock;->uptimeClock()Ljava/time/Clock;
-Landroid/os/SystemClock;->uptimeMillisClock()Ljava/time/Clock;
-Landroid/os/SystemProperties;-><init>()V
-Landroid/os/SystemProperties;->PROP_NAME_MAX:I
-Landroid/os/SystemProperties;->addChangeCallback(Ljava/lang/Runnable;)V
-Landroid/os/SystemProperties;->native_get(Ljava/lang/String;)Ljava/lang/String;
-Landroid/os/SystemProperties;->reportSyspropChanged()V
-Landroid/os/SystemProperties;->set(Ljava/lang/String;Ljava/lang/String;)V
-Landroid/os/SystemService;->start(Ljava/lang/String;)V
-Landroid/os/SystemService;->stop(Ljava/lang/String;)V
-Landroid/os/SystemVibrator;-><init>()V
-Landroid/os/TestLooperManager;->getQueue()Landroid/os/MessageQueue;
-Landroid/os/Trace;->TRACE_TAG_APP:J
-Landroid/os/Trace;->TRACE_TAG_VIEW:J
-Landroid/os/Trace;->asyncTraceBegin(JLjava/lang/String;I)V
-Landroid/os/Trace;->asyncTraceEnd(JLjava/lang/String;I)V
-Landroid/os/Trace;->isTagEnabled(J)Z
-Landroid/os/Trace;->setAppTracingAllowed(Z)V
-Landroid/os/Trace;->traceBegin(JLjava/lang/String;)V
-Landroid/os/Trace;->traceCounter(JLjava/lang/String;I)V
-Landroid/os/Trace;->traceEnd(J)V
-Landroid/os/UpdateLock;->NOW_IS_CONVENIENT:Ljava/lang/String;
-Landroid/os/UpdateLock;->TIMESTAMP:Ljava/lang/String;
-Landroid/os/UpdateLock;->UPDATE_LOCK_CHANGED:Ljava/lang/String;
-Landroid/os/UpdateLock;->acquire()V
-Landroid/os/UpdateLock;->isHeld()Z
-Landroid/os/UpdateLock;->release()V
-Landroid/os/UserHandle;-><init>(I)V
-Landroid/os/UserHandle;->AID_APP_END:I
-Landroid/os/UserHandle;->AID_APP_START:I
-Landroid/os/UserHandle;->AID_CACHE_GID_START:I
-Landroid/os/UserHandle;->AID_ROOT:I
-Landroid/os/UserHandle;->AID_SHARED_GID_START:I
-Landroid/os/UserHandle;->ALL:Landroid/os/UserHandle;
-Landroid/os/UserHandle;->CURRENT:Landroid/os/UserHandle;
-Landroid/os/UserHandle;->CURRENT_OR_SELF:Landroid/os/UserHandle;
-Landroid/os/UserHandle;->ERR_GID:I
-Landroid/os/UserHandle;->MU_ENABLED:Z
-Landroid/os/UserHandle;->OWNER:Landroid/os/UserHandle;
-Landroid/os/UserHandle;->PER_USER_RANGE:I
-Landroid/os/UserHandle;->USER_ALL:I
-Landroid/os/UserHandle;->USER_CURRENT:I
-Landroid/os/UserHandle;->USER_CURRENT_OR_SELF:I
-Landroid/os/UserHandle;->USER_NULL:I
-Landroid/os/UserHandle;->USER_OWNER:I
-Landroid/os/UserHandle;->USER_SERIAL_SYSTEM:I
-Landroid/os/UserHandle;->USER_SYSTEM:I
-Landroid/os/UserHandle;->getAppIdFromSharedAppGid(I)I
-Landroid/os/UserHandle;->getCallingUserId()I
-Landroid/os/UserHandle;->getUid(II)I
-Landroid/os/UserHandle;->getUserId(I)I
-Landroid/os/UserHandle;->isSameApp(II)Z
-Landroid/os/UserManager;->get(Landroid/content/Context;)Landroid/os/UserManager;
-Landroid/os/UserManager;->getBadgedDrawableForUser(Landroid/graphics/drawable/Drawable;Landroid/os/UserHandle;Landroid/graphics/Rect;I)Landroid/graphics/drawable/Drawable;
-Landroid/os/UserManager;->getBadgedIconForUser(Landroid/graphics/drawable/Drawable;Landroid/os/UserHandle;)Landroid/graphics/drawable/Drawable;
-Landroid/os/UserManager;->getBadgedLabelForUser(Ljava/lang/CharSequence;Landroid/os/UserHandle;)Ljava/lang/CharSequence;
-Landroid/os/UserManager;->getMaxSupportedUsers()I
-Landroid/os/UserManager;->getProfiles(I)Ljava/util/List;
-Landroid/os/UserManager;->getUserHandle()I
-Landroid/os/UserManager;->getUserHandle(I)I
-Landroid/os/UserManager;->getUserIcon(I)Landroid/graphics/Bitmap;
-Landroid/os/UserManager;->getUserInfo(I)Landroid/content/pm/UserInfo;
-Landroid/os/UserManager;->getUserSerialNumber(I)I
-Landroid/os/UserManager;->getUserStartRealtime()J
-Landroid/os/UserManager;->getUserUnlockRealtime()J
-Landroid/os/UserManager;->getUsers()Ljava/util/List;
-Landroid/os/UserManager;->hasBaseUserRestriction(Ljava/lang/String;Landroid/os/UserHandle;)Z
-Landroid/os/UserManager;->hasUserRestriction(Ljava/lang/String;Landroid/os/UserHandle;)Z
-Landroid/os/UserManager;->isAdminUser()Z
-Landroid/os/UserManager;->isLinkedUser()Z
-Landroid/os/UserManager;->isUserUnlocked(I)Z
-Landroid/os/UserManager;->mService:Landroid/os/IUserManager;
-Landroid/os/VintfObject;->getHalNamesAndVersions()[Ljava/lang/String;
-Landroid/os/VintfObject;->getSepolicyVersion()Ljava/lang/String;
-Landroid/os/VintfObject;->getTargetFrameworkCompatibilityMatrixVersion()Ljava/lang/Long;
-Landroid/os/VintfObject;->getVndkSnapshots()Ljava/util/Map;
-Landroid/os/VintfObject;->report()[Ljava/lang/String;
-Landroid/os/VintfRuntimeInfo;->getCpuInfo()Ljava/lang/String;
-Landroid/os/VintfRuntimeInfo;->getHardwareId()Ljava/lang/String;
-Landroid/os/VintfRuntimeInfo;->getKernelVersion()Ljava/lang/String;
-Landroid/os/VintfRuntimeInfo;->getNodeName()Ljava/lang/String;
-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;->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;->size()I
-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/Parcel;)V
-Landroid/os/health/HealthStatsParceler;-><init>(Landroid/os/health/HealthStatsWriter;)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;->from(Landroid/content/Context;)Landroid/os/health/SystemHealthManager;
-Landroid/os/storage/DiskInfo;->getDescription()Ljava/lang/String;
-Landroid/os/storage/DiskInfo;->getId()Ljava/lang/String;
-Landroid/os/storage/DiskInfo;->isSd()Z
-Landroid/os/storage/DiskInfo;->isUsb()Z
-Landroid/os/storage/IStorageManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-Landroid/os/storage/IStorageManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/os/storage/IStorageManager;
-Landroid/os/storage/StorageEventListener;-><init>()V
-Landroid/os/storage/StorageManager;->findVolumeById(Ljava/lang/String;)Landroid/os/storage/VolumeInfo;
-Landroid/os/storage/StorageManager;->findVolumeByUuid(Ljava/lang/String;)Landroid/os/storage/VolumeInfo;
-Landroid/os/storage/StorageManager;->from(Landroid/content/Context;)Landroid/os/storage/StorageManager;
-Landroid/os/storage/StorageManager;->getBestVolumeDescription(Landroid/os/storage/VolumeInfo;)Ljava/lang/String;
-Landroid/os/storage/StorageManager;->getDisks()Ljava/util/List;
-Landroid/os/storage/StorageManager;->getPrimaryVolume()Landroid/os/storage/StorageVolume;
-Landroid/os/storage/StorageManager;->getStorageBytesUntilLow(Ljava/io/File;)J
-Landroid/os/storage/StorageManager;->getStorageFullBytes(Ljava/io/File;)J
-Landroid/os/storage/StorageManager;->getStorageLowBytes(Ljava/io/File;)J
-Landroid/os/storage/StorageManager;->getVolumeList()[Landroid/os/storage/StorageVolume;
-Landroid/os/storage/StorageManager;->getVolumeList(II)[Landroid/os/storage/StorageVolume;
-Landroid/os/storage/StorageManager;->getVolumePaths()[Ljava/lang/String;
-Landroid/os/storage/StorageManager;->getVolumeState(Ljava/lang/String;)Ljava/lang/String;
-Landroid/os/storage/StorageManager;->getVolumes()Ljava/util/List;
-Landroid/os/storage/StorageManager;->registerListener(Landroid/os/storage/StorageEventListener;)V
-Landroid/os/storage/StorageManager;->unregisterListener(Landroid/os/storage/StorageEventListener;)V
-Landroid/os/storage/StorageVolume;->allowMassStorage()Z
-Landroid/os/storage/StorageVolume;->getId()Ljava/lang/String;
-Landroid/os/storage/StorageVolume;->getMaxFileSize()J
-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;->mPath:Ljava/io/File;
-Landroid/os/storage/VolumeInfo;->TYPE_EMULATED:I
-Landroid/os/storage/VolumeInfo;->TYPE_PUBLIC:I
-Landroid/os/storage/VolumeInfo;->buildStorageVolume(Landroid/content/Context;IZ)Landroid/os/storage/StorageVolume;
-Landroid/os/storage/VolumeInfo;->getDisk()Landroid/os/storage/DiskInfo;
-Landroid/os/storage/VolumeInfo;->getEnvironmentForState(I)Ljava/lang/String;
-Landroid/os/storage/VolumeInfo;->getFsUuid()Ljava/lang/String;
-Landroid/os/storage/VolumeInfo;->getId()Ljava/lang/String;
-Landroid/os/storage/VolumeInfo;->getPath()Ljava/io/File;
-Landroid/os/storage/VolumeInfo;->getState()I
-Landroid/os/storage/VolumeInfo;->getType()I
-Landroid/os/storage/VolumeInfo;->isPrimary()Z
-Landroid/os/storage/VolumeInfo;->isVisible()Z
-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/ListPreference;->mClickedDialogEntryIndex:I
-Landroid/preference/Preference;->onKey(Landroid/view/View;ILandroid/view/KeyEvent;)Z
-Landroid/preference/Preference;->performClick(Landroid/preference/PreferenceScreen;)V
-Landroid/preference/PreferenceActivity;->mPreferenceManager:Landroid/preference/PreferenceManager;
-Landroid/preference/PreferenceActivity;->mPrefsContainer:Landroid/view/ViewGroup;
-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;->getEditor()Landroid/content/SharedPreferences$Editor;
-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;->mOnPreferenceTreeClickListener:Landroid/preference/PreferenceManager$OnPreferenceTreeClickListener;
-Landroid/preference/PreferenceManager;->mSharedPreferences:Landroid/content/SharedPreferences;
-Landroid/preference/PreferenceManager;->registerOnActivityDestroyListener(Landroid/preference/PreferenceManager$OnActivityDestroyListener;)V
-Landroid/preference/PreferenceManager;->registerOnActivityStopListener(Landroid/preference/PreferenceManager$OnActivityStopListener;)V
-Landroid/preference/PreferenceManager;->setFragment(Landroid/preference/PreferenceFragment;)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;->unregisterOnActivityStopListener(Landroid/preference/PreferenceManager$OnActivityStopListener;)V
-Landroid/preference/PreferenceScreen;->mRootAdapter:Landroid/widget/ListAdapter;
-Landroid/print/PrintDocumentAdapter$LayoutResultCallback;-><init>()V
-Landroid/print/PrintDocumentAdapter$WriteResultCallback;-><init>()V
-Landroid/print/PrintJobInfo;->getAdvancedOptions()Landroid/os/Bundle;
-Landroid/print/PrintJobInfo;->getDocumentInfo()Landroid/print/PrintDocumentInfo;
-Landroid/print/PrinterId;->getServiceName()Landroid/content/ComponentName;
-Landroid/provider/Browser$BookmarkColumns;
-Landroid/provider/Browser$BookmarkColumns;-><init>()V
-Landroid/provider/Browser$BookmarkColumns;->BOOKMARK:Ljava/lang/String;
-Landroid/provider/Browser$BookmarkColumns;->CREATED:Ljava/lang/String;
-Landroid/provider/Browser$BookmarkColumns;->DATE:Ljava/lang/String;
-Landroid/provider/Browser$BookmarkColumns;->FAVICON:Ljava/lang/String;
-Landroid/provider/Browser$BookmarkColumns;->TITLE:Ljava/lang/String;
-Landroid/provider/Browser$BookmarkColumns;->URL:Ljava/lang/String;
-Landroid/provider/Browser$BookmarkColumns;->VISITS:Ljava/lang/String;
-Landroid/provider/Browser$SearchColumns;
-Landroid/provider/Browser$SearchColumns;-><init>()V
-Landroid/provider/Browser$SearchColumns;->DATE:Ljava/lang/String;
-Landroid/provider/Browser$SearchColumns;->SEARCH:Ljava/lang/String;
-Landroid/provider/Browser$SearchColumns;->URL:Ljava/lang/String;
-Landroid/provider/Browser;->BOOKMARKS_URI:Landroid/net/Uri;
-Landroid/provider/Browser;->HISTORY_PROJECTION:[Ljava/lang/String;
-Landroid/provider/Browser;->HISTORY_PROJECTION_BOOKMARK_INDEX:I
-Landroid/provider/Browser;->HISTORY_PROJECTION_DATE_INDEX:I
-Landroid/provider/Browser;->HISTORY_PROJECTION_FAVICON_INDEX:I
-Landroid/provider/Browser;->HISTORY_PROJECTION_ID_INDEX:I
-Landroid/provider/Browser;->HISTORY_PROJECTION_TITLE_INDEX:I
-Landroid/provider/Browser;->HISTORY_PROJECTION_URL_INDEX:I
-Landroid/provider/Browser;->HISTORY_PROJECTION_VISITS_INDEX:I
-Landroid/provider/Browser;->SEARCHES_PROJECTION:[Ljava/lang/String;
-Landroid/provider/Browser;->SEARCHES_PROJECTION_DATE_INDEX:I
-Landroid/provider/Browser;->SEARCHES_PROJECTION_SEARCH_INDEX:I
-Landroid/provider/Browser;->SEARCHES_URI:Landroid/net/Uri;
-Landroid/provider/Browser;->TRUNCATE_HISTORY_PROJECTION:[Ljava/lang/String;
-Landroid/provider/Browser;->TRUNCATE_HISTORY_PROJECTION_ID_INDEX:I
-Landroid/provider/Browser;->TRUNCATE_N_OLDEST:I
-Landroid/provider/Browser;->addSearchUrl(Landroid/content/ContentResolver;Ljava/lang/String;)V
-Landroid/provider/Browser;->canClearHistory(Landroid/content/ContentResolver;)Z
-Landroid/provider/Browser;->clearHistory(Landroid/content/ContentResolver;)V
-Landroid/provider/Browser;->clearSearches(Landroid/content/ContentResolver;)V
-Landroid/provider/Browser;->deleteFromHistory(Landroid/content/ContentResolver;Ljava/lang/String;)V
-Landroid/provider/Browser;->deleteHistoryTimeFrame(Landroid/content/ContentResolver;JJ)V
-Landroid/provider/Browser;->getAllBookmarks(Landroid/content/ContentResolver;)Landroid/database/Cursor;
-Landroid/provider/Browser;->getAllVisitedUrls(Landroid/content/ContentResolver;)Landroid/database/Cursor;
-Landroid/provider/Browser;->getVisitedHistory(Landroid/content/ContentResolver;)[Ljava/lang/String;
-Landroid/provider/Browser;->requestAllIcons(Landroid/content/ContentResolver;Ljava/lang/String;Landroid/webkit/WebIconDatabase$IconListener;)V
-Landroid/provider/Browser;->saveBookmark(Landroid/content/Context;Ljava/lang/String;Ljava/lang/String;)V
-Landroid/provider/Browser;->sendString(Landroid/content/Context;Ljava/lang/String;Ljava/lang/String;)V
-Landroid/provider/Browser;->truncateHistory(Landroid/content/ContentResolver;)V
-Landroid/provider/Browser;->updateVisitedHistory(Landroid/content/ContentResolver;Ljava/lang/String;Z)V
-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$Events;->PROVIDER_WRITABLE_COLUMNS:[Ljava/lang/String;
-Landroid/provider/ContactsContract$CommonDataKinds$Phone;->getDisplayLabel(Landroid/content/Context;ILjava/lang/CharSequence;)Ljava/lang/CharSequence;
-Landroid/provider/ContactsContract$Contacts$StreamItems;
-Landroid/provider/ContactsContract$Contacts$StreamItems;->CONTENT_DIRECTORY:Ljava/lang/String;
-Landroid/provider/ContactsContract$RawContacts$StreamItems;
-Landroid/provider/ContactsContract$RawContacts$StreamItems;->CONTENT_DIRECTORY:Ljava/lang/String;
-Landroid/provider/ContactsContract$StreamItemPhotos;
-Landroid/provider/ContactsContract$StreamItemPhotos;->PHOTO:Ljava/lang/String;
-Landroid/provider/ContactsContract$StreamItemPhotosColumns;
-Landroid/provider/ContactsContract$StreamItemPhotosColumns;->PHOTO_FILE_ID:Ljava/lang/String;
-Landroid/provider/ContactsContract$StreamItemPhotosColumns;->PHOTO_URI:Ljava/lang/String;
-Landroid/provider/ContactsContract$StreamItemPhotosColumns;->SORT_INDEX:Ljava/lang/String;
-Landroid/provider/ContactsContract$StreamItemPhotosColumns;->STREAM_ITEM_ID:Ljava/lang/String;
-Landroid/provider/ContactsContract$StreamItemPhotosColumns;->SYNC1:Ljava/lang/String;
-Landroid/provider/ContactsContract$StreamItemPhotosColumns;->SYNC2:Ljava/lang/String;
-Landroid/provider/ContactsContract$StreamItemPhotosColumns;->SYNC3:Ljava/lang/String;
-Landroid/provider/ContactsContract$StreamItemPhotosColumns;->SYNC4:Ljava/lang/String;
-Landroid/provider/ContactsContract$StreamItems$StreamItemPhotos;
-Landroid/provider/ContactsContract$StreamItems$StreamItemPhotos;->CONTENT_DIRECTORY:Ljava/lang/String;
-Landroid/provider/ContactsContract$StreamItems$StreamItemPhotos;->CONTENT_ITEM_TYPE:Ljava/lang/String;
-Landroid/provider/ContactsContract$StreamItems$StreamItemPhotos;->CONTENT_TYPE:Ljava/lang/String;
-Landroid/provider/ContactsContract$StreamItems;
-Landroid/provider/ContactsContract$StreamItems;->CONTENT_ITEM_TYPE:Ljava/lang/String;
-Landroid/provider/ContactsContract$StreamItems;->CONTENT_LIMIT_URI:Landroid/net/Uri;
-Landroid/provider/ContactsContract$StreamItems;->CONTENT_PHOTO_URI:Landroid/net/Uri;
-Landroid/provider/ContactsContract$StreamItems;->CONTENT_TYPE:Ljava/lang/String;
-Landroid/provider/ContactsContract$StreamItems;->CONTENT_URI:Landroid/net/Uri;
-Landroid/provider/ContactsContract$StreamItems;->MAX_ITEMS:Ljava/lang/String;
-Landroid/provider/ContactsContract$StreamItemsColumns;
-Landroid/provider/ContactsContract$StreamItemsColumns;->ACCOUNT_NAME:Ljava/lang/String;
-Landroid/provider/ContactsContract$StreamItemsColumns;->ACCOUNT_TYPE:Ljava/lang/String;
-Landroid/provider/ContactsContract$StreamItemsColumns;->COMMENTS:Ljava/lang/String;
-Landroid/provider/ContactsContract$StreamItemsColumns;->CONTACT_ID:Ljava/lang/String;
-Landroid/provider/ContactsContract$StreamItemsColumns;->CONTACT_LOOKUP_KEY:Ljava/lang/String;
-Landroid/provider/ContactsContract$StreamItemsColumns;->DATA_SET:Ljava/lang/String;
-Landroid/provider/ContactsContract$StreamItemsColumns;->RAW_CONTACT_ID:Ljava/lang/String;
-Landroid/provider/ContactsContract$StreamItemsColumns;->RAW_CONTACT_SOURCE_ID:Ljava/lang/String;
-Landroid/provider/ContactsContract$StreamItemsColumns;->RES_ICON:Ljava/lang/String;
-Landroid/provider/ContactsContract$StreamItemsColumns;->RES_LABEL:Ljava/lang/String;
-Landroid/provider/ContactsContract$StreamItemsColumns;->RES_PACKAGE:Ljava/lang/String;
-Landroid/provider/ContactsContract$StreamItemsColumns;->SYNC1:Ljava/lang/String;
-Landroid/provider/ContactsContract$StreamItemsColumns;->SYNC2:Ljava/lang/String;
-Landroid/provider/ContactsContract$StreamItemsColumns;->SYNC3:Ljava/lang/String;
-Landroid/provider/ContactsContract$StreamItemsColumns;->SYNC4:Ljava/lang/String;
-Landroid/provider/ContactsContract$StreamItemsColumns;->TEXT:Ljava/lang/String;
-Landroid/provider/ContactsContract$StreamItemsColumns;->TIMESTAMP:Ljava/lang/String;
-Landroid/provider/Downloads$Impl$RequestHeaders;->INSERT_KEY_PREFIX:Ljava/lang/String;
-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/Settings$ContentProviderHolder;->mContentProvider:Landroid/content/IContentProvider;
-Landroid/provider/Settings$Global;->CONTACT_METADATA_SYNC:Ljava/lang/String;
-Landroid/provider/Settings$Global;->ENABLE_ACCESSIBILITY_GLOBAL_GESTURE_ENABLED:Ljava/lang/String;
-Landroid/provider/Settings$Global;->PACKAGE_VERIFIER_ENABLE:Ljava/lang/String;
-Landroid/provider/Settings$Global;->getStringForUser(Landroid/content/ContentResolver;Ljava/lang/String;I)Ljava/lang/String;
-Landroid/provider/Settings$Global;->sNameValueCache:Landroid/provider/Settings$NameValueCache;
-Landroid/provider/Settings$NameValueCache;->mProviderHolder:Landroid/provider/Settings$ContentProviderHolder;
-Landroid/provider/Settings$Secure;->ACCESSIBILITY_AUTOCLICK_ENABLED: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;->ENABLED_NOTIFICATION_LISTENERS:Ljava/lang/String;
-Landroid/provider/Settings$Secure;->INCALL_POWER_BUTTON_BEHAVIOR:Ljava/lang/String;
-Landroid/provider/Settings$Secure;->LONG_PRESS_TIMEOUT:Ljava/lang/String;
-Landroid/provider/Settings$Secure;->PACKAGE_VERIFIER_USER_CONSENT:Ljava/lang/String;
-Landroid/provider/Settings$Secure;->getStringForUser(Landroid/content/ContentResolver;Ljava/lang/String;I)Ljava/lang/String;
-Landroid/provider/Settings$Secure;->putIntForUser(Landroid/content/ContentResolver;Ljava/lang/String;II)Z
-Landroid/provider/Settings$Secure;->sNameValueCache:Landroid/provider/Settings$NameValueCache;
-Landroid/provider/Settings$System;->AIRPLANE_MODE_TOGGLEABLE_RADIOS:Ljava/lang/String;
-Landroid/provider/Settings$System;->APPEND_FOR_LAST_AUDIBLE:Ljava/lang/String;
-Landroid/provider/Settings$System;->HEARING_AID:Ljava/lang/String;
-Landroid/provider/Settings$System;->MASTER_MONO:Ljava/lang/String;
-Landroid/provider/Settings$System;->SCREEN_AUTO_BRIGHTNESS_ADJ:Ljava/lang/String;
-Landroid/provider/Settings$System;->VOLUME_ALARM:Ljava/lang/String;
-Landroid/provider/Settings$System;->VOLUME_BLUETOOTH_SCO:Ljava/lang/String;
-Landroid/provider/Settings$System;->VOLUME_MUSIC:Ljava/lang/String;
-Landroid/provider/Settings$System;->VOLUME_NOTIFICATION:Ljava/lang/String;
-Landroid/provider/Settings$System;->VOLUME_RING:Ljava/lang/String;
-Landroid/provider/Settings$System;->VOLUME_SETTINGS:[Ljava/lang/String;
-Landroid/provider/Settings$System;->VOLUME_SYSTEM:Ljava/lang/String;
-Landroid/provider/Settings$System;->VOLUME_VOICE:Ljava/lang/String;
-Landroid/provider/Settings$System;->getStringForUser(Landroid/content/ContentResolver;Ljava/lang/String;I)Ljava/lang/String;
-Landroid/provider/Settings$System;->putStringForUser(Landroid/content/ContentResolver;Ljava/lang/String;Ljava/lang/String;I)Z
-Landroid/provider/Settings$System;->sNameValueCache:Landroid/provider/Settings$NameValueCache;
-Landroid/provider/Settings;->isCallingPackageAllowedToDrawOverlays(Landroid/content/Context;ILjava/lang/String;Z)Z
-Landroid/provider/Settings;->isCallingPackageAllowedToWriteSettings(Landroid/content/Context;ILjava/lang/String;Z)Z
-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$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$Intents;->SMS_EMERGENCY_CB_RECEIVED_ACTION:Ljava/lang/String;
-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/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/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/RenderScriptCacheDir;->mCacheDir:Ljava/io/File;
-Landroid/renderscript/RenderScriptCacheDir;->setupDiskCache(Ljava/io/File;)V
-Landroid/security/KeyStore;->getInstance()Landroid/security/KeyStore;
-Landroid/security/keystore/AndroidKeyStoreProvider;->getKeyStoreOperationHandle(Ljava/lang/Object;)J
-Landroid/security/keystore/recovery/KeyChainSnapshot;->getTrustedHardwarePublicKey()[B
-Landroid/security/keystore/recovery/RecoveryController;->generateAndStoreKey(Ljava/lang/String;[B)[B
-Landroid/security/keystore/recovery/RecoveryController;->generateKey(Ljava/lang/String;[B)Ljava/security/Key;
-Landroid/security/keystore/recovery/RecoveryController;->getAliases(Ljava/lang/String;)Ljava/util/List;
-Landroid/security/keystore/recovery/RecoveryController;->getRecoveryData()Landroid/security/keystore/recovery/KeyChainSnapshot;
-Landroid/security/keystore/recovery/RecoveryController;->getRecoveryStatus(Ljava/lang/String;Ljava/lang/String;)I
-Landroid/security/keystore/recovery/RecoveryController;->initRecoveryService(Ljava/lang/String;[B)V
-Landroid/security/keystore/recovery/RecoveryController;->setRecoveryStatus(Ljava/lang/String;Ljava/lang/String;I)V
-Landroid/security/keystore/recovery/RecoverySession;->recoverKeys([BLjava/util/List;)Ljava/util/Map;
-Landroid/security/keystore/recovery/RecoverySession;->start(Ljava/security/cert/CertPath;[B[BLjava/util/List;)[B
-Landroid/security/keystore/recovery/RecoverySession;->start([B[B[BLjava/util/List;)[B
-Landroid/security/keystore/recovery/WrappedApplicationKey$Builder;->setAccount([B)Landroid/security/keystore/recovery/WrappedApplicationKey$Builder;
-Landroid/security/keystore/recovery/WrappedApplicationKey;->getAccount()[B
-Landroid/security/net/config/RootTrustManager;->checkServerTrusted([Ljava/security/cert/X509Certificate;Ljava/lang/String;Ljava/lang/String;)Ljava/util/List;
-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/media/IMediaBrowserServiceCallbacks$Stub;->asInterface(Landroid/os/IBinder;)Landroid/service/media/IMediaBrowserServiceCallbacks;
-Landroid/service/media/IMediaBrowserServiceCallbacks;->onConnect(Ljava/lang/String;Landroid/media/session/MediaSession$Token;Landroid/os/Bundle;)V
-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/NotificationListenerService$Ranking;->getAdditionalPeople()Ljava/util/List;
-Landroid/service/notification/NotificationListenerService$Ranking;->getSnoozeCriteria()Ljava/util/List;
-Landroid/service/notification/NotificationListenerService;->TRIM_FULL:I
-Landroid/service/notification/NotificationListenerService;->TRIM_LIGHT:I
-Landroid/service/notification/NotificationListenerService;->getActiveNotifications(I)[Landroid/service/notification/StatusBarNotification;
-Landroid/service/notification/NotificationListenerService;->getActiveNotifications([Ljava/lang/String;I)[Landroid/service/notification/StatusBarNotification;
-Landroid/service/notification/NotificationListenerService;->isBound()Z
-Landroid/service/notification/NotificationListenerService;->mHandler:Landroid/os/Handler;
-Landroid/service/notification/NotificationListenerService;->registerAsSystemService(Landroid/content/Context;Landroid/content/ComponentName;I)V
-Landroid/service/notification/NotificationListenerService;->setOnNotificationPostedTrim(I)V
-Landroid/service/notification/NotificationListenerService;->snoozeNotification(Ljava/lang/String;Ljava/lang/String;)V
-Landroid/service/notification/NotificationListenerService;->unregisterAsSystemService()V
-Landroid/service/notification/StatusBarNotification;->getInitialPid()I
-Landroid/service/notification/StatusBarNotification;->getUid()I
-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;->getVr2dDisplayId()I
-Landroid/service/vr/VrListenerService;->onCurrentVrActivityChanged(Landroid/content/ComponentName;ZI)V
-Landroid/service/wallpaper/WallpaperService$Engine;->setFixedSizeAllowed(Z)V
-Landroid/speech/tts/TextToSpeech;->getCurrentEngine()Ljava/lang/String;
-Landroid/speech/tts/UtteranceProgressListener;->onUtteranceRangeStart(Ljava/lang/String;II)V
-Landroid/system/Int32Ref;->value:I
-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
-Landroid/system/Os;->sendto(Ljava/io/FileDescriptor;[BIIILjava/net/SocketAddress;)I
-Landroid/system/Os;->setsockoptIfreq(Ljava/io/FileDescriptor;IILjava/lang/String;)V
-Landroid/system/Os;->setsockoptTimeval(Ljava/io/FileDescriptor;IILandroid/system/StructTimeval;)V
-Landroid/system/OsConstants;-><init>()V
-Landroid/system/OsConstants;->AF_NETLINK:I
-Landroid/system/OsConstants;->AF_PACKET:I
-Landroid/system/OsConstants;->ARPHRD_ETHER:I
-Landroid/system/OsConstants;->ARPHRD_LOOPBACK:I
-Landroid/system/OsConstants;->CAP_TO_INDEX(I)I
-Landroid/system/OsConstants;->CAP_TO_MASK(I)I
-Landroid/system/OsConstants;->ENONET:I
-Landroid/system/OsConstants;->ETH_P_ALL:I
-Landroid/system/OsConstants;->ETH_P_ARP:I
-Landroid/system/OsConstants;->ETH_P_IP:I
-Landroid/system/OsConstants;->ETH_P_IPV6:I
-Landroid/system/OsConstants;->EUSERS:I
-Landroid/system/OsConstants;->ICMP6_ECHO_REPLY:I
-Landroid/system/OsConstants;->ICMP6_ECHO_REQUEST:I
-Landroid/system/OsConstants;->ICMP_ECHO:I
-Landroid/system/OsConstants;->ICMP_ECHOREPLY:I
-Landroid/system/OsConstants;->IP_MULTICAST_ALL:I
-Landroid/system/OsConstants;->IP_RECVTOS:I
-Landroid/system/OsConstants;->MAP_POPULATE:I
-Landroid/system/OsConstants;->NETLINK_NETFILTER:I
-Landroid/system/OsConstants;->NETLINK_ROUTE:I
-Landroid/system/OsConstants;->O_DIRECT:I
-Landroid/system/OsConstants;->PR_CAP_AMBIENT:I
-Landroid/system/OsConstants;->PR_CAP_AMBIENT_RAISE:I
-Landroid/system/OsConstants;->RLIMIT_NOFILE:I
-Landroid/system/OsConstants;->RTMGRP_IPV4_IFADDR:I
-Landroid/system/OsConstants;->RTMGRP_IPV4_MROUTE:I
-Landroid/system/OsConstants;->RTMGRP_IPV4_ROUTE:I
-Landroid/system/OsConstants;->RTMGRP_IPV4_RULE:I
-Landroid/system/OsConstants;->RTMGRP_IPV6_IFADDR:I
-Landroid/system/OsConstants;->RTMGRP_IPV6_IFINFO:I
-Landroid/system/OsConstants;->RTMGRP_IPV6_MROUTE:I
-Landroid/system/OsConstants;->RTMGRP_IPV6_PREFIX:I
-Landroid/system/OsConstants;->RTMGRP_IPV6_ROUTE:I
-Landroid/system/OsConstants;->RTMGRP_LINK:I
-Landroid/system/OsConstants;->RTMGRP_NEIGH:I
-Landroid/system/OsConstants;->RTMGRP_NOTIFY:I
-Landroid/system/OsConstants;->RTMGRP_TC:I
-Landroid/system/OsConstants;->SO_DOMAIN:I
-Landroid/system/OsConstants;->SO_PROTOCOL:I
-Landroid/system/OsConstants;->SPLICE_F_MORE:I
-Landroid/system/OsConstants;->SPLICE_F_MOVE:I
-Landroid/system/OsConstants;->SPLICE_F_NONBLOCK:I
-Landroid/system/OsConstants;->TIOCOUTQ:I
-Landroid/system/OsConstants;->UDP_ENCAP:I
-Landroid/system/OsConstants;->UDP_ENCAP_ESPINUDP:I
-Landroid/system/OsConstants;->UDP_ENCAP_ESPINUDP_NON_IKE:I
-Landroid/system/OsConstants;->UNIX_PATH_MAX:I
-Landroid/system/OsConstants;->XATTR_CREATE:I
-Landroid/system/OsConstants;->XATTR_REPLACE:I
-Landroid/system/OsConstants;->_LINUX_CAPABILITY_VERSION_3:I
-Landroid/system/OsConstants;->initConstants()V
-Landroid/system/OsConstants;->placeholder()I
-Landroid/system/PacketSocketAddress;-><init>(I[B)V
-Landroid/system/PacketSocketAddress;-><init>(SI)V
-Landroid/system/StructTimeval;->fromMillis(J)Landroid/system/StructTimeval;
-Landroid/telecom/AudioState;->isMuted:Z
-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;->EXTRA_IS_HANDOVER:Ljava/lang/String;
-Landroid/telecom/TelecomManager;->from(Landroid/content/Context;)Landroid/telecom/TelecomManager;
-Landroid/telecom/TelecomManager;->getUserSelectedOutgoingPhoneAccount()Landroid/telecom/PhoneAccountHandle;
-Landroid/telecom/TelecomManager;->setUserSelectedOutgoingPhoneAccount(Landroid/telecom/PhoneAccountHandle;)V
-Landroid/telecom/VideoProfile$CameraCapabilities;-><init>(IIZF)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/NetworkScan;->stop()V
-Landroid/telephony/PhoneNumberUtils;->formatNumber(Ljava/lang/String;I)Ljava/lang/String;
-Landroid/telephony/PhoneNumberUtils;->isEmergencyNumber(ILjava/lang/String;)Z
-Landroid/telephony/PhoneNumberUtils;->isLocalEmergencyNumber(Landroid/content/Context;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/PhoneStateListener;->mSubId:Ljava/lang/Integer;
-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;->newFromBundle(Landroid/os/Bundle;)Landroid/telephony/ServiceState;
-Landroid/telephony/ServiceState;->rilRadioTechnologyToString(I)Ljava/lang/String;
-Landroid/telephony/SignalStrength;-><init>()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;->getAsuLevel()I
-Landroid/telephony/SignalStrength;->getCdmaLevel()I
-Landroid/telephony/SignalStrength;->getDbm()I
-Landroid/telephony/SignalStrength;->getGsmDbm()I
-Landroid/telephony/SignalStrength;->getLteDbm()I
-Landroid/telephony/SignalStrength;->getLteRsrp()I
-Landroid/telephony/SignalStrength;->getLteRsrq()I
-Landroid/telephony/SignalStrength;->getLteRssnr()I
-Landroid/telephony/SignalStrength;->getLteSignalStrength()I
-Landroid/telephony/SignalStrength;->mGsmBitErrorRate:I
-Landroid/telephony/SignalStrength;->mGsmSignalStrength:I
-Landroid/telephony/SignalStrength;->mLteCqi:I
-Landroid/telephony/SignalStrength;->mLteRsrp:I
-Landroid/telephony/SignalStrength;->mLteRsrq:I
-Landroid/telephony/SignalStrength;->mLteRssnr:I
-Landroid/telephony/SignalStrength;->mLteSignalStrength: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/SmsMessage;->getSubId()I
-Landroid/telephony/SmsMessage;->mWrappedSmsMessage:Lcom/android/internal/telephony/SmsMessageBase;
-Landroid/telephony/SubscriptionInfo;->setDisplayName(Ljava/lang/CharSequence;)V
-Landroid/telephony/SubscriptionInfo;->setIconTint(I)V
-Landroid/telephony/SubscriptionManager;->clearDefaultsForInactiveSubIds()V
-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;->getDefaultVoicePhoneId()I
-Landroid/telephony/SubscriptionManager;->getDefaultVoiceSubscriptionInfo()Landroid/telephony/SubscriptionInfo;
-Landroid/telephony/SubscriptionManager;->getPhoneId(I)I
-Landroid/telephony/SubscriptionManager;->getResourcesForSubId(Landroid/content/Context;I)Landroid/content/res/Resources;
-Landroid/telephony/SubscriptionManager;->getSlotIndex(I)I
-Landroid/telephony/SubscriptionManager;->getSubId(I)[I
-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;->setDefaultDataSubId(I)V
-Landroid/telephony/SubscriptionManager;->setDefaultSmsSubId(I)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;-><init>()V
-Landroid/telephony/TelephonyManager;-><init>(Landroid/content/Context;)V
-Landroid/telephony/TelephonyManager;->from(Landroid/content/Context;)Landroid/telephony/TelephonyManager;
-Landroid/telephony/TelephonyManager;->getCallState(I)I
-Landroid/telephony/TelephonyManager;->getDataNetworkType(I)I
-Landroid/telephony/TelephonyManager;->getDefault()Landroid/telephony/TelephonyManager;
-Landroid/telephony/TelephonyManager;->getGroupIdLevel1(I)Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getITelephony()Lcom/android/internal/telephony/ITelephony;
-Landroid/telephony/TelephonyManager;->getIntAtIndex(Landroid/content/ContentResolver;Ljava/lang/String;I)I
-Landroid/telephony/TelephonyManager;->getIsimDomain()Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getLine1Number(I)Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getMultiSimConfiguration()Landroid/telephony/TelephonyManager$MultiSimVariants;
-Landroid/telephony/TelephonyManager;->getNetworkClass(I)I
-Landroid/telephony/TelephonyManager;->getNetworkCountryIso(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()Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getNetworkTypeName(I)Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getPhoneType(I)I
-Landroid/telephony/TelephonyManager;->getPreferredNetworkType(I)I
-Landroid/telephony/TelephonyManager;->getServiceStateForSubscriber(I)Landroid/telephony/ServiceState;
-Landroid/telephony/TelephonyManager;->getSimCount()I
-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(I)Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getSimOperatorNumericForPhone(I)Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getSimSerialNumber(I)Ljava/lang/String;
-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;->getVoiceMessageCount()I
-Landroid/telephony/TelephonyManager;->getVoiceNetworkType(I)I
-Landroid/telephony/TelephonyManager;->hasIccCard(I)Z
-Landroid/telephony/TelephonyManager;->isImsRegistered()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;->nvResetConfig(I)Z
-Landroid/telephony/TelephonyManager;->putIntAtIndex(Landroid/content/ContentResolver;Ljava/lang/String;II)Z
-Landroid/telephony/TelephonyManager;->requestNetworkScan(Landroid/telephony/NetworkScanRequest;Landroid/telephony/TelephonyScanManager$NetworkScanCallback;)Landroid/telephony/NetworkScan;
-Landroid/telephony/TelephonyManager;->setPreferredNetworkType(II)Z
-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/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/ims/compat/ImsService;-><init>()V
-Landroid/telephony/ims/compat/ImsService;->mImsServiceController:Landroid/os/IBinder;
-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/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/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;
-Landroid/telephony/mbms/vendor/IMbmsStreamingService;->getPlaybackUri(ILjava/lang/String;)Landroid/net/Uri;
-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/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;->sStaticLayout:Landroid/text/StaticLayout;
-Landroid/text/Html;->withinStyle(Ljava/lang/StringBuilder;Ljava/lang/CharSequence;II)V
-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;->getPrimaryHorizontal(IZ)F
-Landroid/text/SpanSet;->spans:[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;->mSpanStarts:[I
-Landroid/text/SpannableStringBuilder;->mSpans:[Ljava/lang/Object;
-Landroid/text/SpannableStringInternal;-><init>(Ljava/lang/CharSequence;II)V
-Landroid/text/SpannableStringInternal;->COLUMNS:I
-Landroid/text/SpannableStringInternal;->EMPTY:[Ljava/lang/Object;
-Landroid/text/SpannableStringInternal;->END:I
-Landroid/text/SpannableStringInternal;->FLAGS:I
-Landroid/text/SpannableStringInternal;->START:I
-Landroid/text/SpannableStringInternal;->charAt(I)C
-Landroid/text/SpannableStringInternal;->checkRange(Ljava/lang/String;II)V
-Landroid/text/SpannableStringInternal;->copySpans(Landroid/text/SpannableStringInternal;II)V
-Landroid/text/SpannableStringInternal;->copySpans(Landroid/text/Spanned;II)V
-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;->getSpanStart(Ljava/lang/Object;)I
-Landroid/text/SpannableStringInternal;->getSpans(IILjava/lang/Class;)[Ljava/lang/Object;
-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/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;->getHeight(Z)I
-Landroid/text/StaticLayout;->mColumns:I
-Landroid/text/StaticLayout;->mLineCount:I
-Landroid/text/StaticLayout;->mLines:[I
-Landroid/text/StaticLayout;->mMaximumVisibleLineCount:I
-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/TextUtils$TruncateAt;->END_SMALL:Landroid/text/TextUtils$TruncateAt;
-Landroid/text/TextUtils;->isPrintableAsciiOnly(Ljava/lang/CharSequence;)Z
-Landroid/text/format/DateFormat;->AM_PM:C
-Landroid/text/format/DateFormat;->CAPITAL_AM_PM:C
-Landroid/text/format/DateFormat;->DATE:C
-Landroid/text/format/DateFormat;->DAY:C
-Landroid/text/format/DateFormat;->HOUR:C
-Landroid/text/format/DateFormat;->HOUR_OF_DAY:C
-Landroid/text/format/DateFormat;->MINUTE:C
-Landroid/text/format/DateFormat;->MONTH:C
-Landroid/text/format/DateFormat;->QUOTE:C
-Landroid/text/format/DateFormat;->SECONDS:C
-Landroid/text/format/DateFormat;->STANDALONE_MONTH:C
-Landroid/text/format/DateFormat;->TIME_ZONE:C
-Landroid/text/format/DateFormat;->YEAR:C
-Landroid/text/method/LinkMovementMethod;->sInstance:Landroid/text/method/LinkMovementMethod;
-Landroid/text/style/RasterizerSpan;
-Landroid/text/style/RasterizerSpan;-><init>(Landroid/graphics/Rasterizer;)V
-Landroid/text/style/RasterizerSpan;->getRasterizer()Landroid/graphics/Rasterizer;
-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;
-Landroid/transition/Scene;->mExitAction:Ljava/lang/Runnable;
-Landroid/transition/Scene;->setCurrentScene(Landroid/view/View;Landroid/transition/Scene;)V
-Landroid/transition/TransitionManager;->sRunningTransitions:Ljava/lang/ThreadLocal;
-Landroid/util/ArrayMap;->append(Ljava/lang/Object;Ljava/lang/Object;)V
-Landroid/util/ArrayMap;->mBaseCacheSize:I
-Landroid/util/ArrayMap;->mTwiceBaseCacheSize:I
-Landroid/util/ArraySet;-><init>(Ljava/util/Collection;)V
-Landroid/util/DisplayMetrics;->DENSITY_DEVICE:I
-Landroid/util/DisplayMetrics;->noncompatHeightPixels:I
-Landroid/util/DisplayMetrics;->noncompatWidthPixels:I
-Landroid/util/EventLog$Event;-><init>([B)V
-Landroid/util/FloatMath;->ceil(F)F
-Landroid/util/FloatMath;->cos(F)F
-Landroid/util/FloatMath;->exp(F)F
-Landroid/util/FloatMath;->floor(F)F
-Landroid/util/FloatMath;->hypot(FF)F
-Landroid/util/FloatMath;->pow(FF)F
-Landroid/util/FloatMath;->sin(F)F
-Landroid/util/FloatMath;->sqrt(F)F
-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/Log;->wtf(ILjava/lang/String;Ljava/lang/String;Ljava/lang/Throwable;ZZ)I
-Landroid/util/LongArray;-><init>()V
-Landroid/util/LongArray;->add(IJ)V
-Landroid/util/LongArray;->get(I)J
-Landroid/util/LongArray;->size()I
-Landroid/util/LongSparseLongArray;->mKeys:[J
-Landroid/util/LongSparseLongArray;->mSize:I
-Landroid/util/LongSparseLongArray;->mValues:[J
-Landroid/util/MalformedJsonException;->serialVersionUID:J
-Landroid/util/MathUtils;->constrain(III)I
-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$SimplePool;->mPool:[Ljava/lang/Object;
-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/Rational;->readObject(Ljava/io/ObjectInputStream;)V
-Landroid/util/Rational;->serialVersionUID:J
-Landroid/util/RecurrenceRule;->buildRecurringMonthly(ILjava/time/ZoneId;)Landroid/util/RecurrenceRule;
-Landroid/util/RecurrenceRule;->start:Ljava/time/ZonedDateTime;
-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;->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;->w(Ljava/lang/String;Ljava/lang/String;)I
-Landroid/util/Slog;->wtf(Ljava/lang/String;Ljava/lang/String;)I
-Landroid/util/SparseIntArray;->mKeys:[I
-Landroid/util/SparseIntArray;->mSize:I
-Landroid/util/SparseIntArray;->mValues:[I
-Landroid/util/apk/SignatureNotFoundException;->serialVersionUID:J
-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$CallbackQueue;->addCallbackLocked(JLjava/lang/Object;Ljava/lang/Object;)V
-Landroid/view/Choreographer;->USE_VSYNC:Z
-Landroid/view/Choreographer;->doFrame(JI)V
-Landroid/view/Choreographer;->getFrameTime()J
-Landroid/view/Choreographer;->getSfInstance()Landroid/view/Choreographer;
-Landroid/view/Choreographer;->mCallbackQueues:[Landroid/view/Choreographer$CallbackQueue;
-Landroid/view/Choreographer;->mFrameIntervalNanos:J
-Landroid/view/Choreographer;->mLastFrameTimeNanos:J
-Landroid/view/Choreographer;->mLock:Ljava/lang/Object;
-Landroid/view/Choreographer;->scheduleVsyncLocked()V
-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;->getDisplayAdjustments()Landroid/view/DisplayAdjustments;
-Landroid/view/DisplayAdjustments;->getConfiguration()Landroid/content/res/Configuration;
-Landroid/view/DisplayAdjustments;->setCompatibilityInfo(Landroid/content/res/CompatibilityInfo;)V
-Landroid/view/DisplayEventReceiver;->dispatchHotplug(JIZ)V
-Landroid/view/DisplayEventReceiver;->dispatchVsync(JII)V
-Landroid/view/DisplayListCanvas;->callDrawGLFunction2(J)V
-Landroid/view/DisplayListCanvas;->drawGLFunctor2(JLjava/lang/Runnable;)V
-Landroid/view/DisplayListCanvas;->drawRenderNode(Landroid/view/RenderNode;)V
-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;->mMinimumFlingVelocity:I
-Landroid/view/GestureDetector;->mTouchSlopSquare:I
-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/IAppTransitionAnimationSpecsFuture$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/IRecentsAnimationController;->finish(Z)V
-Landroid/view/IRecentsAnimationController;->screenshotTask(I)Landroid/app/ActivityManager$TaskSnapshot;
-Landroid/view/IRecentsAnimationController;->setAnimationTargetsBehindSystemBars(Z)V
-Landroid/view/IRecentsAnimationController;->setInputConsumerEnabled(Z)V
-Landroid/view/IRecentsAnimationRunner$Stub;-><init>()V
-Landroid/view/IRecentsAnimationRunner;->onAnimationCanceled()V
-Landroid/view/IRecentsAnimationRunner;->onAnimationStart(Landroid/view/IRecentsAnimationController;[Landroid/view/RemoteAnimationTarget;)V
-Landroid/view/IRecentsAnimationRunner;->onAnimationStart_New(Landroid/view/IRecentsAnimationController;[Landroid/view/RemoteAnimationTarget;Landroid/graphics/Rect;Landroid/graphics/Rect;)V
-Landroid/view/IRemoteAnimationFinishedCallback;->onAnimationFinished()V
-Landroid/view/IRemoteAnimationRunner$Stub;-><init>()V
-Landroid/view/IRemoteAnimationRunner;->onAnimationCancelled()V
-Landroid/view/IRemoteAnimationRunner;->onAnimationStart([Landroid/view/RemoteAnimationTarget;Landroid/view/IRemoteAnimationFinishedCallback;)V
-Landroid/view/IWindowManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-Landroid/view/IWindowManager$Stub$Proxy;->getBaseDisplayDensity(I)I
-Landroid/view/IWindowManager$Stub$Proxy;->getDockedStackSide()I
-Landroid/view/IWindowManager$Stub$Proxy;->getInitialDisplayDensity(I)I
-Landroid/view/IWindowManager$Stub$Proxy;->hasNavigationBar()Z
-Landroid/view/IWindowManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/view/IWindowManager;
-Landroid/view/IWindowManager;->createInputConsumer(Landroid/os/IBinder;Ljava/lang/String;Landroid/view/InputChannel;)V
-Landroid/view/IWindowManager;->destroyInputConsumer(Ljava/lang/String;)Z
-Landroid/view/IWindowManager;->endProlongedAnimations()V
-Landroid/view/IWindowManager;->getAnimationScale(I)F
-Landroid/view/IWindowManager;->getStableInsets(ILandroid/graphics/Rect;)V
-Landroid/view/IWindowManager;->hasNavigationBar()Z
-Landroid/view/IWindowManager;->overridePendingAppTransitionMultiThumbFuture(Landroid/view/IAppTransitionAnimationSpecsFuture;Landroid/os/IRemoteCallback;Z)V
-Landroid/view/IWindowManager;->overridePendingAppTransitionRemote(Landroid/view/RemoteAnimationAdapter;)V
-Landroid/view/IWindowManager;->setAnimationScale(IF)V
-Landroid/view/IWindowManager;->setNavBarVirtualKeyHapticFeedbackEnabled(Z)V
-Landroid/view/IWindowManager;->setShelfHeight(ZI)V
-Landroid/view/IWindowManager;->setStrictModeVisualIndicatorPreference(Ljava/lang/String;)V
-Landroid/view/IWindowSession$Stub$Proxy;->relayout(Landroid/view/IWindow;ILandroid/view/WindowManager$LayoutParams;IIIIJLandroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/view/DisplayCutout$ParcelableWrapper;Landroid/util/MergedConfiguration;Landroid/view/Surface;)I
-Landroid/view/InputChannel;-><init>()V
-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/InputEvent;->getSequenceNumber()I
-Landroid/view/InputEventReceiver;->dispatchBatchedInputEventPending()V
-Landroid/view/InputEventReceiver;->dispatchInputEvent(ILandroid/view/InputEvent;I)V
-Landroid/view/InputEventReceiver;->onInputEvent(Landroid/view/InputEvent;I)V
-Landroid/view/InputEventSender;->dispatchInputEventFinished(IZ)V
-Landroid/view/InputQueue;->finishInputEvent(JZ)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;->mAction:I
-Landroid/view/KeyEvent;->mCharacters:Ljava/lang/String;
-Landroid/view/KeyEvent;->mDeviceId:I
-Landroid/view/KeyEvent;->mDownTime:J
-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;->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;->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;->sConstructorMap:Ljava/util/HashMap;
-Landroid/view/LayoutInflater;->setPrivateFactory(Landroid/view/LayoutInflater$Factory2;)V
-Landroid/view/MotionEvent$PointerCoords;->mPackedAxisBits:J
-Landroid/view/MotionEvent$PointerCoords;->mPackedAxisValues:[F
-Landroid/view/MotionEvent;->HISTORY_CURRENT:I
-Landroid/view/MotionEvent;->getPointerIdBits()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;->split(I)Landroid/view/MotionEvent;
-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/RemoteAnimationAdapter;-><init>(Landroid/view/IRemoteAnimationRunner;JJ)V
-Landroid/view/RemoteAnimationDefinition;-><init>()V
-Landroid/view/RemoteAnimationDefinition;->addRemoteAnimation(IILandroid/view/RemoteAnimationAdapter;)V
-Landroid/view/RemoteAnimationDefinition;->addRemoteAnimation(ILandroid/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;->create(Ljava/lang/String;Landroid/view/View;)Landroid/view/RenderNode;
-Landroid/view/RenderNode;->discardDisplayList()V
-Landroid/view/RenderNode;->end(Landroid/view/DisplayListCanvas;)V
-Landroid/view/RenderNode;->isValid()Z
-Landroid/view/RenderNode;->output()V
-Landroid/view/RenderNode;->setClipToBounds(Z)Z
-Landroid/view/RenderNode;->setLeftTopRightBottom(IIII)Z
-Landroid/view/RenderNode;->start(II)Landroid/view/DisplayListCanvas;
-Landroid/view/RenderNodeAnimator;-><init>(IF)V
-Landroid/view/RenderNodeAnimator;->callOnFinished(Landroid/view/RenderNodeAnimator;)V
-Landroid/view/RenderNodeAnimator;->mapViewPropertyToRenderProperty(I)I
-Landroid/view/RenderNodeAnimator;->setTarget(Landroid/view/View;)V
-Landroid/view/ScaleGestureDetector;->mListener:Landroid/view/ScaleGestureDetector$OnScaleGestureListener;
-Landroid/view/ScaleGestureDetector;->mMinSpan:I
-Landroid/view/Surface;-><init>(J)V
-Landroid/view/Surface;->getNextFrameNumber()J
-Landroid/view/Surface;->mLock:Ljava/lang/Object;
-Landroid/view/Surface;->mNativeObject:J
-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$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/SurfaceSession;->mNativeClient:J
-Landroid/view/SurfaceView;->isFixedSize()Z
-Landroid/view/SurfaceView;->mCallbacks:Ljava/util/ArrayList;
-Landroid/view/SurfaceView;->mFormat:I
-Landroid/view/SurfaceView;->mRequestedFormat:I
-Landroid/view/SurfaceView;->mSurfaceHolder:Landroid/view/SurfaceHolder;
-Landroid/view/SurfaceView;->setFrame(IIII)Z
-Landroid/view/SurfaceView;->surfacePositionLost_uiRtSync(J)V
-Landroid/view/SurfaceView;->updateSurfacePosition_renderWorker(JIIII)V
-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;->mSurface:Landroid/graphics/SurfaceTexture;
-Landroid/view/TextureView;->mUpdateListener:Landroid/graphics/SurfaceTexture$OnFrameAvailableListener;
-Landroid/view/ThreadedRenderer;->createHardwareBitmap(Landroid/view/RenderNode;II)Landroid/graphics/Bitmap;
-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$AttachInfo;->mContentInsets:Landroid/graphics/Rect;
-Landroid/view/View$AttachInfo;->mDrawingTime:J
-Landroid/view/View$AttachInfo;->mStableInsets:Landroid/graphics/Rect;
-Landroid/view/View$ListenerInfo;-><init>()V
-Landroid/view/View$ListenerInfo;->mOnClickListener:Landroid/view/View$OnClickListener;
-Landroid/view/View$ListenerInfo;->mOnDragListener:Landroid/view/View$OnDragListener;
-Landroid/view/View$ListenerInfo;->mOnFocusChangeListener:Landroid/view/View$OnFocusChangeListener;
-Landroid/view/View$ListenerInfo;->mOnLongClickListener:Landroid/view/View$OnLongClickListener;
-Landroid/view/View$ListenerInfo;->mOnTouchListener:Landroid/view/View$OnTouchListener;
-Landroid/view/View$ScrollabilityCache;->scrollBar:Landroid/widget/ScrollBarDrawable;
-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;->applyDrawableToTransparentRegion(Landroid/graphics/drawable/Drawable;Landroid/graphics/Region;)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;->dispatchAttachedToWindow(Landroid/view/View$AttachInfo;I)V
-Landroid/view/View;->dispatchDetachedFromWindow()V
-Landroid/view/View;->fitsSystemWindows()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;->getHorizontalScrollFactor()F
-Landroid/view/View;->getInverseMatrix()Landroid/graphics/Matrix;
-Landroid/view/View;->getListenerInfo()Landroid/view/View$ListenerInfo;
-Landroid/view/View;->getLocationOnScreen()[I
-Landroid/view/View;->getRawTextAlignment()I
-Landroid/view/View;->getRawTextDirection()I
-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;->hideTooltip()V
-Landroid/view/View;->includeForAccessibility()Z
-Landroid/view/View;->initializeFadingEdge(Landroid/content/res/TypedArray;)V
-Landroid/view/View;->initializeScrollbars(Landroid/content/res/TypedArray;)V
-Landroid/view/View;->internalSetPadding(IIII)V
-Landroid/view/View;->invalidateParentIfNeeded()V
-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;->mAttachInfo:Landroid/view/View$AttachInfo;
-Landroid/view/View;->mBackground:Landroid/graphics/drawable/Drawable;
-Landroid/view/View;->mBottom:I
-Landroid/view/View;->mContext:Landroid/content/Context;
-Landroid/view/View;->mDrawingCache:Landroid/graphics/Bitmap;
-Landroid/view/View;->mLayoutParams:Landroid/view/ViewGroup$LayoutParams;
-Landroid/view/View;->mLeft:I
-Landroid/view/View;->mListenerInfo:Landroid/view/View$ListenerInfo;
-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;->mPrivateFlags2:I
-Landroid/view/View;->mPrivateFlags3:I
-Landroid/view/View;->mPrivateFlags:I
-Landroid/view/View;->mRecreateDisplayList:Z
-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;->mUnscaledDrawingCache:Landroid/graphics/Bitmap;
-Landroid/view/View;->mViewFlags:I
-Landroid/view/View;->notifySubtreeAccessibilityStateChangedIfNeeded()V
-Landroid/view/View;->onDrawVerticalScrollBar(Landroid/graphics/Canvas;Landroid/graphics/drawable/Drawable;IIII)V
-Landroid/view/View;->performAccessibilityActionInternal(ILandroid/os/Bundle;)Z
-Landroid/view/View;->recomputePadding()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;->setAlphaNoInvalidation(F)Z
-Landroid/view/View;->setAnimationMatrix(Landroid/graphics/Matrix;)V
-Landroid/view/View;->setAssistBlocked(Z)V
-Landroid/view/View;->setFrame(IIII)Z
-Landroid/view/View;->setIsRootNamespace(Z)V
-Landroid/view/View;->setLeftTopRightBottom(IIII)V
-Landroid/view/View;->setTooltip(Ljava/lang/CharSequence;)V
-Landroid/view/View;->setTransitionAlpha(F)V
-Landroid/view/View;->startActivityForResult(Landroid/content/Intent;I)V
-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/ViewConfiguration;->getDeviceGlobalActionKeyTimeout()J
-Landroid/view/ViewConfiguration;->getDoubleTapMinTime()I
-Landroid/view/ViewConfiguration;->getScaledScrollFactor()I
-Landroid/view/ViewConfiguration;->mFadingMarqueeEnabled:Z
-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/ViewGroup$MarginLayoutParams;->endMargin:I
-Landroid/view/ViewGroup$MarginLayoutParams;->startMargin:I
-Landroid/view/ViewGroup;->FLAG_SUPPORT_STATIC_TRANSFORMATIONS:I
-Landroid/view/ViewGroup;->FLAG_USE_CHILD_DRAWING_ORDER:I
-Landroid/view/ViewGroup;->dispatchViewAdded(Landroid/view/View;)V
-Landroid/view/ViewGroup;->dispatchViewRemoved(Landroid/view/View;)V
-Landroid/view/ViewGroup;->mChildren:[Landroid/view/View;
-Landroid/view/ViewGroup;->mChildrenCount:I
-Landroid/view/ViewGroup;->mFirstTouchTarget:Landroid/view/ViewGroup$TouchTarget;
-Landroid/view/ViewGroup;->mGroupFlags:I
-Landroid/view/ViewGroup;->mOnHierarchyChangeListener:Landroid/view/ViewGroup$OnHierarchyChangeListener;
-Landroid/view/ViewGroup;->mPersistentDrawingCache:I
-Landroid/view/ViewGroup;->makeOptionalFitsSystemWindows()V
-Landroid/view/ViewGroup;->offsetChildrenTopAndBottom(I)V
-Landroid/view/ViewGroup;->onChildVisibilityChanged(Landroid/view/View;II)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;->suppressLayout(Z)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;->enqueueInputEvent(Landroid/view/InputEvent;)V
-Landroid/view/ViewRootImpl;->getWindowFlags()I
-Landroid/view/ViewRootImpl;->invokeFunctor(JZ)V
-Landroid/view/ViewRootImpl;->mStopped:Z
-Landroid/view/ViewRootImpl;->mSurface:Landroid/view/Surface;
-Landroid/view/ViewRootImpl;->mView:Landroid/view/View;
-Landroid/view/ViewTreeObserver$InternalInsetsInfo;->TOUCHABLE_INSETS_REGION:I
-Landroid/view/ViewTreeObserver$InternalInsetsInfo;->setTouchableInsets(I)V
-Landroid/view/ViewTreeObserver$InternalInsetsInfo;->touchableRegion:Landroid/graphics/Region;
-Landroid/view/ViewTreeObserver;->addOnComputeInternalInsetsListener(Landroid/view/ViewTreeObserver$OnComputeInternalInsetsListener;)V
-Landroid/view/ViewTreeObserver;->removeOnComputeInternalInsetsListener(Landroid/view/ViewTreeObserver$OnComputeInternalInsetsListener;)V
-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;->mHardwareAccelerated:Z
-Landroid/view/Window;->mWindowStyle:Landroid/content/res/TypedArray;
-Landroid/view/Window;->setNeedsMenuKey(I)V
-Landroid/view/WindowAnimationFrameStats;->init(J[J)V
-Landroid/view/WindowContentFrameStats;->init(J[J[J[J)V
-Landroid/view/WindowManager$LayoutParams;->NEEDS_MENU_SET_FALSE:I
-Landroid/view/WindowManager$LayoutParams;->NEEDS_MENU_SET_TRUE:I
-Landroid/view/WindowManager$LayoutParams;->TYPE_KEYGUARD:I
-Landroid/view/WindowManager$LayoutParams;->hideTimeoutMilliseconds:J
-Landroid/view/WindowManager$LayoutParams;->needsMenuKey: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;->getViewRootNames()[Ljava/lang/String;
-Landroid/view/WindowManagerGlobal;->getWindowManagerService()Landroid/view/IWindowManager;
-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;->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/view/accessibility/AccessibilityInteractionClient;->clearCache()V
-Landroid/view/accessibility/AccessibilityInteractionClient;->getInstance()Landroid/view/accessibility/AccessibilityInteractionClient;
-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;->mIsEnabled:Z
-Landroid/view/accessibility/AccessibilityManager;->mIsHighTextContrastEnabled:Z
-Landroid/view/accessibility/AccessibilityManager;->sInstance:Landroid/view/accessibility/AccessibilityManager;
-Landroid/view/accessibility/AccessibilityManager;->sInstanceSync:Ljava/lang/Object;
-Landroid/view/accessibility/AccessibilityNodeInfo;->isSealed()Z
-Landroid/view/accessibility/AccessibilityNodeInfo;->mChildNodeIds:Landroid/util/LongArray;
-Landroid/view/accessibility/AccessibilityNodeInfo;->mSealed:Z
-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/IAccessibilityManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-Landroid/view/accessibility/IAccessibilityManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/view/accessibility/IAccessibilityManager;
-Landroid/view/accessibility/IAccessibilityManager;->getEnabledAccessibilityServiceList(II)Ljava/util/List;
-Landroid/view/animation/Animation;->detach()V
-Landroid/view/animation/Animation;->initializeInvalidateRegion(IIII)V
-Landroid/view/animation/Animation;->mListener:Landroid/view/animation/Animation$AnimationListener;
-Landroid/view/autofill/IAutoFillManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-Landroid/view/inputmethod/InputMethodInfo;->mSubtypes:Landroid/view/inputmethod/InputMethodSubtypeArray;
-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;->getInputMethodWindowVisibleHeight()I
-Landroid/view/inputmethod/InputMethodManager;->getInstance()Landroid/view/inputmethod/InputMethodManager;
-Landroid/view/inputmethod/InputMethodManager;->mCurId:Ljava/lang/String;
-Landroid/view/inputmethod/InputMethodManager;->mCurRootView:Landroid/view/View;
-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;->notifyUserAction()V
-Landroid/view/inputmethod/InputMethodManager;->peekInstance()Landroid/view/inputmethod/InputMethodManager;
-Landroid/view/inputmethod/InputMethodManager;->sInstance:Landroid/view/inputmethod/InputMethodManager;
-Landroid/view/inputmethod/InputMethodManager;->showSoftInputUnchecked(ILandroid/os/ResultReceiver;)V
-Landroid/view/inputmethod/InputMethodManager;->windowDismissed(Landroid/os/IBinder;)V
-Landroid/view/inputmethod/InputMethodSubtypeArray;-><init>(Ljava/util/List;)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/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/textservice/TextServicesManager;->isSpellCheckerEnabled()Z
-Landroid/webkit/CacheManager$CacheResult;-><init>()V
-Landroid/webkit/CacheManager$CacheResult;->getContentDisposition()Ljava/lang/String;
-Landroid/webkit/CacheManager$CacheResult;->getContentLength()J
-Landroid/webkit/CacheManager$CacheResult;->getETag()Ljava/lang/String;
-Landroid/webkit/CacheManager$CacheResult;->getEncoding()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;->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;Landroid/webkit/CacheManager$CacheResult;)V
-Landroid/webkit/CacheManager;->startCacheTransaction()Z
-Landroid/webkit/IWebViewUpdateService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-Landroid/webkit/WebResourceResponse;->mImmutable:Z
-Landroid/webkit/WebSettings$TextSize;->value:I
-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/WebSyncManager;->mHandler:Landroid/os/Handler;
-Landroid/webkit/WebView;->debugDump()V
-Landroid/webkit/WebView;->disablePlatformNotifications()V
-Landroid/webkit/WebView;->emulateShiftHeld()V
-Landroid/webkit/WebView;->enablePlatformNotifications()V
-Landroid/webkit/WebView;->getContentWidth()I
-Landroid/webkit/WebView;->getPluginList()Landroid/webkit/PluginList;
-Landroid/webkit/WebView;->getTouchIconUrl()Ljava/lang/String;
-Landroid/webkit/WebView;->getVisibleTitleHeight()I
-Landroid/webkit/WebView;->getZoomControls()Landroid/view/View;
-Landroid/webkit/WebView;->isPaused()Z
-Landroid/webkit/WebView;->mProvider:Landroid/webkit/WebViewProvider;
-Landroid/webkit/WebView;->notifyFindDialogDismissed()V
-Landroid/webkit/WebView;->onDrawVerticalScrollBar(Landroid/graphics/Canvas;Landroid/graphics/drawable/Drawable;IIII)V
-Landroid/webkit/WebView;->refreshPlugins(Z)V
-Landroid/webkit/WebView;->restorePicture(Landroid/os/Bundle;Ljava/io/File;)Z
-Landroid/webkit/WebView;->sEnforceThreadChecking:Z
-Landroid/webkit/WebView;->savePicture(Landroid/os/Bundle;Ljava/io/File;)Z
-Landroid/webkit/WebViewClient;->onUnhandledInputEvent(Landroid/webkit/WebView;Landroid/view/InputEvent;)V
-Landroid/webkit/WebViewDelegate;-><init>()V
-Landroid/webkit/WebViewFactory;->getProvider()Landroid/webkit/WebViewFactoryProvider;
-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/widget/AbsListView$FlingRunnable;->endFling()V
-Landroid/widget/AbsListView$FlingRunnable;->mScroller:Landroid/widget/OverScroller;
-Landroid/widget/AbsListView$FlingRunnable;->start(I)V
-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;->invokeOnItemScrollListener()V
-Landroid/widget/AbsListView;->isVerticalScrollBarHidden()Z
-Landroid/widget/AbsListView;->mAdapter:Landroid/widget/ListAdapter;
-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;->mOnScrollListener:Landroid/widget/AbsListView$OnScrollListener;
-Landroid/widget/AbsListView;->mPendingCheckForLongPress:Landroid/widget/AbsListView$CheckForLongPress;
-Landroid/widget/AbsListView;->mPendingCheckForTap:Landroid/widget/AbsListView$CheckForTap;
-Landroid/widget/AbsListView;->mRecycler:Landroid/widget/AbsListView$RecycleBin;
-Landroid/widget/AbsListView;->mSelectionTopPadding:I
-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;->reportScrollStateChange(I)V
-Landroid/widget/AbsListView;->smoothScrollBy(IIZZ)V
-Landroid/widget/AbsListView;->trackMotionScroll(II)Z
-Landroid/widget/AbsSeekBar;->mIsDragging:Z
-Landroid/widget/AbsSeekBar;->mSplitTrack:Z
-Landroid/widget/AbsSeekBar;->mThumb:Landroid/graphics/drawable/Drawable;
-Landroid/widget/AbsSeekBar;->mTouchProgressOffset:F
-Landroid/widget/ActivityChooserModel;->get(Landroid/content/Context;Ljava/lang/String;)Landroid/widget/ActivityChooserModel;
-Landroid/widget/ActivityChooserView;->setExpandActivityOverflowButtonDrawable(Landroid/graphics/drawable/Drawable;)V
-Landroid/widget/AdapterView;->mDataChanged:Z
-Landroid/widget/AdapterView;->mFirstPosition:I
-Landroid/widget/AdapterView;->mNextSelectedPosition:I
-Landroid/widget/AdapterView;->mNextSelectedRowId:J
-Landroid/widget/AdapterView;->mOldSelectedPosition:I
-Landroid/widget/AdapterView;->setNextSelectedPositionInt(I)V
-Landroid/widget/AdapterView;->setSelectedPositionInt(I)V
-Landroid/widget/AutoCompleteTextView;->doAfterTextChanged()V
-Landroid/widget/AutoCompleteTextView;->doBeforeTextChanged()V
-Landroid/widget/AutoCompleteTextView;->ensureImeVisible(Z)V
-Landroid/widget/AutoCompleteTextView;->mPopup:Landroid/widget/ListPopupWindow;
-Landroid/widget/AutoCompleteTextView;->setDropDownAlwaysVisible(Z)V
-Landroid/widget/AutoCompleteTextView;->setForceIgnoreOutsideTouch(Z)V
-Landroid/widget/BaseAdapter;->mDataSetObservable:Landroid/database/DataSetObservable;
-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;->mDataSetObserver:Landroid/database/DataSetObserver;
-Landroid/widget/CursorAdapter;->mDataValid:Z
-Landroid/widget/CursorAdapter;->mRowIDColumn:I
-Landroid/widget/DatePicker;->mDelegate:Landroid/widget/DatePicker$DatePickerDelegate;
-Landroid/widget/EdgeEffect;->mPaint:Landroid/graphics/Paint;
-Landroid/widget/Editor;->invalidateTextDisplayList()V
-Landroid/widget/Editor;->mSelectHandleLeft:Landroid/graphics/drawable/Drawable;
-Landroid/widget/Editor;->mShowCursor:J
-Landroid/widget/Editor;->mShowSoftInputOnFocus:Z
-Landroid/widget/ExpandableListView;->mChildDivider:Landroid/graphics/drawable/Drawable;
-Landroid/widget/ExpandableListView;->mGroupIndicator:Landroid/graphics/drawable/Drawable;
-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/Gallery$FlingRunnable;->startUsingVelocity(I)V
-Landroid/widget/Gallery;->fillToGalleryLeft()V
-Landroid/widget/Gallery;->fillToGalleryRight()V
-Landroid/widget/Gallery;->mDownTouchPosition:I
-Landroid/widget/Gallery;->mDownTouchView:Landroid/view/View;
-Landroid/widget/Gallery;->mFlingRunnable:Landroid/widget/Gallery$FlingRunnable;
-Landroid/widget/Gallery;->mSpacing:I
-Landroid/widget/Gallery;->makeAndAddView(IIIZ)Landroid/view/View;
-Landroid/widget/Gallery;->moveDirection(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;->mRequestedNumColumns:I
-Landroid/widget/GridView;->mVerticalSpacing:I
-Landroid/widget/HorizontalScrollView;->mChildToScrollTo:Landroid/view/View;
-Landroid/widget/HorizontalScrollView;->mEdgeGlowLeft:Landroid/widget/EdgeEffect;
-Landroid/widget/HorizontalScrollView;->mEdgeGlowRight:Landroid/widget/EdgeEffect;
-Landroid/widget/HorizontalScrollView;->mScroller:Landroid/widget/OverScroller;
-Landroid/widget/ImageView;->animateTransform(Landroid/graphics/Matrix;)V
-Landroid/widget/ImageView;->mAdjustViewBounds:Z
-Landroid/widget/ImageView;->mAlpha: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;->updateDrawable(Landroid/graphics/drawable/Drawable;)V
-Landroid/widget/LinearLayout;->mGravity:I
-Landroid/widget/LinearLayout;->mUseLargestChild:Z
-Landroid/widget/ListPopupWindow;->mPopup:Landroid/widget/PopupWindow;
-Landroid/widget/ListPopupWindow;->setForceIgnoreOutsideTouch(Z)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;->findViewTraversal(I)Landroid/view/View;
-Landroid/widget/ListView;->findViewWithTagTraversal(Ljava/lang/Object;)Landroid/view/View;
-Landroid/widget/ListView;->lookForSelectablePosition(IZ)I
-Landroid/widget/ListView;->mAreAllItemsSelectable:Z
-Landroid/widget/ListView;->mFooterViewInfos:Ljava/util/ArrayList;
-Landroid/widget/ListView;->mHeaderViewInfos:Ljava/util/ArrayList;
-Landroid/widget/ListView;->setSelectionInt(I)V
-Landroid/widget/MediaController;->mAnchor:Landroid/view/View;
-Landroid/widget/MediaController;->mDecor:Landroid/view/View;
-Landroid/widget/MediaController;->mDecorLayoutParams:Landroid/view/WindowManager$LayoutParams;
-Landroid/widget/MediaController;->mWindowManager:Landroid/view/WindowManager;
-Landroid/widget/NumberPicker;->mInputText:Landroid/widget/EditText;
-Landroid/widget/NumberPicker;->mSelectionDivider:Landroid/graphics/drawable/Drawable;
-Landroid/widget/NumberPicker;->mSelectorWheelPaint:Landroid/graphics/Paint;
-Landroid/widget/OverScroller$SplineOverScroller;->mCurrVelocity:F
-Landroid/widget/OverScroller;->isScrollingInDirection(FF)Z
-Landroid/widget/OverScroller;->mScrollerY:Landroid/widget/OverScroller$SplineOverScroller;
-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;->mAnchor:Ljava/lang/ref/WeakReference;
-Landroid/widget/PopupWindow;->mAnimationStyle:I
-Landroid/widget/PopupWindow;->mBackgroundView:Landroid/view/View;
-Landroid/widget/PopupWindow;->mContentView:Landroid/view/View;
-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;->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;->preparePopup(Landroid/view/WindowManager$LayoutParams;)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/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;->mOnlyIndeterminate:Z
-Landroid/widget/ProgressBar;->setProgressInternal(IZZ)Z
-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$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;->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;->mLayoutId:I
-Landroid/widget/RemoteViews;->mPortrait:Landroid/widget/RemoteViews;
-Landroid/widget/RemoteViews;->mergeRemoteViews(Landroid/widget/RemoteViews;)V
-Landroid/widget/RemoteViewsAdapter;->mCache:Landroid/widget/RemoteViewsAdapter$FixedSizeRemoteViewsCache;
-Landroid/widget/RemoteViewsAdapter;->mWorkerThread:Landroid/os/HandlerThread;
-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/ScrollView;->mChildToScrollTo:Landroid/view/View;
-Landroid/widget/ScrollView;->mEdgeGlowBottom:Landroid/widget/EdgeEffect;
-Landroid/widget/ScrollView;->mEdgeGlowTop:Landroid/widget/EdgeEffect;
-Landroid/widget/ScrollView;->mIsBeingDragged:Z
-Landroid/widget/ScrollView;->mMinimumVelocity:I
-Landroid/widget/ScrollView;->mOverflingDistance:I
-Landroid/widget/ScrollView;->mOverscrollDistance:I
-Landroid/widget/ScrollView;->mScroller:Landroid/widget/OverScroller;
-Landroid/widget/Scroller;->mInterpolator:Landroid/view/animation/Interpolator;
-Landroid/widget/SearchView;->mCloseButton:Landroid/widget/ImageView;
-Landroid/widget/SearchView;->mSearchButton:Landroid/widget/ImageView;
-Landroid/widget/SearchView;->mSearchPlate:Landroid/view/View;
-Landroid/widget/SearchView;->mSearchSrcTextView:Landroid/widget/SearchView$SearchAutoComplete;
-Landroid/widget/SearchView;->onCloseClicked()V
-Landroid/widget/SearchView;->setQuery(Ljava/lang/CharSequence;)V
-Landroid/widget/SlidingDrawer;->mTopOffset:I
-Landroid/widget/Spinner;->mPopup:Landroid/widget/Spinner$SpinnerPopup;
-Landroid/widget/Switch;->mThumbDrawable:Landroid/graphics/drawable/Drawable;
-Landroid/widget/Switch;->mTrackDrawable:Landroid/graphics/drawable/Drawable;
-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;->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/TextView;->LINES:I
-Landroid/widget/TextView;->assumeLayout()V
-Landroid/widget/TextView;->createEditorIfNeeded()V
-Landroid/widget/TextView;->getHorizontallyScrolling()Z
-Landroid/widget/TextView;->getTextColor(Landroid/content/Context;Landroid/content/res/TypedArray;I)I
-Landroid/widget/TextView;->getTextColors(Landroid/content/Context;Landroid/content/res/TypedArray;)Landroid/content/res/ColorStateList;
-Landroid/widget/TextView;->isSingleLine()Z
-Landroid/widget/TextView;->mCurTextColor:I
-Landroid/widget/TextView;->mCursorDrawableRes:I
-Landroid/widget/TextView;->mEditor:Landroid/widget/Editor;
-Landroid/widget/TextView;->mListeners:Ljava/util/ArrayList;
-Landroid/widget/TextView;->mMarquee:Landroid/widget/TextView$Marquee;
-Landroid/widget/TextView;->mMaxMode:I
-Landroid/widget/TextView;->mMaximum:I
-Landroid/widget/TextView;->mSingleLine:Z
-Landroid/widget/TextView;->mText:Ljava/lang/CharSequence;
-Landroid/widget/TextView;->mTextPaint:Landroid/text/TextPaint;
-Landroid/widget/TextView;->setText(Ljava/lang/CharSequence;Landroid/widget/TextView$BufferType;ZI)V
-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;->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/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;->mMediaController:Landroid/widget/MediaController;
-Landroid/widget/VideoView;->mSHCallback:Landroid/view/SurfaceHolder$Callback;
-Landroid/widget/VideoView;->mUri:Landroid/net/Uri;
-Landroid/widget/VideoView;->mVideoHeight:I
-Landroid/widget/VideoView;->mVideoWidth:I
-Lcom/android/i18n/phonenumbers/Phonemetadata$NumberFormat;->serialVersionUID:J
-Lcom/android/i18n/phonenumbers/Phonemetadata$PhoneMetadata;->serialVersionUID:J
-Lcom/android/i18n/phonenumbers/Phonemetadata$PhoneMetadataCollection;->serialVersionUID:J
-Lcom/android/i18n/phonenumbers/Phonemetadata$PhoneNumberDesc;->serialVersionUID:J
-Lcom/android/i18n/phonenumbers/Phonenumber$PhoneNumber;->serialVersionUID:J
-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
-Lcom/android/ims/internal/IImsCallSessionListener;->callSessionHandoverFailed(Lcom/android/ims/internal/IImsCallSession;IILandroid/telephony/ims/ImsReasonInfo;)V
-Lcom/android/ims/internal/IImsCallSessionListener;->callSessionHeld(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsCallProfile;)V
-Lcom/android/ims/internal/IImsCallSessionListener;->callSessionHoldFailed(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsReasonInfo;)V
-Lcom/android/ims/internal/IImsCallSessionListener;->callSessionHoldReceived(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsCallProfile;)V
-Lcom/android/ims/internal/IImsCallSessionListener;->callSessionInviteParticipantsRequestDelivered(Lcom/android/ims/internal/IImsCallSession;)V
-Lcom/android/ims/internal/IImsCallSessionListener;->callSessionInviteParticipantsRequestFailed(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsReasonInfo;)V
-Lcom/android/ims/internal/IImsCallSessionListener;->callSessionMergeComplete(Lcom/android/ims/internal/IImsCallSession;)V
-Lcom/android/ims/internal/IImsCallSessionListener;->callSessionMergeFailed(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsReasonInfo;)V
-Lcom/android/ims/internal/IImsCallSessionListener;->callSessionMergeStarted(Lcom/android/ims/internal/IImsCallSession;Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsCallProfile;)V
-Lcom/android/ims/internal/IImsCallSessionListener;->callSessionMultipartyStateChanged(Lcom/android/ims/internal/IImsCallSession;Z)V
-Lcom/android/ims/internal/IImsCallSessionListener;->callSessionProgressing(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsStreamMediaProfile;)V
-Lcom/android/ims/internal/IImsCallSessionListener;->callSessionResumeFailed(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsReasonInfo;)V
-Lcom/android/ims/internal/IImsCallSessionListener;->callSessionResumeReceived(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsCallProfile;)V
-Lcom/android/ims/internal/IImsCallSessionListener;->callSessionResumed(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsCallProfile;)V
-Lcom/android/ims/internal/IImsCallSessionListener;->callSessionStartFailed(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsReasonInfo;)V
-Lcom/android/ims/internal/IImsCallSessionListener;->callSessionStarted(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsCallProfile;)V
-Lcom/android/ims/internal/IImsCallSessionListener;->callSessionSuppServiceReceived(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsSuppServiceNotification;)V
-Lcom/android/ims/internal/IImsCallSessionListener;->callSessionTerminated(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsReasonInfo;)V
-Lcom/android/ims/internal/IImsCallSessionListener;->callSessionTtyModeReceived(Lcom/android/ims/internal/IImsCallSession;I)V
-Lcom/android/ims/internal/IImsCallSessionListener;->callSessionUpdated(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsCallProfile;)V
-Lcom/android/ims/internal/IImsRegistrationListener;->registrationAssociatedUriChanged([Landroid/net/Uri;)V
-Lcom/android/ims/internal/IImsRegistrationListener;->registrationChangeFailed(ILandroid/telephony/ims/ImsReasonInfo;)V
-Lcom/android/ims/internal/IImsRegistrationListener;->registrationConnectedWithRadioTech(I)V
-Lcom/android/ims/internal/IImsRegistrationListener;->registrationDisconnected(Landroid/telephony/ims/ImsReasonInfo;)V
-Lcom/android/ims/internal/IImsRegistrationListener;->registrationFeatureCapabilityChanged(I[I[I)V
-Lcom/android/ims/internal/IImsRegistrationListener;->registrationProgressingWithRadioTech(I)V
-Lcom/android/ims/internal/IImsRegistrationListener;->voiceMessageCountUpdate(I)V
-Lcom/android/ims/internal/IImsUtListener;->utConfigurationCallBarringQueried(Lcom/android/ims/internal/IImsUt;I[Landroid/telephony/ims/ImsSsInfo;)V
-Lcom/android/ims/internal/IImsUtListener;->utConfigurationCallForwardQueried(Lcom/android/ims/internal/IImsUt;I[Landroid/telephony/ims/ImsCallForwardInfo;)V
-Lcom/android/ims/internal/IImsUtListener;->utConfigurationCallWaitingQueried(Lcom/android/ims/internal/IImsUt;I[Landroid/telephony/ims/ImsSsInfo;)V
-Lcom/android/ims/internal/IImsUtListener;->utConfigurationQueried(Lcom/android/ims/internal/IImsUt;ILandroid/os/Bundle;)V
-Lcom/android/ims/internal/IImsUtListener;->utConfigurationQueryFailed(Lcom/android/ims/internal/IImsUt;ILandroid/telephony/ims/ImsReasonInfo;)V
-Lcom/android/ims/internal/IImsUtListener;->utConfigurationUpdateFailed(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/uce/common/CapInfo;-><init>()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/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;->getStatusCode()I
-Lcom/android/ims/internal/uce/common/StatusCode;->setStatusCode(I)V
-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;->getUceLong()J
-Lcom/android/ims/internal/uce/common/UceLong;->setClientId(I)V
-Lcom/android/ims/internal/uce/common/UceLong;->setUceLong(J)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
-Lcom/android/ims/internal/uce/options/IOptionsListener;->serviceAvailable(Lcom/android/ims/internal/uce/common/StatusCode;)V
-Lcom/android/ims/internal/uce/options/IOptionsListener;->serviceUnavailable(Lcom/android/ims/internal/uce/common/StatusCode;)V
-Lcom/android/ims/internal/uce/options/IOptionsListener;->sipResponseReceived(Ljava/lang/String;Lcom/android/ims/internal/uce/options/OptionsSipResponse;Lcom/android/ims/internal/uce/options/OptionsCapInfo;)V
-Lcom/android/ims/internal/uce/options/IOptionsService$Stub;-><init>()V
-Lcom/android/ims/internal/uce/options/IOptionsService;->addListener(ILcom/android/ims/internal/uce/options/IOptionsListener;Lcom/android/ims/internal/uce/common/UceLong;)Lcom/android/ims/internal/uce/common/StatusCode;
-Lcom/android/ims/internal/uce/options/IOptionsService;->getContactCap(ILjava/lang/String;I)Lcom/android/ims/internal/uce/common/StatusCode;
-Lcom/android/ims/internal/uce/options/IOptionsService;->getContactListCap(I[Ljava/lang/String;I)Lcom/android/ims/internal/uce/common/StatusCode;
-Lcom/android/ims/internal/uce/options/IOptionsService;->getMyInfo(II)Lcom/android/ims/internal/uce/common/StatusCode;
-Lcom/android/ims/internal/uce/options/IOptionsService;->getVersion(I)Lcom/android/ims/internal/uce/common/StatusCode;
-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
-Lcom/android/ims/internal/uce/presence/IPresenceListener;->listCapInfoReceived(Lcom/android/ims/internal/uce/presence/PresRlmiInfo;[Lcom/android/ims/internal/uce/presence/PresResInfo;)V
-Lcom/android/ims/internal/uce/presence/IPresenceListener;->publishTriggering(Lcom/android/ims/internal/uce/presence/PresPublishTriggerType;)V
-Lcom/android/ims/internal/uce/presence/IPresenceListener;->serviceAvailable(Lcom/android/ims/internal/uce/common/StatusCode;)V
-Lcom/android/ims/internal/uce/presence/IPresenceListener;->serviceUnAvailable(Lcom/android/ims/internal/uce/common/StatusCode;)V
-Lcom/android/ims/internal/uce/presence/IPresenceListener;->sipResponseReceived(Lcom/android/ims/internal/uce/presence/PresSipResponse;)V
-Lcom/android/ims/internal/uce/presence/IPresenceListener;->unpublishMessageSent()V
-Lcom/android/ims/internal/uce/presence/IPresenceService$Stub;-><init>()V
-Lcom/android/ims/internal/uce/presence/IPresenceService;->addListener(ILcom/android/ims/internal/uce/presence/IPresenceListener;Lcom/android/ims/internal/uce/common/UceLong;)Lcom/android/ims/internal/uce/common/StatusCode;
-Lcom/android/ims/internal/uce/presence/IPresenceService;->getContactCap(ILjava/lang/String;I)Lcom/android/ims/internal/uce/common/StatusCode;
-Lcom/android/ims/internal/uce/presence/IPresenceService;->getContactListCap(I[Ljava/lang/String;I)Lcom/android/ims/internal/uce/common/StatusCode;
-Lcom/android/ims/internal/uce/presence/IPresenceService;->getVersion(I)Lcom/android/ims/internal/uce/common/StatusCode;
-Lcom/android/ims/internal/uce/presence/IPresenceService;->publishMyCap(ILcom/android/ims/internal/uce/presence/PresCapInfo;I)Lcom/android/ims/internal/uce/common/StatusCode;
-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/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/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;-><init>()V
-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/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/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
-Lcom/android/ims/internal/uce/uceservice/IUceService;->createPresenceService(Lcom/android/ims/internal/uce/presence/IPresenceListener;Lcom/android/ims/internal/uce/common/UceLong;)I
-Lcom/android/ims/internal/uce/uceservice/IUceService;->destroyOptionsService(I)V
-Lcom/android/ims/internal/uce/uceservice/IUceService;->destroyPresenceService(I)V
-Lcom/android/ims/internal/uce/uceservice/IUceService;->getOptionsService()Lcom/android/ims/internal/uce/options/IOptionsService;
-Lcom/android/ims/internal/uce/uceservice/IUceService;->getPresenceService()Lcom/android/ims/internal/uce/presence/IPresenceService;
-Lcom/android/ims/internal/uce/uceservice/IUceService;->getServiceStatus()Z
-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/R$array;->config_mobile_hotspot_provision_app:I
-Lcom/android/internal/R$array;->config_tether_wifi_regexs:I
-Lcom/android/internal/R$array;->maps_starting_lat_lng:I
-Lcom/android/internal/R$array;->maps_starting_zoom:I
-Lcom/android/internal/R$attr;->actionBarStyle:I
-Lcom/android/internal/R$attr;->mapViewStyle:I
-Lcom/android/internal/R$attr;->state_focused:I
-Lcom/android/internal/R$attr;->state_pressed:I
-Lcom/android/internal/R$attr;->state_selected:I
-Lcom/android/internal/R$attr;->switchStyle:I
-Lcom/android/internal/R$bool;->config_mms_content_disposition_support:I
-Lcom/android/internal/R$bool;->config_showNavigationBar:I
-Lcom/android/internal/R$dimen;-><init>()V
-Lcom/android/internal/R$dimen;->navigation_bar_height:I
-Lcom/android/internal/R$dimen;->navigation_bar_height_landscape:I
-Lcom/android/internal/R$dimen;->status_bar_height:I
-Lcom/android/internal/R$dimen;->toast_y_offset:I
-Lcom/android/internal/R$drawable;->btn_check_off:I
-Lcom/android/internal/R$drawable;->compass_arrow:I
-Lcom/android/internal/R$drawable;->compass_base:I
-Lcom/android/internal/R$drawable;->ic_maps_indicator_current_position_anim:I
-Lcom/android/internal/R$drawable;->ic_menu_close_clear_cancel:I
-Lcom/android/internal/R$drawable;->loading_tile_android:I
-Lcom/android/internal/R$drawable;->maps_google_logo:I
-Lcom/android/internal/R$drawable;->no_tile_256:I
-Lcom/android/internal/R$drawable;->reticle:I
-Lcom/android/internal/R$id;->amPm:I
-Lcom/android/internal/R$id;->edittext_container:I
-Lcom/android/internal/R$id;->icon:I
-Lcom/android/internal/R$id;->message:I
-Lcom/android/internal/R$id;->minute:I
-Lcom/android/internal/R$id;->shortcut:I
-Lcom/android/internal/R$id;->text:I
-Lcom/android/internal/R$id;->time:I
-Lcom/android/internal/R$id;->timePicker:I
-Lcom/android/internal/R$id;->title:I
-Lcom/android/internal/R$id;->title_container:I
-Lcom/android/internal/R$integer;->config_screenBrightnessDim:I
-Lcom/android/internal/R$integer;->config_toastDefaultGravity:I
-Lcom/android/internal/R$layout;->screen_title:I
-Lcom/android/internal/R$string;->byteShort:I
-Lcom/android/internal/R$string;->gigabyteShort:I
-Lcom/android/internal/R$string;->kilobyteShort:I
-Lcom/android/internal/R$string;->megabyteShort:I
-Lcom/android/internal/R$string;->petabyteShort:I
-Lcom/android/internal/R$string;->terabyteShort:I
-Lcom/android/internal/R$style;->Theme:I
-Lcom/android/internal/R$styleable;->AbsListView:[I
-Lcom/android/internal/R$styleable;->AbsListView_cacheColorHint:I
-Lcom/android/internal/R$styleable;->AbsListView_choiceMode:I
-Lcom/android/internal/R$styleable;->AbsListView_drawSelectorOnTop:I
-Lcom/android/internal/R$styleable;->AbsListView_fastScrollAlwaysVisible:I
-Lcom/android/internal/R$styleable;->AbsListView_fastScrollEnabled:I
-Lcom/android/internal/R$styleable;->AbsListView_listSelector:I
-Lcom/android/internal/R$styleable;->AbsListView_scrollingCache:I
-Lcom/android/internal/R$styleable;->AbsListView_smoothScrollbar:I
-Lcom/android/internal/R$styleable;->AbsListView_stackFromBottom:I
-Lcom/android/internal/R$styleable;->AbsListView_textFilterEnabled:I
-Lcom/android/internal/R$styleable;->AbsListView_transcriptMode:I
-Lcom/android/internal/R$styleable;->AccountAuthenticator:[I
-Lcom/android/internal/R$styleable;->AccountAuthenticator_accountPreferences:I
-Lcom/android/internal/R$styleable;->AccountAuthenticator_accountType:I
-Lcom/android/internal/R$styleable;->AccountAuthenticator_customTokens:I
-Lcom/android/internal/R$styleable;->AccountAuthenticator_icon:I
-Lcom/android/internal/R$styleable;->AccountAuthenticator_label:I
-Lcom/android/internal/R$styleable;->AccountAuthenticator_smallIcon:I
-Lcom/android/internal/R$styleable;->AndroidManifest:[I
-Lcom/android/internal/R$styleable;->AndroidManifestActivity:[I
-Lcom/android/internal/R$styleable;->AndroidManifestActivity_allowTaskReparenting:I
-Lcom/android/internal/R$styleable;->AndroidManifestActivity_configChanges:I
-Lcom/android/internal/R$styleable;->AndroidManifestActivity_description:I
-Lcom/android/internal/R$styleable;->AndroidManifestActivity_enabled:I
-Lcom/android/internal/R$styleable;->AndroidManifestActivity_excludeFromRecents:I
-Lcom/android/internal/R$styleable;->AndroidManifestActivity_exported:I
-Lcom/android/internal/R$styleable;->AndroidManifestActivity_hardwareAccelerated:I
-Lcom/android/internal/R$styleable;->AndroidManifestActivity_icon:I
-Lcom/android/internal/R$styleable;->AndroidManifestActivity_immersive:I
-Lcom/android/internal/R$styleable;->AndroidManifestActivity_label:I
-Lcom/android/internal/R$styleable;->AndroidManifestActivity_launchMode:I
-Lcom/android/internal/R$styleable;->AndroidManifestActivity_logo:I
-Lcom/android/internal/R$styleable;->AndroidManifestActivity_name:I
-Lcom/android/internal/R$styleable;->AndroidManifestActivity_noHistory:I
-Lcom/android/internal/R$styleable;->AndroidManifestActivity_permission:I
-Lcom/android/internal/R$styleable;->AndroidManifestActivity_process:I
-Lcom/android/internal/R$styleable;->AndroidManifestActivity_screenOrientation:I
-Lcom/android/internal/R$styleable;->AndroidManifestActivity_taskAffinity:I
-Lcom/android/internal/R$styleable;->AndroidManifestActivity_theme:I
-Lcom/android/internal/R$styleable;->AndroidManifestActivity_uiOptions:I
-Lcom/android/internal/R$styleable;->AndroidManifestActivity_windowSoftInputMode:I
-Lcom/android/internal/R$styleable;->AndroidManifestApplication:[I
-Lcom/android/internal/R$styleable;->AndroidManifestApplication_enabled:I
-Lcom/android/internal/R$styleable;->AndroidManifestApplication_hardwareAccelerated:I
-Lcom/android/internal/R$styleable;->AndroidManifestApplication_label:I
-Lcom/android/internal/R$styleable;->AndroidManifestApplication_largeHeap:I
-Lcom/android/internal/R$styleable;->AndroidManifestApplication_name:I
-Lcom/android/internal/R$styleable;->AndroidManifestApplication_permission:I
-Lcom/android/internal/R$styleable;->AndroidManifestApplication_process:I
-Lcom/android/internal/R$styleable;->AndroidManifestApplication_supportsRtl:I
-Lcom/android/internal/R$styleable;->AndroidManifestApplication_theme:I
-Lcom/android/internal/R$styleable;->AndroidManifestApplication_uiOptions:I
-Lcom/android/internal/R$styleable;->AndroidManifestData:[I
-Lcom/android/internal/R$styleable;->AndroidManifestIntentFilter:[I
-Lcom/android/internal/R$styleable;->AndroidManifestIntentFilter_priority:I
-Lcom/android/internal/R$styleable;->AndroidManifestMetaData:[I
-Lcom/android/internal/R$styleable;->AndroidManifestMetaData_name:I
-Lcom/android/internal/R$styleable;->AndroidManifestMetaData_resource:I
-Lcom/android/internal/R$styleable;->AndroidManifestMetaData_value:I
-Lcom/android/internal/R$styleable;->AndroidManifestService:[I
-Lcom/android/internal/R$styleable;->AndroidManifestService_enabled:I
-Lcom/android/internal/R$styleable;->AndroidManifestService_exported:I
-Lcom/android/internal/R$styleable;->AndroidManifestService_name:I
-Lcom/android/internal/R$styleable;->AndroidManifestService_permission:I
-Lcom/android/internal/R$styleable;->AndroidManifestService_process:I
-Lcom/android/internal/R$styleable;->AndroidManifestUsesPermission:[I
-Lcom/android/internal/R$styleable;->AndroidManifestUsesPermission_name:I
-Lcom/android/internal/R$styleable;->AndroidManifestUsesSdk:[I
-Lcom/android/internal/R$styleable;->AndroidManifestUsesSdk_minSdkVersion:I
-Lcom/android/internal/R$styleable;->AndroidManifestUsesSdk_targetSdkVersion:I
-Lcom/android/internal/R$styleable;->AndroidManifest_installLocation:I
-Lcom/android/internal/R$styleable;->AndroidManifest_sharedUserId:I
-Lcom/android/internal/R$styleable;->AndroidManifest_versionCode:I
-Lcom/android/internal/R$styleable;->AndroidManifest_versionName:I
-Lcom/android/internal/R$styleable;->CheckBoxPreference:[I
-Lcom/android/internal/R$styleable;->CheckBoxPreference_disableDependentsState:I
-Lcom/android/internal/R$styleable;->CheckBoxPreference_summaryOff:I
-Lcom/android/internal/R$styleable;->CheckBoxPreference_summaryOn:I
-Lcom/android/internal/R$styleable;->CompoundButton:[I
-Lcom/android/internal/R$styleable;->CompoundButton_button:I
-Lcom/android/internal/R$styleable;->CompoundButton_checked:I
-Lcom/android/internal/R$styleable;->DialogPreference:[I
-Lcom/android/internal/R$styleable;->DialogPreference_dialogTitle:I
-Lcom/android/internal/R$styleable;->EdgeEffect:[I
-Lcom/android/internal/R$styleable;->EdgeEffect_colorEdgeEffect:I
-Lcom/android/internal/R$styleable;->GridView:[I
-Lcom/android/internal/R$styleable;->IconMenuView:[I
-Lcom/android/internal/R$styleable;->ImageView:[I
-Lcom/android/internal/R$styleable;->ImageView_scaleType:I
-Lcom/android/internal/R$styleable;->ImageView_src:I
-Lcom/android/internal/R$styleable;->ListPreference:[I
-Lcom/android/internal/R$styleable;->ListPreference_entries:I
-Lcom/android/internal/R$styleable;->ListView:[I
-Lcom/android/internal/R$styleable;->ListView_divider:I
-Lcom/android/internal/R$styleable;->ListView_dividerHeight:I
-Lcom/android/internal/R$styleable;->ListView_entries:I
-Lcom/android/internal/R$styleable;->ListView_footerDividersEnabled:I
-Lcom/android/internal/R$styleable;->ListView_headerDividersEnabled:I
-Lcom/android/internal/R$styleable;->ListView_overScrollFooter:I
-Lcom/android/internal/R$styleable;->ListView_overScrollHeader:I
-Lcom/android/internal/R$styleable;->NumberPicker:[I
-Lcom/android/internal/R$styleable;->PopupWindow:[I
-Lcom/android/internal/R$styleable;->Preference:[I
-Lcom/android/internal/R$styleable;->PreferenceGroup:[I
-Lcom/android/internal/R$styleable;->PreferenceGroup_orderingFromXml:I
-Lcom/android/internal/R$styleable;->Preference_defaultValue:I
-Lcom/android/internal/R$styleable;->Preference_dependency:I
-Lcom/android/internal/R$styleable;->Preference_enabled:I
-Lcom/android/internal/R$styleable;->Preference_fragment:I
-Lcom/android/internal/R$styleable;->Preference_icon:I
-Lcom/android/internal/R$styleable;->Preference_key:I
-Lcom/android/internal/R$styleable;->Preference_layout:I
-Lcom/android/internal/R$styleable;->Preference_order:I
-Lcom/android/internal/R$styleable;->Preference_persistent:I
-Lcom/android/internal/R$styleable;->Preference_selectable:I
-Lcom/android/internal/R$styleable;->Preference_shouldDisableView:I
-Lcom/android/internal/R$styleable;->Preference_summary:I
-Lcom/android/internal/R$styleable;->Preference_title:I
-Lcom/android/internal/R$styleable;->Preference_widgetLayout:I
-Lcom/android/internal/R$styleable;->ScrollView:[I
-Lcom/android/internal/R$styleable;->ScrollView_fillViewport:I
-Lcom/android/internal/R$styleable;->SyncAdapter:[I
-Lcom/android/internal/R$styleable;->SyncAdapter_accountType:I
-Lcom/android/internal/R$styleable;->SyncAdapter_allowParallelSyncs:I
-Lcom/android/internal/R$styleable;->SyncAdapter_contentAuthority:I
-Lcom/android/internal/R$styleable;->SyncAdapter_isAlwaysSyncable:I
-Lcom/android/internal/R$styleable;->SyncAdapter_settingsActivity:I
-Lcom/android/internal/R$styleable;->SyncAdapter_supportsUploading:I
-Lcom/android/internal/R$styleable;->SyncAdapter_userVisible:I
-Lcom/android/internal/R$styleable;->TabWidget:[I
-Lcom/android/internal/R$styleable;->TextAppearance:[I
-Lcom/android/internal/R$styleable;->TextView:[I
-Lcom/android/internal/R$styleable;->TextViewAppearance:[I
-Lcom/android/internal/R$styleable;->TextView_drawableBottom:I
-Lcom/android/internal/R$styleable;->TextView_drawableLeft:I
-Lcom/android/internal/R$styleable;->TextView_drawableRight:I
-Lcom/android/internal/R$styleable;->TextView_drawableTop:I
-Lcom/android/internal/R$styleable;->TextView_maxLines:I
-Lcom/android/internal/R$styleable;->TextView_textColor:I
-Lcom/android/internal/R$styleable;->TextView_textColorHint:I
-Lcom/android/internal/R$styleable;->TwoLineListItem:[I
-Lcom/android/internal/R$styleable;->View:[I
-Lcom/android/internal/R$styleable;->ViewGroup_Layout:[I
-Lcom/android/internal/R$styleable;->ViewGroup_Layout_layout_height:I
-Lcom/android/internal/R$styleable;->ViewGroup_Layout_layout_width:I
-Lcom/android/internal/R$styleable;->ViewStub:[I
-Lcom/android/internal/R$styleable;->ViewStub_inflatedId:I
-Lcom/android/internal/R$styleable;->ViewStub_layout:I
-Lcom/android/internal/R$styleable;->View_background:I
-Lcom/android/internal/R$styleable;->View_id:I
-Lcom/android/internal/R$styleable;->Window:[I
-Lcom/android/internal/R$styleable;->Window_windowActionBarFullscreenDecorLayout:I
-Lcom/android/internal/R$styleable;->Window_windowIsFloating:I
-Lcom/android/internal/R$styleable;->Window_windowIsTranslucent:I
-Lcom/android/internal/R$styleable;->Window_windowShowWallpaper:I
-Lcom/android/internal/R$xml;->power_profile:I
-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$RecycleListView;-><init>(Landroid/content/Context;Landroid/util/AttributeSet;)V
-Lcom/android/internal/app/AlertController;->getButton(I)Landroid/widget/Button;
-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/IAppOpsService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-Lcom/android/internal/app/IAppOpsService$Stub$Proxy;->checkOperation(IILjava/lang/String;)I
-Lcom/android/internal/app/IAppOpsService$Stub$Proxy;->setMode(IILjava/lang/String;I)V
-Lcom/android/internal/app/IAppOpsService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/app/IAppOpsService;
-Lcom/android/internal/app/IAppOpsService;->finishOperation(Landroid/os/IBinder;IILjava/lang/String;)V
-Lcom/android/internal/app/IBatteryStats$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-Lcom/android/internal/app/IBatteryStats$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/app/IBatteryStats;
-Lcom/android/internal/app/IBatteryStats;->getStatistics()[B
-Lcom/android/internal/app/IVoiceInteractionManagerService$Stub$Proxy;->showSessionFromSession(Landroid/os/IBinder;Landroid/os/Bundle;I)Z
-Lcom/android/internal/app/IVoiceInteractionManagerService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/app/IVoiceInteractionManagerService;
-Lcom/android/internal/app/IVoiceInteractionManagerService;->getKeyphraseSoundModel(ILjava/lang/String;)Landroid/hardware/soundtrigger/SoundTrigger$KeyphraseSoundModel;
-Lcom/android/internal/appwidget/IAppWidgetService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/appwidget/IAppWidgetService;
-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/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/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
-Lcom/android/internal/location/ILocationProvider;->getProperties()Lcom/android/internal/location/ProviderProperties;
-Lcom/android/internal/location/ILocationProvider;->getStatus(Landroid/os/Bundle;)I
-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/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;->drainType:Lcom/android/internal/os/BatterySipper$DrainType;
-Lcom/android/internal/os/BatterySipper;->getUid()I
-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/BatteryStatsHelper;-><init>(Landroid/content/Context;ZZ)V
-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;->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/BatteryStatsImpl$Timer;->getCountLocked(I)I
-Lcom/android/internal/os/BatteryStatsImpl$Timer;->getTotalTimeLocked(JI)J
-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$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;->CREATOR:Landroid/os/Parcelable$Creator;
-Lcom/android/internal/os/BatteryStatsImpl;->computeBatteryRealtime(JI)J
-Lcom/android/internal/os/BatteryStatsImpl;->computeBatteryUptime(JI)J
-Lcom/android/internal/os/BatteryStatsImpl;->getBatteryRealtime(J)J
-Lcom/android/internal/os/BatteryStatsImpl;->getDischargeAmount(I)I
-Lcom/android/internal/os/BatteryStatsImpl;->getDischargeCurrentLevel()I
-Lcom/android/internal/os/BatteryStatsImpl;->getDischargeStartLevel()I
-Lcom/android/internal/os/BatteryStatsImpl;->getGlobalWifiRunningTime(JI)J
-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;->getScreenOnTime(JI)J
-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;->getWifiOnTime(JI)J
-Lcom/android/internal/os/FuseAppLoop;->onCommand(IJJJI[B)V
-Lcom/android/internal/os/FuseAppLoop;->onOpen(JJ)[B
-Lcom/android/internal/os/IDropBoxManagerService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/os/IDropBoxManagerService;
-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/SomeArgs;->arg1:Ljava/lang/Object;
-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/telephony/GsmAlphabet;->gsm7BitPackedToString([BII)Ljava/lang/String;
-Lcom/android/internal/telephony/GsmAlphabet;->stringToGsm7BitPacked(Ljava/lang/String;)[B
-Lcom/android/internal/telephony/IMms$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/telephony/IMms;
-Lcom/android/internal/telephony/IPhoneSubInfo$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-Lcom/android/internal/telephony/IPhoneSubInfo$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/telephony/IPhoneSubInfo;
-Lcom/android/internal/telephony/ISms$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/telephony/ISms;
-Lcom/android/internal/telephony/ISub$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-Lcom/android/internal/telephony/ITelephony$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-Lcom/android/internal/telephony/ITelephony$Stub$Proxy;->endCall()Z
-Lcom/android/internal/telephony/ITelephony$Stub$Proxy;->mRemote:Landroid/os/IBinder;
-Lcom/android/internal/telephony/ITelephony$Stub;->TRANSACTION_call:I
-Lcom/android/internal/telephony/ITelephony$Stub;->TRANSACTION_endCall:I
-Lcom/android/internal/telephony/ITelephony$Stub;->TRANSACTION_getDeviceId:I
-Lcom/android/internal/telephony/ITelephony$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/telephony/ITelephony;
-Lcom/android/internal/telephony/ITelephony;->answerRingingCall()V
-Lcom/android/internal/telephony/ITelephony;->call(Ljava/lang/String;Ljava/lang/String;)V
-Lcom/android/internal/telephony/ITelephony;->dial(Ljava/lang/String;)V
-Lcom/android/internal/telephony/ITelephony;->disableDataConnectivity()Z
-Lcom/android/internal/telephony/ITelephony;->enableDataConnectivity()Z
-Lcom/android/internal/telephony/ITelephony;->endCall()Z
-Lcom/android/internal/telephony/ITelephony;->endCallForSubscriber(I)Z
-Lcom/android/internal/telephony/ITelephony;->getCallState()I
-Lcom/android/internal/telephony/ITelephony;->getDataEnabled(I)Z
-Lcom/android/internal/telephony/ITelephony;->getDataState()I
-Lcom/android/internal/telephony/ITelephony;->isIdle(Ljava/lang/String;)Z
-Lcom/android/internal/telephony/ITelephony;->setRadio(Z)Z
-Lcom/android/internal/telephony/ITelephony;->silenceRinger()V
-Lcom/android/internal/telephony/ITelephonyRegistry$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-Lcom/android/internal/telephony/ITelephonyRegistry$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/telephony/ITelephonyRegistry;
-Lcom/android/internal/telephony/ITelephonyRegistry;->notifyCallState(ILjava/lang/String;)V
-Lcom/android/internal/telephony/OperatorInfo$State;->CURRENT:Lcom/android/internal/telephony/OperatorInfo$State;
-Lcom/android/internal/telephony/OperatorInfo$State;->FORBIDDEN:Lcom/android/internal/telephony/OperatorInfo$State;
-Lcom/android/internal/telephony/OperatorInfo;-><init>(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
-Lcom/android/internal/telephony/OperatorInfo;->CREATOR:Landroid/os/Parcelable$Creator;
-Lcom/android/internal/telephony/OperatorInfo;->getOperatorAlphaLong()Ljava/lang/String;
-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/telephony/SmsHeader$ConcatRef;->msgCount:I
-Lcom/android/internal/telephony/SmsHeader$ConcatRef;->refNumber:I
-Lcom/android/internal/telephony/SmsHeader$ConcatRef;->seqNumber:I
-Lcom/android/internal/telephony/SmsHeader;->concatRef:Lcom/android/internal/telephony/SmsHeader$ConcatRef;
-Lcom/android/internal/telephony/SmsMessageBase;->mUserDataHeader:Lcom/android/internal/telephony/SmsHeader;
-Lcom/android/internal/telephony/SmsRawData;-><init>([B)V
-Lcom/android/internal/telephony/SmsRawData;->CREATOR:Landroid/os/Parcelable$Creator;
-Lcom/android/internal/textservice/ITextServicesManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-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(III)V
-Lcom/android/internal/util/AsyncChannel;->sendMessage(Landroid/os/Message;)V
-Lcom/android/internal/util/FastPrintWriter;-><init>(Ljava/io/OutputStream;)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
-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/view/IInputConnectionWrapper;->mInputConnection:Landroid/view/inputmethod/InputConnection;
-Lcom/android/internal/view/IInputConnectionWrapper;->mLock:Ljava/lang/Object;
-Lcom/android/internal/view/IInputMethodManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-Lcom/android/internal/view/IInputMethodManager$Stub$Proxy;->getEnabledInputMethodList()Ljava/util/List;
-Lcom/android/internal/view/IInputMethodManager$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/view/IInputMethodManager;
-Lcom/android/internal/view/InputBindResult;->CREATOR:Landroid/os/Parcelable$Creator;
-Lcom/android/internal/view/menu/MenuBuilder;-><init>(Landroid/content/Context;)V
-Lcom/android/internal/view/menu/MenuBuilder;->mContext:Landroid/content/Context;
-Lcom/android/internal/view/menu/MenuBuilder;->setCurrentMenuInfo(Landroid/view/ContextMenu$ContextMenuInfo;)V
-Lcom/android/internal/view/menu/MenuBuilder;->setOptionalIconsVisible(Z)V
-Lcom/android/internal/view/menu/MenuItemImpl;->mIconResId:I
-Lcom/android/internal/view/menu/MenuItemImpl;->setMenuInfo(Landroid/view/ContextMenu$ContextMenuInfo;)V
-Lcom/android/internal/view/menu/MenuPopupHelper;->mForceShowIcon:Z
-Lcom/android/internal/view/menu/MenuPopupHelper;->setForceShowIcon(Z)V
-Lcom/android/internal/view/menu/MenuView$ItemView;->getItemData()Lcom/android/internal/view/menu/MenuItemImpl;
-Lcom/android/okhttp/ConnectionPool;->keepAliveDurationNs:J
-Lcom/android/okhttp/ConnectionPool;->maxIdleConnections:I
-Lcom/android/okhttp/ConnectionPool;->systemDefault:Lcom/android/okhttp/ConnectionPool;
-Lcom/android/okhttp/HttpUrl;->encodedPath()Ljava/lang/String;
-Lcom/android/okhttp/HttpUrl;->query()Ljava/lang/String;
-Lcom/android/okhttp/OkHttpClient;->DEFAULT_PROTOCOLS:Ljava/util/List;
-Lcom/android/okhttp/OkHttpClient;->connectionPool:Lcom/android/okhttp/ConnectionPool;
-Lcom/android/okhttp/OkHttpClient;->dns:Lcom/android/okhttp/Dns;
-Lcom/android/okhttp/OkHttpClient;->setProtocols(Ljava/util/List;)Lcom/android/okhttp/OkHttpClient;
-Lcom/android/okhttp/OkHttpClient;->setRetryOnConnectionFailure(Z)V
-Lcom/android/okhttp/Request;->headers:Lcom/android/okhttp/Headers;
-Lcom/android/okhttp/Request;->method:Ljava/lang/String;
-Lcom/android/okhttp/Request;->url:Lcom/android/okhttp/HttpUrl;
-Lcom/android/okhttp/Response;->code:I
-Lcom/android/okhttp/Response;->headers:Lcom/android/okhttp/Headers;
-Lcom/android/okhttp/Response;->message:Ljava/lang/String;
-Lcom/android/okhttp/Response;->networkResponse:Lcom/android/okhttp/Response;
-Lcom/android/okhttp/Response;->protocol:Lcom/android/okhttp/Protocol;
-Lcom/android/okhttp/internal/http/HttpEngine;->httpStream:Lcom/android/okhttp/internal/http/HttpStream;
-Lcom/android/okhttp/internal/http/HttpEngine;->networkRequest(Lcom/android/okhttp/Request;)Lcom/android/okhttp/Request;
-Lcom/android/okhttp/internal/http/HttpEngine;->networkRequest:Lcom/android/okhttp/Request;
-Lcom/android/okhttp/internal/http/HttpEngine;->priorResponse:Lcom/android/okhttp/Response;
-Lcom/android/okhttp/internal/http/HttpEngine;->userResponse:Lcom/android/okhttp/Response;
-Lcom/android/okhttp/okio/ByteString;->readObject(Ljava/io/ObjectInputStream;)V
-Lcom/android/okhttp/okio/ByteString;->serialVersionUID:J
-Lcom/android/okhttp/okio/ByteString;->writeObject(Ljava/io/ObjectOutputStream;)V
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->getAlpnSelectedProtocol()[B
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->getApplicationProtocol()Ljava/lang/String;
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->getApplicationProtocols()[Ljava/lang/String;
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->getChannelId()[B
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->getHandshakeApplicationProtocol()Ljava/lang/String;
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->getHostname()Ljava/lang/String;
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->getHostnameOrIP()Ljava/lang/String;
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->getNpnSelectedProtocol()[B
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->getSoWriteTimeout()I
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->setAlpnProtocols([B)V
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->setAlpnProtocols([Ljava/lang/String;)V
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->setApplicationProtocols([Ljava/lang/String;)V
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->setChannelIdEnabled(Z)V
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->setChannelIdPrivateKey(Ljava/security/PrivateKey;)V
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->setHandshakeTimeout(I)V
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->setHostname(Ljava/lang/String;)V
-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/ConscryptSocketBase;->getHostname()Ljava/lang/String;
-Lcom/android/org/conscrypt/ConscryptSocketBase;->getHostnameOrIP()Ljava/lang/String;
-Lcom/android/org/conscrypt/ConscryptSocketBase;->getSoWriteTimeout()I
-Lcom/android/org/conscrypt/ConscryptSocketBase;->setHandshakeTimeout(I)V
-Lcom/android/org/conscrypt/ConscryptSocketBase;->setHostname(Ljava/lang/String;)V
-Lcom/android/org/conscrypt/ConscryptSocketBase;->setSoWriteTimeout(I)V
-Lcom/android/org/conscrypt/ConscryptSocketBase;->socket:Ljava/net/Socket;
-Lcom/android/org/conscrypt/OpenSSLSocketImpl;->getAlpnSelectedProtocol()[B
-Lcom/android/org/conscrypt/OpenSSLSocketImpl;->getChannelId()[B
-Lcom/android/org/conscrypt/OpenSSLSocketImpl;->getHostname()Ljava/lang/String;
-Lcom/android/org/conscrypt/OpenSSLSocketImpl;->getHostnameOrIP()Ljava/lang/String;
-Lcom/android/org/conscrypt/OpenSSLSocketImpl;->getNpnSelectedProtocol()[B
-Lcom/android/org/conscrypt/OpenSSLSocketImpl;->getSoWriteTimeout()I
-Lcom/android/org/conscrypt/OpenSSLSocketImpl;->setAlpnProtocols([B)V
-Lcom/android/org/conscrypt/OpenSSLSocketImpl;->setAlpnProtocols([Ljava/lang/String;)V
-Lcom/android/org/conscrypt/OpenSSLSocketImpl;->setChannelIdEnabled(Z)V
-Lcom/android/org/conscrypt/OpenSSLSocketImpl;->setChannelIdPrivateKey(Ljava/security/PrivateKey;)V
-Lcom/android/org/conscrypt/OpenSSLSocketImpl;->setHandshakeTimeout(I)V
-Lcom/android/org/conscrypt/OpenSSLSocketImpl;->setHostname(Ljava/lang/String;)V
-Lcom/android/org/conscrypt/OpenSSLSocketImpl;->setNpnProtocols([B)V
-Lcom/android/org/conscrypt/OpenSSLSocketImpl;->setSoWriteTimeout(I)V
-Lcom/android/org/conscrypt/OpenSSLSocketImpl;->setUseSessionTickets(Z)V
-Lcom/android/org/conscrypt/OpenSSLX509Certificate;->mContext:J
-Lcom/android/org/conscrypt/OpenSSLX509Certificate;->serialVersionUID:J
-Lcom/android/org/conscrypt/OpenSSLX509CertificateFactory$ParsingException;->serialVersionUID:J
-Lcom/android/org/conscrypt/TrustManagerImpl;-><init>(Ljava/security/KeyStore;)V
-Ldalvik/system/BaseDexClassLoader;->addDexPath(Ljava/lang/String;)V
-Ldalvik/system/BaseDexClassLoader;->getLdLibraryPath()Ljava/lang/String;
-Ldalvik/system/BaseDexClassLoader;->pathList:Ldalvik/system/DexPathList;
-Ldalvik/system/BlockGuard$Policy;->onNetwork()V
-Ldalvik/system/BlockGuard$Policy;->onReadFromDisk()V
-Ldalvik/system/BlockGuard;->getThreadPolicy()Ldalvik/system/BlockGuard$Policy;
-Ldalvik/system/CloseGuard;->close()V
-Ldalvik/system/CloseGuard;->get()Ldalvik/system/CloseGuard;
-Ldalvik/system/CloseGuard;->open(Ljava/lang/String;)V
-Ldalvik/system/CloseGuard;->warnIfOpen()V
-Ldalvik/system/DexFile$DFEnum;->mNameList:[Ljava/lang/String;
-Ldalvik/system/DexFile;->getClassNameList(Ljava/lang/Object;)[Ljava/lang/String;
-Ldalvik/system/DexFile;->isBackedByOatFile()Z
-Ldalvik/system/DexFile;->loadClassBinaryName(Ljava/lang/String;Ljava/lang/ClassLoader;Ljava/util/List;)Ljava/lang/Class;
-Ldalvik/system/DexFile;->mCookie:Ljava/lang/Object;
-Ldalvik/system/DexFile;->mFileName:Ljava/lang/String;
-Ldalvik/system/DexFile;->mInternalCookie:Ljava/lang/Object;
-Ldalvik/system/DexFile;->openDexFile(Ljava/lang/String;Ljava/lang/String;ILjava/lang/ClassLoader;[Ldalvik/system/DexPathList$Element;)Ljava/lang/Object;
-Ldalvik/system/DexPathList$Element;-><init>(Ldalvik/system/DexFile;Ljava/io/File;)V
-Ldalvik/system/DexPathList$Element;-><init>(Ljava/io/File;ZLjava/io/File;Ldalvik/system/DexFile;)V
-Ldalvik/system/DexPathList$Element;->dexFile:Ldalvik/system/DexFile;
-Ldalvik/system/DexPathList$NativeLibraryElement;-><init>(Ljava/io/File;)V
-Ldalvik/system/DexPathList$NativeLibraryElement;->path:Ljava/io/File;
-Ldalvik/system/DexPathList;-><init>(Ljava/lang/ClassLoader;Ljava/lang/String;Ljava/lang/String;Ljava/io/File;)V
-Ldalvik/system/DexPathList;->addDexPath(Ljava/lang/String;Ljava/io/File;)V
-Ldalvik/system/DexPathList;->definingContext:Ljava/lang/ClassLoader;
-Ldalvik/system/DexPathList;->dexElements:[Ldalvik/system/DexPathList$Element;
-Ldalvik/system/DexPathList;->loadDexFile(Ljava/io/File;Ljava/io/File;Ljava/lang/ClassLoader;[Ldalvik/system/DexPathList$Element;)Ldalvik/system/DexFile;
-Ldalvik/system/DexPathList;->makeDexElements(Ljava/util/List;Ljava/io/File;Ljava/util/List;Ljava/lang/ClassLoader;)[Ldalvik/system/DexPathList$Element;
-Ldalvik/system/DexPathList;->makeInMemoryDexElements([Ljava/nio/ByteBuffer;Ljava/util/List;)[Ldalvik/system/DexPathList$Element;
-Ldalvik/system/DexPathList;->makePathElements(Ljava/util/List;)[Ldalvik/system/DexPathList$NativeLibraryElement;
-Ldalvik/system/DexPathList;->makePathElements(Ljava/util/List;Ljava/io/File;Ljava/util/List;)[Ldalvik/system/DexPathList$Element;
-Ldalvik/system/DexPathList;->nativeLibraryDirectories:Ljava/util/List;
-Ldalvik/system/DexPathList;->nativeLibraryPathElements:[Ldalvik/system/DexPathList$NativeLibraryElement;
-Ldalvik/system/DexPathList;->splitPaths(Ljava/lang/String;Z)Ljava/util/List;
-Ldalvik/system/DexPathList;->systemNativeLibraryDirectories:Ljava/util/List;
-Ldalvik/system/VMDebug;->dumpReferenceTables()V
-Ldalvik/system/VMDebug;->isDebuggerConnected()Z
-Ldalvik/system/VMRuntime;->addressOf(Ljava/lang/Object;)J
-Ldalvik/system/VMRuntime;->clearGrowthLimit()V
-Ldalvik/system/VMRuntime;->gcSoftReferences()V
-Ldalvik/system/VMRuntime;->getCurrentInstructionSet()Ljava/lang/String;
-Ldalvik/system/VMRuntime;->getExternalBytesAllocated()J
-Ldalvik/system/VMRuntime;->getInstructionSet(Ljava/lang/String;)Ljava/lang/String;
-Ldalvik/system/VMRuntime;->getRuntime()Ldalvik/system/VMRuntime;
-Ldalvik/system/VMRuntime;->is64Bit()Z
-Ldalvik/system/VMRuntime;->is64BitAbi(Ljava/lang/String;)Z
-Ldalvik/system/VMRuntime;->newNonMovableArray(Ljava/lang/Class;I)Ljava/lang/Object;
-Ldalvik/system/VMRuntime;->registerNativeAllocation(I)V
-Ldalvik/system/VMRuntime;->registerNativeFree(I)V
-Ldalvik/system/VMRuntime;->runFinalization(J)V
-Ldalvik/system/VMRuntime;->setMinimumHeapSize(J)J
-Ldalvik/system/VMRuntime;->setTargetHeapUtilization(F)F
-Ldalvik/system/VMRuntime;->setTargetSdkVersion(I)V
-Ldalvik/system/VMRuntime;->trackExternalAllocation(J)Z
-Ldalvik/system/VMRuntime;->trackExternalFree(J)V
-Ldalvik/system/VMRuntime;->vmInstructionSet()Ljava/lang/String;
-Ldalvik/system/VMRuntime;->vmLibrary()Ljava/lang/String;
-Ldalvik/system/VMStack;->getCallingClassLoader()Ljava/lang/ClassLoader;
-Ldalvik/system/VMStack;->getStackClass2()Ljava/lang/Class;
-Ljava/awt/font/NumericShaper;->serialVersionUID:J
-Ljava/awt/font/NumericShaper;->writeObject(Ljava/io/ObjectOutputStream;)V
-Ljava/awt/font/TextAttribute;->serialVersionUID:J
-Ljava/beans/IndexedPropertyChangeEvent;->serialVersionUID:J
-Ljava/beans/PropertyChangeEvent;->serialVersionUID:J
-Ljava/beans/PropertyChangeSupport;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/beans/PropertyChangeSupport;->serialPersistentFields:[Ljava/io/ObjectStreamField;
-Ljava/beans/PropertyChangeSupport;->serialVersionUID:J
-Ljava/beans/PropertyChangeSupport;->writeObject(Ljava/io/ObjectOutputStream;)V
-Ljava/io/CharConversionException;->serialVersionUID:J
-Ljava/io/EOFException;->serialVersionUID:J
-Ljava/io/File;->filePath:Ljava/nio/file/Path;
-Ljava/io/File;->fs:Ljava/io/FileSystem;
-Ljava/io/File;->path:Ljava/lang/String;
-Ljava/io/File;->prefixLength:I
-Ljava/io/File;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/io/File;->serialVersionUID:J
-Ljava/io/File;->status:Ljava/io/File$PathStatus;
-Ljava/io/File;->writeObject(Ljava/io/ObjectOutputStream;)V
-Ljava/io/FileDescriptor;->descriptor:I
-Ljava/io/FileDescriptor;->getInt$()I
-Ljava/io/FileDescriptor;->isSocket$()Z
-Ljava/io/FileDescriptor;->setInt$(I)V
-Ljava/io/FileInputStream;->fd:Ljava/io/FileDescriptor;
-Ljava/io/FileNotFoundException;->serialVersionUID:J
-Ljava/io/FileOutputStream;->fd:Ljava/io/FileDescriptor;
-Ljava/io/IOError;->serialVersionUID:J
-Ljava/io/IOException;->serialVersionUID:J
-Ljava/io/InterruptedIOException;->serialVersionUID:J
-Ljava/io/InvalidClassException;->serialVersionUID:J
-Ljava/io/InvalidObjectException;->serialVersionUID:J
-Ljava/io/NotActiveException;->serialVersionUID:J
-Ljava/io/NotSerializableException;->serialVersionUID:J
-Ljava/io/ObjectStreamClass;->getConstructorId(Ljava/lang/Class;)J
-Ljava/io/ObjectStreamClass;->newInstance()Ljava/lang/Object;
-Ljava/io/ObjectStreamClass;->newInstance(Ljava/lang/Class;J)Ljava/lang/Object;
-Ljava/io/ObjectStreamClass;->serialPersistentFields:[Ljava/io/ObjectStreamField;
-Ljava/io/ObjectStreamClass;->serialVersionUID:J
-Ljava/io/ObjectStreamException;->serialVersionUID:J
-Ljava/io/OptionalDataException;->serialVersionUID:J
-Ljava/io/StreamCorruptedException;->serialVersionUID:J
-Ljava/io/SyncFailedException;->serialVersionUID:J
-Ljava/io/UTFDataFormatException;->serialVersionUID:J
-Ljava/io/UncheckedIOException;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/io/UncheckedIOException;->serialVersionUID:J
-Ljava/io/UnsupportedEncodingException;->serialVersionUID:J
-Ljava/io/WriteAbortedException;->serialVersionUID:J
-Ljava/lang/AbstractMethodError;->serialVersionUID:J
-Ljava/lang/AbstractStringBuilder;->value:[C
-Ljava/lang/ArithmeticException;->serialVersionUID:J
-Ljava/lang/ArrayIndexOutOfBoundsException;->serialVersionUID:J
-Ljava/lang/ArrayStoreException;->serialVersionUID:J
-Ljava/lang/AssertionError;->serialVersionUID:J
-Ljava/lang/Boolean;->serialVersionUID:J
-Ljava/lang/Boolean;->value:Z
-Ljava/lang/BootstrapMethodError;->serialVersionUID:J
-Ljava/lang/Byte;->serialVersionUID:J
-Ljava/lang/Byte;->value:B
-Ljava/lang/Character;->serialVersionUID:J
-Ljava/lang/Character;->value:C
-Ljava/lang/Class;->accessFlags:I
-Ljava/lang/Class;->dexCache:Ljava/lang/Object;
-Ljava/lang/Class;->dexClassDefIndex:I
-Ljava/lang/Class;->ifTable:[Ljava/lang/Object;
-Ljava/lang/Class;->serialVersionUID:J
-Ljava/lang/ClassCastException;->serialVersionUID:J
-Ljava/lang/ClassCircularityError;->serialVersionUID:J
-Ljava/lang/ClassFormatError;->serialVersionUID:J
-Ljava/lang/ClassLoader;->parent:Ljava/lang/ClassLoader;
-Ljava/lang/ClassNotFoundException;->serialVersionUID:J
-Ljava/lang/CloneNotSupportedException;->serialVersionUID:J
-Ljava/lang/Daemons$Daemon;->isRunning()Z
-Ljava/lang/Daemons$Daemon;->start()V
-Ljava/lang/Daemons$Daemon;->stop()V
-Ljava/lang/Daemons$Daemon;->thread:Ljava/lang/Thread;
-Ljava/lang/Daemons$FinalizerDaemon;->INSTANCE:Ljava/lang/Daemons$FinalizerDaemon;
-Ljava/lang/Daemons$FinalizerDaemon;->finalizingObject:Ljava/lang/Object;
-Ljava/lang/Daemons$FinalizerWatchdogDaemon;->INSTANCE:Ljava/lang/Daemons$FinalizerWatchdogDaemon;
-Ljava/lang/Daemons$ReferenceQueueDaemon;->INSTANCE:Ljava/lang/Daemons$ReferenceQueueDaemon;
-Ljava/lang/Daemons;->MAX_FINALIZE_NANOS:J
-Ljava/lang/Daemons;->requestHeapTrim()V
-Ljava/lang/Daemons;->start()V
-Ljava/lang/Daemons;->stop()V
-Ljava/lang/Double;->serialVersionUID:J
-Ljava/lang/Double;->value:D
-Ljava/lang/Enum;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/lang/Enum;->readObjectNoData()V
-Ljava/lang/EnumConstantNotPresentException;->serialVersionUID:J
-Ljava/lang/Error;->serialVersionUID:J
-Ljava/lang/Exception;->serialVersionUID:J
-Ljava/lang/ExceptionInInitializerError;->serialVersionUID:J
-Ljava/lang/Float;->serialVersionUID:J
-Ljava/lang/Float;->value:F
-Ljava/lang/IllegalAccessError;->serialVersionUID:J
-Ljava/lang/IllegalAccessException;->serialVersionUID:J
-Ljava/lang/IllegalArgumentException;->serialVersionUID:J
-Ljava/lang/IllegalMonitorStateException;->serialVersionUID:J
-Ljava/lang/IllegalStateException;->serialVersionUID:J
-Ljava/lang/IllegalThreadStateException;->serialVersionUID:J
-Ljava/lang/IncompatibleClassChangeError;->serialVersionUID:J
-Ljava/lang/IndexOutOfBoundsException;->serialVersionUID:J
-Ljava/lang/InstantiationError;->serialVersionUID:J
-Ljava/lang/InstantiationException;->serialVersionUID:J
-Ljava/lang/Integer;->serialVersionUID:J
-Ljava/lang/Integer;->value:I
-Ljava/lang/InternalError;->serialVersionUID:J
-Ljava/lang/InterruptedException;->serialVersionUID:J
-Ljava/lang/LinkageError;->serialVersionUID:J
-Ljava/lang/Long;->serialVersionUID:J
-Ljava/lang/Long;->value:J
-Ljava/lang/NegativeArraySizeException;->serialVersionUID:J
-Ljava/lang/NoClassDefFoundError;->serialVersionUID:J
-Ljava/lang/NoSuchFieldError;->serialVersionUID:J
-Ljava/lang/NoSuchFieldException;->serialVersionUID:J
-Ljava/lang/NoSuchMethodError;->serialVersionUID:J
-Ljava/lang/NoSuchMethodException;->serialVersionUID:J
-Ljava/lang/NullPointerException;->serialVersionUID:J
-Ljava/lang/Number;->serialVersionUID:J
-Ljava/lang/NumberFormatException;->serialVersionUID:J
-Ljava/lang/OutOfMemoryError;->serialVersionUID:J
-Ljava/lang/ReflectiveOperationException;->serialVersionUID:J
-Ljava/lang/Runtime;->load(Ljava/lang/String;Ljava/lang/ClassLoader;)V
-Ljava/lang/Runtime;->loadLibrary(Ljava/lang/String;Ljava/lang/ClassLoader;)V
-Ljava/lang/Runtime;->mLibPaths:[Ljava/lang/String;
-Ljava/lang/Runtime;->nativeLoad(Ljava/lang/String;Ljava/lang/ClassLoader;)Ljava/lang/String;
-Ljava/lang/RuntimeException;->serialVersionUID:J
-Ljava/lang/RuntimePermission;->serialVersionUID:J
-Ljava/lang/SecurityException;->serialVersionUID:J
-Ljava/lang/Short;->serialVersionUID:J
-Ljava/lang/Short;->value:S
-Ljava/lang/StackOverflowError;->serialVersionUID:J
-Ljava/lang/StackTraceElement;->serialVersionUID:J
-Ljava/lang/String$CaseInsensitiveComparator;->readResolve()Ljava/lang/Object;
-Ljava/lang/String$CaseInsensitiveComparator;->serialVersionUID:J
-Ljava/lang/String;-><init>(II[C)V
-Ljava/lang/String;->getCharsNoCheck(II[CI)V
-Ljava/lang/String;->serialPersistentFields:[Ljava/io/ObjectStreamField;
-Ljava/lang/String;->serialVersionUID:J
-Ljava/lang/StringBuffer;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/lang/StringBuffer;->serialPersistentFields:[Ljava/io/ObjectStreamField;
-Ljava/lang/StringBuffer;->serialVersionUID:J
-Ljava/lang/StringBuffer;->writeObject(Ljava/io/ObjectOutputStream;)V
-Ljava/lang/StringBuilder;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/lang/StringBuilder;->serialVersionUID:J
-Ljava/lang/StringBuilder;->writeObject(Ljava/io/ObjectOutputStream;)V
-Ljava/lang/StringIndexOutOfBoundsException;->serialVersionUID:J
-Ljava/lang/System;-><init>()V
-Ljava/lang/System;->arraycopy([BI[BII)V
-Ljava/lang/System;->arraycopy([CI[CII)V
-Ljava/lang/System;->arraycopy([II[III)V
-Ljava/lang/Thread;-><init>(Ljava/lang/ThreadGroup;Ljava/lang/String;IZ)V
-Ljava/lang/Thread;->contextClassLoader:Ljava/lang/ClassLoader;
-Ljava/lang/Thread;->daemon:Z
-Ljava/lang/Thread;->dispatchUncaughtException(Ljava/lang/Throwable;)V
-Ljava/lang/Thread;->group:Ljava/lang/ThreadGroup;
-Ljava/lang/Thread;->inheritableThreadLocals:Ljava/lang/ThreadLocal$ThreadLocalMap;
-Ljava/lang/Thread;->lock:Ljava/lang/Object;
-Ljava/lang/Thread;->name:Ljava/lang/String;
-Ljava/lang/Thread;->nativePeer:J
-Ljava/lang/Thread;->parkBlocker:Ljava/lang/Object;
-Ljava/lang/Thread;->priority:I
-Ljava/lang/Thread;->threadLocals:Ljava/lang/ThreadLocal$ThreadLocalMap;
-Ljava/lang/ThreadDeath;->serialVersionUID:J
-Ljava/lang/ThreadGroup;->add(Ljava/lang/Thread;)V
-Ljava/lang/ThreadGroup;->groups:[Ljava/lang/ThreadGroup;
-Ljava/lang/ThreadGroup;->mainThreadGroup:Ljava/lang/ThreadGroup;
-Ljava/lang/ThreadGroup;->name:Ljava/lang/String;
-Ljava/lang/ThreadGroup;->ngroups:I
-Ljava/lang/ThreadGroup;->parent:Ljava/lang/ThreadGroup;
-Ljava/lang/ThreadGroup;->systemThreadGroup:Ljava/lang/ThreadGroup;
-Ljava/lang/ThreadGroup;->threadTerminated(Ljava/lang/Thread;)V
-Ljava/lang/Throwable;->backtrace:Ljava/lang/Object;
-Ljava/lang/Throwable;->cause:Ljava/lang/Throwable;
-Ljava/lang/Throwable;->detailMessage:Ljava/lang/String;
-Ljava/lang/Throwable;->nativeFillInStackTrace()Ljava/lang/Object;
-Ljava/lang/Throwable;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/lang/Throwable;->serialVersionUID:J
-Ljava/lang/Throwable;->stackTrace:[Ljava/lang/StackTraceElement;
-Ljava/lang/Throwable;->suppressedExceptions:Ljava/util/List;
-Ljava/lang/Throwable;->writeObject(Ljava/io/ObjectOutputStream;)V
-Ljava/lang/TypeNotPresentException;->serialVersionUID:J
-Ljava/lang/UnknownError;->serialVersionUID:J
-Ljava/lang/UnsatisfiedLinkError;->serialVersionUID:J
-Ljava/lang/UnsupportedClassVersionError;->serialVersionUID:J
-Ljava/lang/UnsupportedOperationException;->serialVersionUID:J
-Ljava/lang/VerifyError;->serialVersionUID:J
-Ljava/lang/VirtualMachineError;->serialVersionUID:J
-Ljava/lang/Void;-><init>()V
-Ljava/lang/annotation/AnnotationFormatError;->serialVersionUID:J
-Ljava/lang/annotation/AnnotationTypeMismatchException;->serialVersionUID:J
-Ljava/lang/annotation/IncompleteAnnotationException;->serialVersionUID:J
-Ljava/lang/invoke/LambdaConversionException;->serialVersionUID:J
-Ljava/lang/invoke/MethodHandles$Lookup;-><init>(Ljava/lang/Class;I)V
-Ljava/lang/invoke/MethodType;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/lang/invoke/MethodType;->readResolve()Ljava/lang/Object;
-Ljava/lang/invoke/MethodType;->serialPersistentFields:[Ljava/io/ObjectStreamField;
-Ljava/lang/invoke/MethodType;->serialVersionUID:J
-Ljava/lang/invoke/MethodType;->writeObject(Ljava/io/ObjectOutputStream;)V
-Ljava/lang/invoke/WrongMethodTypeException;->serialVersionUID:J
-Ljava/lang/ref/FinalizerReference;->add(Ljava/lang/Object;)V
-Ljava/lang/ref/FinalizerReference;->head:Ljava/lang/ref/FinalizerReference;
-Ljava/lang/ref/FinalizerReference;->next:Ljava/lang/ref/FinalizerReference;
-Ljava/lang/ref/FinalizerReference;->queue:Ljava/lang/ref/ReferenceQueue;
-Ljava/lang/ref/FinalizerReference;->remove(Ljava/lang/ref/FinalizerReference;)V
-Ljava/lang/ref/Reference;->getReferent()Ljava/lang/Object;
-Ljava/lang/ref/Reference;->referent:Ljava/lang/Object;
-Ljava/lang/ref/ReferenceQueue;->add(Ljava/lang/ref/Reference;)V
-Ljava/lang/reflect/Executable;->artMethod:J
-Ljava/lang/reflect/Field;->accessFlags:I
-Ljava/lang/reflect/GenericSignatureFormatError;->serialVersionUID:J
-Ljava/lang/reflect/InvocationTargetException;->serialVersionUID:J
-Ljava/lang/reflect/MalformedParameterizedTypeException;->serialVersionUID:J
-Ljava/lang/reflect/MalformedParametersException;->serialVersionUID:J
-Ljava/lang/reflect/Parameter;-><init>(Ljava/lang/String;ILjava/lang/reflect/Executable;I)V
-Ljava/lang/reflect/Proxy;->invoke(Ljava/lang/reflect/Proxy;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;
-Ljava/lang/reflect/Proxy;->serialVersionUID:J
-Ljava/lang/reflect/UndeclaredThrowableException;->serialVersionUID:J
-Ljava/math/BigDecimal;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/math/BigDecimal;->serialVersionUID:J
-Ljava/math/BigDecimal;->writeObject(Ljava/io/ObjectOutputStream;)V
-Ljava/math/BigInteger;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/math/BigInteger;->serialVersionUID:J
-Ljava/math/BigInteger;->writeObject(Ljava/io/ObjectOutputStream;)V
-Ljava/math/MathContext;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/math/MathContext;->serialVersionUID:J
-Ljava/net/Authenticator;->theAuthenticator:Ljava/net/Authenticator;
-Ljava/net/BindException;->serialVersionUID:J
-Ljava/net/ConnectException;->serialVersionUID:J
-Ljava/net/DatagramSocket;->impl:Ljava/net/DatagramSocketImpl;
-Ljava/net/HttpCookie;->assignors:Ljava/util/Map;
-Ljava/net/HttpCookie;->comment:Ljava/lang/String;
-Ljava/net/HttpCookie;->commentURL:Ljava/lang/String;
-Ljava/net/HttpCookie;->domain:Ljava/lang/String;
-Ljava/net/HttpCookie;->header:Ljava/lang/String;
-Ljava/net/HttpCookie;->httpOnly:Z
-Ljava/net/HttpCookie;->maxAge:J
-Ljava/net/HttpCookie;->name:Ljava/lang/String;
-Ljava/net/HttpCookie;->path:Ljava/lang/String;
-Ljava/net/HttpCookie;->portlist:Ljava/lang/String;
-Ljava/net/HttpCookie;->secure:Z
-Ljava/net/HttpCookie;->toDiscard:Z
-Ljava/net/HttpCookie;->tspecials:Ljava/lang/String;
-Ljava/net/HttpCookie;->value:Ljava/lang/String;
-Ljava/net/HttpCookie;->version:I
-Ljava/net/HttpCookie;->whenCreated:J
-Ljava/net/HttpRetryException;->serialVersionUID:J
-Ljava/net/Inet4Address;-><init>()V
-Ljava/net/Inet4Address;->ALL:Ljava/net/InetAddress;
-Ljava/net/Inet4Address;->ANY:Ljava/net/InetAddress;
-Ljava/net/Inet4Address;->serialVersionUID:J
-Ljava/net/Inet4Address;->writeReplace()Ljava/lang/Object;
-Ljava/net/Inet6Address$Inet6AddressHolder;->ipaddress:[B
-Ljava/net/Inet6Address$Inet6AddressHolder;->scope_id:I
-Ljava/net/Inet6Address$Inet6AddressHolder;->scope_id_set:Z
-Ljava/net/Inet6Address$Inet6AddressHolder;->scope_ifname:Ljava/net/NetworkInterface;
-Ljava/net/Inet6Address;-><init>()V
-Ljava/net/Inet6Address;->ANY:Ljava/net/InetAddress;
-Ljava/net/Inet6Address;->holder6:Ljava/net/Inet6Address$Inet6AddressHolder;
-Ljava/net/Inet6Address;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/net/Inet6Address;->serialPersistentFields:[Ljava/io/ObjectStreamField;
-Ljava/net/Inet6Address;->serialVersionUID:J
-Ljava/net/Inet6Address;->writeObject(Ljava/io/ObjectOutputStream;)V
-Ljava/net/InetAddress$InetAddressHolder;->address:I
-Ljava/net/InetAddress$InetAddressHolder;->family:I
-Ljava/net/InetAddress$InetAddressHolder;->hostName:Ljava/lang/String;
-Ljava/net/InetAddress$InetAddressHolder;->originalHostName:Ljava/lang/String;
-Ljava/net/InetAddress;->clearDnsCache()V
-Ljava/net/InetAddress;->holder()Ljava/net/InetAddress$InetAddressHolder;
-Ljava/net/InetAddress;->holder:Ljava/net/InetAddress$InetAddressHolder;
-Ljava/net/InetAddress;->isNumeric(Ljava/lang/String;)Z
-Ljava/net/InetAddress;->parseNumericAddress(Ljava/lang/String;)Ljava/net/InetAddress;
-Ljava/net/InetAddress;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/net/InetAddress;->readResolve()Ljava/lang/Object;
-Ljava/net/InetAddress;->serialPersistentFields:[Ljava/io/ObjectStreamField;
-Ljava/net/InetAddress;->serialVersionUID:J
-Ljava/net/InetAddress;->writeObject(Ljava/io/ObjectOutputStream;)V
-Ljava/net/InetSocketAddress;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/net/InetSocketAddress;->readObjectNoData()V
-Ljava/net/InetSocketAddress;->serialPersistentFields:[Ljava/io/ObjectStreamField;
-Ljava/net/InetSocketAddress;->serialVersionUID:J
-Ljava/net/InetSocketAddress;->writeObject(Ljava/io/ObjectOutputStream;)V
-Ljava/net/MalformedURLException;->serialVersionUID:J
-Ljava/net/NoRouteToHostException;->serialVersionUID:J
-Ljava/net/PortUnreachableException;->serialVersionUID:J
-Ljava/net/ProtocolException;->serialVersionUID:J
-Ljava/net/Socket;->getFileDescriptor$()Ljava/io/FileDescriptor;
-Ljava/net/Socket;->impl:Ljava/net/SocketImpl;
-Ljava/net/SocketAddress;->serialVersionUID:J
-Ljava/net/SocketException;->serialVersionUID:J
-Ljava/net/SocketImpl;->serverSocket:Ljava/net/ServerSocket;
-Ljava/net/SocketImpl;->socket:Ljava/net/Socket;
-Ljava/net/SocketTimeoutException;->serialVersionUID:J
-Ljava/net/URI;->fragment:Ljava/lang/String;
-Ljava/net/URI;->host:Ljava/lang/String;
-Ljava/net/URI;->port:I
-Ljava/net/URI;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/net/URI;->serialVersionUID:J
-Ljava/net/URI;->string:Ljava/lang/String;
-Ljava/net/URI;->writeObject(Ljava/io/ObjectOutputStream;)V
-Ljava/net/URISyntaxException;->serialVersionUID:J
-Ljava/net/URL;->handler:Ljava/net/URLStreamHandler;
-Ljava/net/URL;->handlers:Ljava/util/Hashtable;
-Ljava/net/URL;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/net/URL;->readResolve()Ljava/lang/Object;
-Ljava/net/URL;->serialPersistentFields:[Ljava/io/ObjectStreamField;
-Ljava/net/URL;->serialVersionUID:J
-Ljava/net/URL;->writeObject(Ljava/io/ObjectOutputStream;)V
-Ljava/net/UnknownHostException;->serialVersionUID:J
-Ljava/net/UnknownServiceException;->serialVersionUID:J
-Ljava/nio/Buffer;->_elementSizeShift:I
-Ljava/nio/Buffer;->address:J
-Ljava/nio/Buffer;->capacity:I
-Ljava/nio/Buffer;->limit:I
-Ljava/nio/Buffer;->position:I
-Ljava/nio/BufferOverflowException;->serialVersionUID:J
-Ljava/nio/BufferUnderflowException;->serialVersionUID:J
-Ljava/nio/ByteBuffer;->hb:[B
-Ljava/nio/ByteBuffer;->isReadOnly:Z
-Ljava/nio/ByteBuffer;->offset:I
-Ljava/nio/DirectByteBuffer;-><init>(JI)V
-Ljava/nio/InvalidMarkException;->serialVersionUID:J
-Ljava/nio/NIOAccess;->getBaseArray(Ljava/nio/Buffer;)Ljava/lang/Object;
-Ljava/nio/NIOAccess;->getBaseArrayOffset(Ljava/nio/Buffer;)I
-Ljava/nio/NIOAccess;->getBasePointer(Ljava/nio/Buffer;)J
-Ljava/nio/ReadOnlyBufferException;->serialVersionUID:J
-Ljava/nio/channels/AcceptPendingException;->serialVersionUID:J
-Ljava/nio/channels/AlreadyBoundException;->serialVersionUID:J
-Ljava/nio/channels/AlreadyConnectedException;->serialVersionUID:J
-Ljava/nio/channels/AsynchronousCloseException;->serialVersionUID:J
-Ljava/nio/channels/CancelledKeyException;->serialVersionUID:J
-Ljava/nio/channels/ClosedByInterruptException;->serialVersionUID:J
-Ljava/nio/channels/ClosedChannelException;->serialVersionUID:J
-Ljava/nio/channels/ClosedSelectorException;->serialVersionUID:J
-Ljava/nio/channels/ConnectionPendingException;->serialVersionUID:J
-Ljava/nio/channels/FileLockInterruptionException;->serialVersionUID:J
-Ljava/nio/channels/IllegalBlockingModeException;->serialVersionUID:J
-Ljava/nio/channels/IllegalChannelGroupException;->serialVersionUID:J
-Ljava/nio/channels/IllegalSelectorException;->serialVersionUID:J
-Ljava/nio/channels/InterruptedByTimeoutException;->serialVersionUID:J
-Ljava/nio/channels/NoConnectionPendingException;->serialVersionUID:J
-Ljava/nio/channels/NonReadableChannelException;->serialVersionUID:J
-Ljava/nio/channels/NonWritableChannelException;->serialVersionUID:J
-Ljava/nio/channels/NotYetBoundException;->serialVersionUID:J
-Ljava/nio/channels/NotYetConnectedException;->serialVersionUID:J
-Ljava/nio/channels/OverlappingFileLockException;->serialVersionUID:J
-Ljava/nio/channels/ReadPendingException;->serialVersionUID:J
-Ljava/nio/channels/ShutdownChannelGroupException;->serialVersionUID:J
-Ljava/nio/channels/UnresolvedAddressException;->serialVersionUID:J
-Ljava/nio/channels/UnsupportedAddressTypeException;->serialVersionUID:J
-Ljava/nio/channels/WritePendingException;->serialVersionUID:J
-Ljava/nio/charset/CharacterCodingException;->serialVersionUID:J
-Ljava/nio/charset/CharsetEncoder;->canEncode(Ljava/nio/CharBuffer;)Z
-Ljava/nio/charset/CoderMalfunctionError;->serialVersionUID:J
-Ljava/nio/charset/IllegalCharsetNameException;->serialVersionUID:J
-Ljava/nio/charset/MalformedInputException;->serialVersionUID:J
-Ljava/nio/charset/UnmappableCharacterException;->serialVersionUID:J
-Ljava/nio/charset/UnsupportedCharsetException;->serialVersionUID:J
-Ljava/nio/file/AccessDeniedException;->serialVersionUID:J
-Ljava/nio/file/AtomicMoveNotSupportedException;->serialVersionUID:J
-Ljava/nio/file/ClosedDirectoryStreamException;->serialVersionUID:J
-Ljava/nio/file/ClosedFileSystemException;->serialVersionUID:J
-Ljava/nio/file/ClosedWatchServiceException;->serialVersionUID:J
-Ljava/nio/file/DirectoryIteratorException;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/nio/file/DirectoryIteratorException;->serialVersionUID:J
-Ljava/nio/file/DirectoryNotEmptyException;->serialVersionUID:J
-Ljava/nio/file/FileAlreadyExistsException;->serialVersionUID:J
-Ljava/nio/file/FileSystemAlreadyExistsException;->serialVersionUID:J
-Ljava/nio/file/FileSystemException;->serialVersionUID:J
-Ljava/nio/file/FileSystemLoopException;->serialVersionUID:J
-Ljava/nio/file/FileSystemNotFoundException;->serialVersionUID:J
-Ljava/nio/file/InvalidPathException;->serialVersionUID:J
-Ljava/nio/file/LinkPermission;->serialVersionUID:J
-Ljava/nio/file/NoSuchFileException;->serialVersionUID:J
-Ljava/nio/file/NotDirectoryException;->serialVersionUID:J
-Ljava/nio/file/NotLinkException;->serialVersionUID:J
-Ljava/nio/file/ProviderMismatchException;->serialVersionUID:J
-Ljava/nio/file/ProviderNotFoundException;->serialVersionUID:J
-Ljava/nio/file/ReadOnlyFileSystemException;->serialVersionUID:J
-Ljava/nio/file/attribute/UserPrincipalNotFoundException;->serialVersionUID:J
-Ljava/security/AccessControlException;->serialVersionUID:J
-Ljava/security/CodeSigner;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/security/CodeSigner;->serialVersionUID:J
-Ljava/security/DigestException;->serialVersionUID:J
-Ljava/security/GeneralSecurityException;->serialVersionUID:J
-Ljava/security/GuardedObject;->serialVersionUID:J
-Ljava/security/GuardedObject;->writeObject(Ljava/io/ObjectOutputStream;)V
-Ljava/security/Identity;->serialVersionUID:J
-Ljava/security/IdentityScope;->serialVersionUID:J
-Ljava/security/InvalidAlgorithmParameterException;->serialVersionUID:J
-Ljava/security/InvalidKeyException;->serialVersionUID:J
-Ljava/security/InvalidParameterException;->serialVersionUID:J
-Ljava/security/KeyException;->serialVersionUID:J
-Ljava/security/KeyManagementException;->serialVersionUID:J
-Ljava/security/KeyPair;->serialVersionUID:J
-Ljava/security/KeyRep;->serialVersionUID:J
-Ljava/security/KeyStoreException;->serialVersionUID:J
-Ljava/security/NoSuchAlgorithmException;->serialVersionUID:J
-Ljava/security/NoSuchProviderException;->serialVersionUID:J
-Ljava/security/PrivilegedActionException;->serialVersionUID:J
-Ljava/security/Provider;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/security/Provider;->serialVersionUID:J
-Ljava/security/ProviderException;->serialVersionUID:J
-Ljava/security/SecureRandom;->serialVersionUID:J
-Ljava/security/SecureRandomSpi;->serialVersionUID:J
-Ljava/security/SignatureException;->serialVersionUID:J
-Ljava/security/SignedObject;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/security/SignedObject;->serialVersionUID:J
-Ljava/security/Signer;->serialVersionUID:J
-Ljava/security/Timestamp;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/security/Timestamp;->serialVersionUID:J
-Ljava/security/UnrecoverableEntryException;->serialVersionUID:J
-Ljava/security/UnrecoverableKeyException;->serialVersionUID:J
-Ljava/security/acl/AclNotFoundException;->serialVersionUID:J
-Ljava/security/acl/LastOwnerException;->serialVersionUID:J
-Ljava/security/acl/NotOwnerException;->serialVersionUID:J
-Ljava/security/cert/CRLException;->serialVersionUID:J
-Ljava/security/cert/CertPath$CertPathRep;->serialVersionUID:J
-Ljava/security/cert/CertPath;->serialVersionUID:J
-Ljava/security/cert/CertPathBuilderException;->serialVersionUID:J
-Ljava/security/cert/CertPathValidatorException;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/security/cert/CertPathValidatorException;->serialVersionUID:J
-Ljava/security/cert/CertStoreException;->serialVersionUID:J
-Ljava/security/cert/Certificate$CertificateRep;->serialVersionUID:J
-Ljava/security/cert/Certificate;->serialVersionUID:J
-Ljava/security/cert/CertificateEncodingException;->serialVersionUID:J
-Ljava/security/cert/CertificateException;->serialVersionUID:J
-Ljava/security/cert/CertificateExpiredException;->serialVersionUID:J
-Ljava/security/cert/CertificateNotYetValidException;->serialVersionUID:J
-Ljava/security/cert/CertificateParsingException;->serialVersionUID:J
-Ljava/security/cert/CertificateRevokedException;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/security/cert/CertificateRevokedException;->serialVersionUID:J
-Ljava/security/cert/CertificateRevokedException;->writeObject(Ljava/io/ObjectOutputStream;)V
-Ljava/security/cert/X509Certificate;->serialVersionUID:J
-Ljava/security/spec/ECParameterSpec;->getCurveName()Ljava/lang/String;
-Ljava/security/spec/ECParameterSpec;->setCurveName(Ljava/lang/String;)V
-Ljava/security/spec/InvalidKeySpecException;->serialVersionUID:J
-Ljava/security/spec/InvalidParameterSpecException;->serialVersionUID:J
-Ljava/sql/BatchUpdateException;->serialVersionUID:J
-Ljava/sql/DataTruncation;->serialVersionUID:J
-Ljava/sql/Date;->serialVersionUID:J
-Ljava/sql/SQLClientInfoException;->serialVersionUID:J
-Ljava/sql/SQLDataException;->serialVersionUID:J
-Ljava/sql/SQLException;->serialVersionUID:J
-Ljava/sql/SQLFeatureNotSupportedException;->serialVersionUID:J
-Ljava/sql/SQLIntegrityConstraintViolationException;->serialVersionUID:J
-Ljava/sql/SQLInvalidAuthorizationSpecException;->serialVersionUID:J
-Ljava/sql/SQLNonTransientConnectionException;->serialVersionUID:J
-Ljava/sql/SQLNonTransientException;->serialVersionUID:J
-Ljava/sql/SQLRecoverableException;->serialVersionUID:J
-Ljava/sql/SQLSyntaxErrorException;->serialVersionUID:J
-Ljava/sql/SQLTimeoutException;->serialVersionUID:J
-Ljava/sql/SQLTransactionRollbackException;->serialVersionUID:J
-Ljava/sql/SQLTransientConnectionException;->serialVersionUID:J
-Ljava/sql/SQLTransientException;->serialVersionUID:J
-Ljava/sql/SQLWarning;->serialVersionUID:J
-Ljava/sql/Time;->serialVersionUID:J
-Ljava/sql/Timestamp;->serialVersionUID:J
-Ljava/text/AttributedCharacterIterator$Attribute;->serialVersionUID:J
-Ljava/text/ChoiceFormat;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/text/ChoiceFormat;->serialVersionUID:J
-Ljava/text/DateFormat$Field;->serialVersionUID:J
-Ljava/text/DateFormat;->is24Hour:Ljava/lang/Boolean;
-Ljava/text/DateFormat;->serialVersionUID:J
-Ljava/text/DateFormatSymbols;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/text/DateFormatSymbols;->serialVersionUID:J
-Ljava/text/DateFormatSymbols;->writeObject(Ljava/io/ObjectOutputStream;)V
-Ljava/text/DecimalFormat;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/text/DecimalFormat;->serialPersistentFields:[Ljava/io/ObjectStreamField;
-Ljava/text/DecimalFormat;->serialVersionUID:J
-Ljava/text/DecimalFormat;->writeObject(Ljava/io/ObjectOutputStream;)V
-Ljava/text/DecimalFormatSymbols;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/text/DecimalFormatSymbols;->serialPersistentFields:[Ljava/io/ObjectStreamField;
-Ljava/text/DecimalFormatSymbols;->serialVersionUID:J
-Ljava/text/DecimalFormatSymbols;->writeObject(Ljava/io/ObjectOutputStream;)V
-Ljava/text/Format$Field;->serialVersionUID:J
-Ljava/text/Format;->serialVersionUID:J
-Ljava/text/MessageFormat$Field;->serialVersionUID:J
-Ljava/text/MessageFormat;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/text/MessageFormat;->serialVersionUID:J
-Ljava/text/NumberFormat$Field;->serialVersionUID:J
-Ljava/text/NumberFormat;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/text/NumberFormat;->serialVersionUID:J
-Ljava/text/NumberFormat;->writeObject(Ljava/io/ObjectOutputStream;)V
-Ljava/text/ParseException;->serialVersionUID:J
-Ljava/text/SimpleDateFormat;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/text/SimpleDateFormat;->serialVersionUID:J
-Ljava/time/Clock$FixedClock;->serialVersionUID:J
-Ljava/time/Clock$OffsetClock;->serialVersionUID:J
-Ljava/time/Clock$SystemClock;->serialVersionUID:J
-Ljava/time/Clock$TickClock;->serialVersionUID:J
-Ljava/time/DateTimeException;->serialVersionUID:J
-Ljava/time/Duration;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/time/Duration;->serialVersionUID:J
-Ljava/time/Duration;->toSeconds()Ljava/math/BigDecimal;
-Ljava/time/Duration;->writeReplace()Ljava/lang/Object;
-Ljava/time/Instant;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/time/Instant;->serialVersionUID:J
-Ljava/time/Instant;->writeReplace()Ljava/lang/Object;
-Ljava/time/LocalDate;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/time/LocalDate;->serialVersionUID:J
-Ljava/time/LocalDate;->writeReplace()Ljava/lang/Object;
-Ljava/time/LocalDateTime;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/time/LocalDateTime;->serialVersionUID:J
-Ljava/time/LocalDateTime;->writeReplace()Ljava/lang/Object;
-Ljava/time/LocalTime;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/time/LocalTime;->serialVersionUID:J
-Ljava/time/LocalTime;->writeReplace()Ljava/lang/Object;
-Ljava/time/MonthDay;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/time/MonthDay;->serialVersionUID:J
-Ljava/time/MonthDay;->writeReplace()Ljava/lang/Object;
-Ljava/time/OffsetDateTime;-><init>(Ljava/time/LocalDateTime;Ljava/time/ZoneOffset;)V
-Ljava/time/OffsetDateTime;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/time/OffsetDateTime;->serialVersionUID:J
-Ljava/time/OffsetDateTime;->writeReplace()Ljava/lang/Object;
-Ljava/time/OffsetTime;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/time/OffsetTime;->serialVersionUID:J
-Ljava/time/OffsetTime;->writeReplace()Ljava/lang/Object;
-Ljava/time/Period;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/time/Period;->serialVersionUID:J
-Ljava/time/Period;->writeReplace()Ljava/lang/Object;
-Ljava/time/Year;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/time/Year;->serialVersionUID:J
-Ljava/time/Year;->writeReplace()Ljava/lang/Object;
-Ljava/time/YearMonth;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/time/YearMonth;->serialVersionUID:J
-Ljava/time/YearMonth;->writeReplace()Ljava/lang/Object;
-Ljava/time/ZoneId;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/time/ZoneId;->serialVersionUID:J
-Ljava/time/ZoneId;->writeReplace()Ljava/lang/Object;
-Ljava/time/ZoneOffset;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/time/ZoneOffset;->serialVersionUID:J
-Ljava/time/ZoneOffset;->writeReplace()Ljava/lang/Object;
-Ljava/time/ZonedDateTime;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/time/ZonedDateTime;->serialVersionUID:J
-Ljava/time/ZonedDateTime;->writeReplace()Ljava/lang/Object;
-Ljava/time/chrono/AbstractChronology;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/time/chrono/AbstractChronology;->writeReplace()Ljava/lang/Object;
-Ljava/time/chrono/ChronoLocalDateImpl;->serialVersionUID:J
-Ljava/time/chrono/HijrahChronology;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/time/chrono/HijrahChronology;->serialVersionUID:J
-Ljava/time/chrono/HijrahChronology;->writeReplace()Ljava/lang/Object;
-Ljava/time/chrono/HijrahDate;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/time/chrono/HijrahDate;->serialVersionUID:J
-Ljava/time/chrono/HijrahDate;->writeReplace()Ljava/lang/Object;
-Ljava/time/chrono/IsoChronology;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/time/chrono/IsoChronology;->serialVersionUID:J
-Ljava/time/chrono/IsoChronology;->writeReplace()Ljava/lang/Object;
-Ljava/time/chrono/JapaneseChronology;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/time/chrono/JapaneseChronology;->serialVersionUID:J
-Ljava/time/chrono/JapaneseChronology;->writeReplace()Ljava/lang/Object;
-Ljava/time/chrono/JapaneseDate;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/time/chrono/JapaneseDate;->serialVersionUID:J
-Ljava/time/chrono/JapaneseDate;->writeReplace()Ljava/lang/Object;
-Ljava/time/chrono/JapaneseEra;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/time/chrono/JapaneseEra;->serialVersionUID:J
-Ljava/time/chrono/JapaneseEra;->writeReplace()Ljava/lang/Object;
-Ljava/time/chrono/MinguoChronology;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/time/chrono/MinguoChronology;->serialVersionUID:J
-Ljava/time/chrono/MinguoChronology;->writeReplace()Ljava/lang/Object;
-Ljava/time/chrono/MinguoDate;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/time/chrono/MinguoDate;->serialVersionUID:J
-Ljava/time/chrono/MinguoDate;->writeReplace()Ljava/lang/Object;
-Ljava/time/chrono/ThaiBuddhistChronology;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/time/chrono/ThaiBuddhistChronology;->serialVersionUID:J
-Ljava/time/chrono/ThaiBuddhistChronology;->writeReplace()Ljava/lang/Object;
-Ljava/time/chrono/ThaiBuddhistDate;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/time/chrono/ThaiBuddhistDate;->serialVersionUID:J
-Ljava/time/chrono/ThaiBuddhistDate;->writeReplace()Ljava/lang/Object;
-Ljava/time/format/DateTimeParseException;->serialVersionUID:J
-Ljava/time/temporal/JulianFields$Field;->serialVersionUID:J
-Ljava/time/temporal/UnsupportedTemporalTypeException;->serialVersionUID:J
-Ljava/time/temporal/ValueRange;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/time/temporal/ValueRange;->serialVersionUID:J
-Ljava/time/temporal/WeekFields;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/time/temporal/WeekFields;->readResolve()Ljava/lang/Object;
-Ljava/time/temporal/WeekFields;->serialVersionUID:J
-Ljava/time/zone/ZoneOffsetTransition;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/time/zone/ZoneOffsetTransition;->serialVersionUID:J
-Ljava/time/zone/ZoneOffsetTransition;->writeReplace()Ljava/lang/Object;
-Ljava/time/zone/ZoneOffsetTransitionRule;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/time/zone/ZoneOffsetTransitionRule;->serialVersionUID:J
-Ljava/time/zone/ZoneOffsetTransitionRule;->writeReplace()Ljava/lang/Object;
-Ljava/time/zone/ZoneRules;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/time/zone/ZoneRules;->serialVersionUID:J
-Ljava/time/zone/ZoneRules;->writeReplace()Ljava/lang/Object;
-Ljava/time/zone/ZoneRulesException;->serialVersionUID:J
-Ljava/util/AbstractMap$SimpleEntry;->serialVersionUID:J
-Ljava/util/AbstractMap$SimpleImmutableEntry;->serialVersionUID:J
-Ljava/util/ArrayDeque;->elements:[Ljava/lang/Object;
-Ljava/util/ArrayDeque;->head:I
-Ljava/util/ArrayDeque;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/util/ArrayDeque;->serialVersionUID:J
-Ljava/util/ArrayDeque;->tail:I
-Ljava/util/ArrayDeque;->writeObject(Ljava/io/ObjectOutputStream;)V
-Ljava/util/ArrayList$SubList;->parent:Ljava/util/AbstractList;
-Ljava/util/ArrayList$SubList;->parentOffset:I
-Ljava/util/ArrayList$SubList;->size:I
-Ljava/util/ArrayList;->elementData:[Ljava/lang/Object;
-Ljava/util/ArrayList;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/util/ArrayList;->serialVersionUID:J
-Ljava/util/ArrayList;->size:I
-Ljava/util/ArrayList;->writeObject(Ljava/io/ObjectOutputStream;)V
-Ljava/util/Arrays$ArrayList;->a:[Ljava/lang/Object;
-Ljava/util/Arrays$ArrayList;->serialVersionUID:J
-Ljava/util/BitSet;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/util/BitSet;->serialPersistentFields:[Ljava/io/ObjectStreamField;
-Ljava/util/BitSet;->serialVersionUID:J
-Ljava/util/BitSet;->writeObject(Ljava/io/ObjectOutputStream;)V
-Ljava/util/Calendar;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/util/Calendar;->serialVersionUID:J
-Ljava/util/Calendar;->writeObject(Ljava/io/ObjectOutputStream;)V
-Ljava/util/Calendar;->zone:Ljava/util/TimeZone;
-Ljava/util/Collections$AsLIFOQueue;->serialVersionUID:J
-Ljava/util/Collections$CheckedCollection;->serialVersionUID:J
-Ljava/util/Collections$CheckedList;->serialVersionUID:J
-Ljava/util/Collections$CheckedMap;->serialVersionUID:J
-Ljava/util/Collections$CheckedNavigableMap;->serialVersionUID:J
-Ljava/util/Collections$CheckedNavigableSet;->serialVersionUID:J
-Ljava/util/Collections$CheckedQueue;->serialVersionUID:J
-Ljava/util/Collections$CheckedRandomAccessList;->serialVersionUID:J
-Ljava/util/Collections$CheckedSet;->serialVersionUID:J
-Ljava/util/Collections$CheckedSortedMap;->serialVersionUID:J
-Ljava/util/Collections$CheckedSortedSet;->serialVersionUID:J
-Ljava/util/Collections$CopiesList;->serialVersionUID:J
-Ljava/util/Collections$EmptyList;-><init>()V
-Ljava/util/Collections$EmptyList;->readResolve()Ljava/lang/Object;
-Ljava/util/Collections$EmptyList;->serialVersionUID:J
-Ljava/util/Collections$EmptyMap;->readResolve()Ljava/lang/Object;
-Ljava/util/Collections$EmptyMap;->serialVersionUID:J
-Ljava/util/Collections$EmptySet;->readResolve()Ljava/lang/Object;
-Ljava/util/Collections$EmptySet;->serialVersionUID:J
-Ljava/util/Collections$ReverseComparator2;->serialVersionUID:J
-Ljava/util/Collections$ReverseComparator;->readResolve()Ljava/lang/Object;
-Ljava/util/Collections$ReverseComparator;->serialVersionUID:J
-Ljava/util/Collections$SetFromMap;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/util/Collections$SetFromMap;->serialVersionUID:J
-Ljava/util/Collections$SingletonList;->serialVersionUID:J
-Ljava/util/Collections$SingletonMap;->serialVersionUID:J
-Ljava/util/Collections$SingletonSet;->serialVersionUID:J
-Ljava/util/Collections$SynchronizedCollection;->c:Ljava/util/Collection;
-Ljava/util/Collections$SynchronizedCollection;->serialVersionUID:J
-Ljava/util/Collections$SynchronizedCollection;->writeObject(Ljava/io/ObjectOutputStream;)V
-Ljava/util/Collections$SynchronizedList;->readResolve()Ljava/lang/Object;
-Ljava/util/Collections$SynchronizedList;->serialVersionUID:J
-Ljava/util/Collections$SynchronizedMap;->m:Ljava/util/Map;
-Ljava/util/Collections$SynchronizedMap;->serialVersionUID:J
-Ljava/util/Collections$SynchronizedMap;->writeObject(Ljava/io/ObjectOutputStream;)V
-Ljava/util/Collections$SynchronizedNavigableMap;->serialVersionUID:J
-Ljava/util/Collections$SynchronizedNavigableSet;->serialVersionUID:J
-Ljava/util/Collections$SynchronizedRandomAccessList;->serialVersionUID:J
-Ljava/util/Collections$SynchronizedRandomAccessList;->writeReplace()Ljava/lang/Object;
-Ljava/util/Collections$SynchronizedSet;->serialVersionUID:J
-Ljava/util/Collections$SynchronizedSortedMap;->serialVersionUID:J
-Ljava/util/Collections$SynchronizedSortedSet;->serialVersionUID:J
-Ljava/util/Collections$UnmodifiableCollection;->c:Ljava/util/Collection;
-Ljava/util/Collections$UnmodifiableCollection;->serialVersionUID:J
-Ljava/util/Collections$UnmodifiableList;->readResolve()Ljava/lang/Object;
-Ljava/util/Collections$UnmodifiableList;->serialVersionUID:J
-Ljava/util/Collections$UnmodifiableMap$UnmodifiableEntrySet;->serialVersionUID:J
-Ljava/util/Collections$UnmodifiableMap;->m:Ljava/util/Map;
-Ljava/util/Collections$UnmodifiableMap;->serialVersionUID:J
-Ljava/util/Collections$UnmodifiableNavigableMap$EmptyNavigableMap;->readResolve()Ljava/lang/Object;
-Ljava/util/Collections$UnmodifiableNavigableMap$EmptyNavigableMap;->serialVersionUID:J
-Ljava/util/Collections$UnmodifiableNavigableMap;->serialVersionUID:J
-Ljava/util/Collections$UnmodifiableNavigableSet$EmptyNavigableSet;->readResolve()Ljava/lang/Object;
-Ljava/util/Collections$UnmodifiableNavigableSet$EmptyNavigableSet;->serialVersionUID:J
-Ljava/util/Collections$UnmodifiableNavigableSet;->serialVersionUID:J
-Ljava/util/Collections$UnmodifiableRandomAccessList;->serialVersionUID:J
-Ljava/util/Collections$UnmodifiableRandomAccessList;->writeReplace()Ljava/lang/Object;
-Ljava/util/Collections$UnmodifiableSet;->serialVersionUID:J
-Ljava/util/Collections$UnmodifiableSortedMap;->serialVersionUID:J
-Ljava/util/Collections$UnmodifiableSortedSet;->serialVersionUID:J
-Ljava/util/ConcurrentModificationException;->serialVersionUID:J
-Ljava/util/Currency;->readResolve()Ljava/lang/Object;
-Ljava/util/Currency;->serialVersionUID:J
-Ljava/util/Date;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/util/Date;->serialVersionUID:J
-Ljava/util/Date;->writeObject(Ljava/io/ObjectOutputStream;)V
-Ljava/util/DuplicateFormatFlagsException;->serialVersionUID:J
-Ljava/util/EmptyStackException;->serialVersionUID:J
-Ljava/util/EnumMap;->keyType:Ljava/lang/Class;
-Ljava/util/EnumMap;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/util/EnumMap;->serialVersionUID:J
-Ljava/util/EnumMap;->writeObject(Ljava/io/ObjectOutputStream;)V
-Ljava/util/EnumSet$SerializationProxy;->readResolve()Ljava/lang/Object;
-Ljava/util/EnumSet$SerializationProxy;->serialVersionUID:J
-Ljava/util/EnumSet;->elementType:Ljava/lang/Class;
-Ljava/util/EnumSet;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/util/EnumSet;->writeReplace()Ljava/lang/Object;
-Ljava/util/EventObject;->serialVersionUID:J
-Ljava/util/FormatFlagsConversionMismatchException;->serialVersionUID:J
-Ljava/util/FormatterClosedException;->serialVersionUID:J
-Ljava/util/GregorianCalendar;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/util/GregorianCalendar;->serialVersionUID:J
-Ljava/util/HashMap$HashIterator;->hasNext()Z
-Ljava/util/HashMap;->modCount:I
-Ljava/util/HashMap;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/util/HashMap;->serialVersionUID:J
-Ljava/util/HashMap;->table:[Ljava/util/HashMap$Node;
-Ljava/util/HashMap;->writeObject(Ljava/io/ObjectOutputStream;)V
-Ljava/util/HashSet;->map:Ljava/util/HashMap;
-Ljava/util/HashSet;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/util/HashSet;->serialVersionUID:J
-Ljava/util/HashSet;->writeObject(Ljava/io/ObjectOutputStream;)V
-Ljava/util/Hashtable;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/util/Hashtable;->serialVersionUID:J
-Ljava/util/Hashtable;->writeObject(Ljava/io/ObjectOutputStream;)V
-Ljava/util/IdentityHashMap;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/util/IdentityHashMap;->serialVersionUID:J
-Ljava/util/IdentityHashMap;->writeObject(Ljava/io/ObjectOutputStream;)V
-Ljava/util/IllegalFormatCodePointException;->serialVersionUID:J
-Ljava/util/IllegalFormatConversionException;->serialVersionUID:J
-Ljava/util/IllegalFormatException;->serialVersionUID:J
-Ljava/util/IllegalFormatFlagsException;->serialVersionUID:J
-Ljava/util/IllegalFormatPrecisionException;->serialVersionUID:J
-Ljava/util/IllegalFormatWidthException;->serialVersionUID:J
-Ljava/util/IllformedLocaleException;->serialVersionUID:J
-Ljava/util/InputMismatchException;->serialVersionUID:J
-Ljava/util/InvalidPropertiesFormatException;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/util/InvalidPropertiesFormatException;->serialVersionUID:J
-Ljava/util/InvalidPropertiesFormatException;->writeObject(Ljava/io/ObjectOutputStream;)V
-Ljava/util/LinkedHashMap$LinkedHashIterator;->hasNext()Z
-Ljava/util/LinkedHashMap;->eldest()Ljava/util/Map$Entry;
-Ljava/util/LinkedHashMap;->serialVersionUID:J
-Ljava/util/LinkedHashSet;->serialVersionUID:J
-Ljava/util/LinkedList;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/util/LinkedList;->serialVersionUID:J
-Ljava/util/LinkedList;->size:I
-Ljava/util/LinkedList;->writeObject(Ljava/io/ObjectOutputStream;)V
-Ljava/util/Locale;->createConstant(Ljava/lang/String;Ljava/lang/String;)Ljava/util/Locale;
-Ljava/util/Locale;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/util/Locale;->readResolve()Ljava/lang/Object;
-Ljava/util/Locale;->serialPersistentFields:[Ljava/io/ObjectStreamField;
-Ljava/util/Locale;->serialVersionUID:J
-Ljava/util/Locale;->writeObject(Ljava/io/ObjectOutputStream;)V
-Ljava/util/MissingFormatArgumentException;->serialVersionUID:J
-Ljava/util/MissingFormatWidthException;->serialVersionUID:J
-Ljava/util/MissingResourceException;->serialVersionUID:J
-Ljava/util/NoSuchElementException;->serialVersionUID:J
-Ljava/util/PriorityQueue;->modCount:I
-Ljava/util/PriorityQueue;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/util/PriorityQueue;->serialVersionUID:J
-Ljava/util/PriorityQueue;->size:I
-Ljava/util/PriorityQueue;->writeObject(Ljava/io/ObjectOutputStream;)V
-Ljava/util/Properties;->serialVersionUID:J
-Ljava/util/Random;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/util/Random;->seedUniquifier()J
-Ljava/util/Random;->serialPersistentFields:[Ljava/io/ObjectStreamField;
-Ljava/util/Random;->serialVersionUID:J
-Ljava/util/Random;->writeObject(Ljava/io/ObjectOutputStream;)V
-Ljava/util/ServiceConfigurationError;->serialVersionUID:J
-Ljava/util/SimpleTimeZone;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/util/SimpleTimeZone;->serialVersionUID:J
-Ljava/util/SimpleTimeZone;->writeObject(Ljava/io/ObjectOutputStream;)V
-Ljava/util/Stack;->serialVersionUID:J
-Ljava/util/TimeZone;->serialVersionUID:J
-Ljava/util/TooManyListenersException;->serialVersionUID:J
-Ljava/util/TreeMap$AscendingSubMap;->serialVersionUID:J
-Ljava/util/TreeMap$DescendingSubMap;->serialVersionUID:J
-Ljava/util/TreeMap$NavigableSubMap;->serialVersionUID:J
-Ljava/util/TreeMap$SubMap;->readResolve()Ljava/lang/Object;
-Ljava/util/TreeMap$SubMap;->serialVersionUID:J
-Ljava/util/TreeMap;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/util/TreeMap;->serialVersionUID:J
-Ljava/util/TreeMap;->writeObject(Ljava/io/ObjectOutputStream;)V
-Ljava/util/TreeSet;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/util/TreeSet;->serialVersionUID:J
-Ljava/util/TreeSet;->writeObject(Ljava/io/ObjectOutputStream;)V
-Ljava/util/UUID;->leastSigBits:J
-Ljava/util/UUID;->mostSigBits:J
-Ljava/util/UUID;->serialVersionUID:J
-Ljava/util/UnknownFormatConversionException;->serialVersionUID:J
-Ljava/util/UnknownFormatFlagsException;->serialVersionUID:J
-Ljava/util/Vector;->elementData(I)Ljava/lang/Object;
-Ljava/util/Vector;->serialVersionUID:J
-Ljava/util/Vector;->writeObject(Ljava/io/ObjectOutputStream;)V
-Ljava/util/concurrent/ArrayBlockingQueue;->serialVersionUID:J
-Ljava/util/concurrent/BrokenBarrierException;->serialVersionUID:J
-Ljava/util/concurrent/CancellationException;->serialVersionUID:J
-Ljava/util/concurrent/CompletionException;->serialVersionUID:J
-Ljava/util/concurrent/ConcurrentHashMap$BaseIterator;->hasMoreElements()Z
-Ljava/util/concurrent/ConcurrentHashMap$CollectionView;->serialVersionUID:J
-Ljava/util/concurrent/ConcurrentHashMap$EntrySetView;->serialVersionUID:J
-Ljava/util/concurrent/ConcurrentHashMap$KeySetView;->serialVersionUID:J
-Ljava/util/concurrent/ConcurrentHashMap$Segment;->serialVersionUID:J
-Ljava/util/concurrent/ConcurrentHashMap$ValuesView;->serialVersionUID:J
-Ljava/util/concurrent/ConcurrentHashMap;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/util/concurrent/ConcurrentHashMap;->serialPersistentFields:[Ljava/io/ObjectStreamField;
-Ljava/util/concurrent/ConcurrentHashMap;->serialVersionUID:J
-Ljava/util/concurrent/ConcurrentHashMap;->writeObject(Ljava/io/ObjectOutputStream;)V
-Ljava/util/concurrent/ConcurrentLinkedDeque;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/util/concurrent/ConcurrentLinkedDeque;->serialVersionUID:J
-Ljava/util/concurrent/ConcurrentLinkedDeque;->writeObject(Ljava/io/ObjectOutputStream;)V
-Ljava/util/concurrent/ConcurrentLinkedQueue;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/util/concurrent/ConcurrentLinkedQueue;->serialVersionUID:J
-Ljava/util/concurrent/ConcurrentLinkedQueue;->writeObject(Ljava/io/ObjectOutputStream;)V
-Ljava/util/concurrent/ConcurrentSkipListMap$SubMap;->serialVersionUID:J
-Ljava/util/concurrent/ConcurrentSkipListMap;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/util/concurrent/ConcurrentSkipListMap;->serialVersionUID:J
-Ljava/util/concurrent/ConcurrentSkipListMap;->writeObject(Ljava/io/ObjectOutputStream;)V
-Ljava/util/concurrent/ConcurrentSkipListSet;->serialVersionUID:J
-Ljava/util/concurrent/CopyOnWriteArrayList;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/util/concurrent/CopyOnWriteArrayList;->serialVersionUID:J
-Ljava/util/concurrent/CopyOnWriteArrayList;->writeObject(Ljava/io/ObjectOutputStream;)V
-Ljava/util/concurrent/CopyOnWriteArraySet;->al:Ljava/util/concurrent/CopyOnWriteArrayList;
-Ljava/util/concurrent/CopyOnWriteArraySet;->serialVersionUID:J
-Ljava/util/concurrent/CountDownLatch$Sync;->serialVersionUID:J
-Ljava/util/concurrent/CountedCompleter;->serialVersionUID:J
-Ljava/util/concurrent/ExecutionException;->serialVersionUID:J
-Ljava/util/concurrent/Executors$RunnableAdapter;->task:Ljava/lang/Runnable;
-Ljava/util/concurrent/ForkJoinPool$AuxState;->serialVersionUID:J
-Ljava/util/concurrent/ForkJoinPool$EmptyTask;->serialVersionUID:J
-Ljava/util/concurrent/ForkJoinTask$AdaptedCallable;->serialVersionUID:J
-Ljava/util/concurrent/ForkJoinTask$AdaptedRunnable;->serialVersionUID:J
-Ljava/util/concurrent/ForkJoinTask$AdaptedRunnableAction;->serialVersionUID:J
-Ljava/util/concurrent/ForkJoinTask$RunnableExecuteAction;->serialVersionUID:J
-Ljava/util/concurrent/ForkJoinTask;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/util/concurrent/ForkJoinTask;->serialVersionUID:J
-Ljava/util/concurrent/ForkJoinTask;->writeObject(Ljava/io/ObjectOutputStream;)V
-Ljava/util/concurrent/FutureTask;->EXCEPTIONAL:I
-Ljava/util/concurrent/FutureTask;->callable:Ljava/util/concurrent/Callable;
-Ljava/util/concurrent/FutureTask;->outcome:Ljava/lang/Object;
-Ljava/util/concurrent/FutureTask;->state:I
-Ljava/util/concurrent/LinkedBlockingDeque;->first:Ljava/util/concurrent/LinkedBlockingDeque$Node;
-Ljava/util/concurrent/LinkedBlockingDeque;->lock:Ljava/util/concurrent/locks/ReentrantLock;
-Ljava/util/concurrent/LinkedBlockingDeque;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/util/concurrent/LinkedBlockingDeque;->serialVersionUID:J
-Ljava/util/concurrent/LinkedBlockingDeque;->writeObject(Ljava/io/ObjectOutputStream;)V
-Ljava/util/concurrent/LinkedBlockingQueue;->capacity:I
-Ljava/util/concurrent/LinkedBlockingQueue;->head:Ljava/util/concurrent/LinkedBlockingQueue$Node;
-Ljava/util/concurrent/LinkedBlockingQueue;->putLock:Ljava/util/concurrent/locks/ReentrantLock;
-Ljava/util/concurrent/LinkedBlockingQueue;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/util/concurrent/LinkedBlockingQueue;->serialVersionUID:J
-Ljava/util/concurrent/LinkedBlockingQueue;->takeLock:Ljava/util/concurrent/locks/ReentrantLock;
-Ljava/util/concurrent/LinkedBlockingQueue;->writeObject(Ljava/io/ObjectOutputStream;)V
-Ljava/util/concurrent/LinkedTransferQueue$Node;->serialVersionUID:J
-Ljava/util/concurrent/LinkedTransferQueue;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/util/concurrent/LinkedTransferQueue;->serialVersionUID:J
-Ljava/util/concurrent/LinkedTransferQueue;->writeObject(Ljava/io/ObjectOutputStream;)V
-Ljava/util/concurrent/PriorityBlockingQueue;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/util/concurrent/PriorityBlockingQueue;->serialVersionUID:J
-Ljava/util/concurrent/PriorityBlockingQueue;->writeObject(Ljava/io/ObjectOutputStream;)V
-Ljava/util/concurrent/RecursiveAction;->serialVersionUID:J
-Ljava/util/concurrent/RecursiveTask;->serialVersionUID:J
-Ljava/util/concurrent/RejectedExecutionException;->serialVersionUID:J
-Ljava/util/concurrent/Semaphore$FairSync;->serialVersionUID:J
-Ljava/util/concurrent/Semaphore$NonfairSync;->serialVersionUID:J
-Ljava/util/concurrent/Semaphore$Sync;->serialVersionUID:J
-Ljava/util/concurrent/Semaphore;->serialVersionUID:J
-Ljava/util/concurrent/SynchronousQueue$FifoWaitQueue;->serialVersionUID:J
-Ljava/util/concurrent/SynchronousQueue$LifoWaitQueue;->serialVersionUID:J
-Ljava/util/concurrent/SynchronousQueue;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/util/concurrent/SynchronousQueue;->serialVersionUID:J
-Ljava/util/concurrent/SynchronousQueue;->writeObject(Ljava/io/ObjectOutputStream;)V
-Ljava/util/concurrent/ThreadLocalRandom;->readResolve()Ljava/lang/Object;
-Ljava/util/concurrent/ThreadLocalRandom;->serialPersistentFields:[Ljava/io/ObjectStreamField;
-Ljava/util/concurrent/ThreadLocalRandom;->serialVersionUID:J
-Ljava/util/concurrent/ThreadLocalRandom;->writeObject(Ljava/io/ObjectOutputStream;)V
-Ljava/util/concurrent/ThreadPoolExecutor$Worker;->serialVersionUID:J
-Ljava/util/concurrent/ThreadPoolExecutor;->allowCoreThreadTimeOut:Z
-Ljava/util/concurrent/TimeoutException;->serialVersionUID:J
-Ljava/util/concurrent/atomic/AtomicBoolean;->serialVersionUID:J
-Ljava/util/concurrent/atomic/AtomicInteger;->serialVersionUID:J
-Ljava/util/concurrent/atomic/AtomicInteger;->value:I
-Ljava/util/concurrent/atomic/AtomicIntegerArray;->serialVersionUID:J
-Ljava/util/concurrent/atomic/AtomicLong;->serialVersionUID:J
-Ljava/util/concurrent/atomic/AtomicLongArray;->serialVersionUID:J
-Ljava/util/concurrent/atomic/AtomicReference;->serialVersionUID:J
-Ljava/util/concurrent/atomic/AtomicReferenceArray;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/util/concurrent/atomic/AtomicReferenceArray;->serialVersionUID:J
-Ljava/util/concurrent/atomic/DoubleAccumulator$SerializationProxy;->readResolve()Ljava/lang/Object;
-Ljava/util/concurrent/atomic/DoubleAccumulator$SerializationProxy;->serialVersionUID:J
-Ljava/util/concurrent/atomic/DoubleAccumulator;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/util/concurrent/atomic/DoubleAccumulator;->serialVersionUID:J
-Ljava/util/concurrent/atomic/DoubleAccumulator;->writeReplace()Ljava/lang/Object;
-Ljava/util/concurrent/atomic/DoubleAdder$SerializationProxy;->readResolve()Ljava/lang/Object;
-Ljava/util/concurrent/atomic/DoubleAdder$SerializationProxy;->serialVersionUID:J
-Ljava/util/concurrent/atomic/DoubleAdder;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/util/concurrent/atomic/DoubleAdder;->serialVersionUID:J
-Ljava/util/concurrent/atomic/DoubleAdder;->writeReplace()Ljava/lang/Object;
-Ljava/util/concurrent/atomic/LongAccumulator$SerializationProxy;->readResolve()Ljava/lang/Object;
-Ljava/util/concurrent/atomic/LongAccumulator$SerializationProxy;->serialVersionUID:J
-Ljava/util/concurrent/atomic/LongAccumulator;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/util/concurrent/atomic/LongAccumulator;->serialVersionUID:J
-Ljava/util/concurrent/atomic/LongAccumulator;->writeReplace()Ljava/lang/Object;
-Ljava/util/concurrent/atomic/LongAdder$SerializationProxy;->readResolve()Ljava/lang/Object;
-Ljava/util/concurrent/atomic/LongAdder$SerializationProxy;->serialVersionUID:J
-Ljava/util/concurrent/atomic/LongAdder;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/util/concurrent/atomic/LongAdder;->serialVersionUID:J
-Ljava/util/concurrent/atomic/LongAdder;->writeReplace()Ljava/lang/Object;
-Ljava/util/concurrent/locks/AbstractOwnableSynchronizer;->serialVersionUID:J
-Ljava/util/concurrent/locks/AbstractQueuedLongSynchronizer$ConditionObject;->serialVersionUID:J
-Ljava/util/concurrent/locks/AbstractQueuedLongSynchronizer;->serialVersionUID:J
-Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject;->serialVersionUID:J
-Ljava/util/concurrent/locks/AbstractQueuedSynchronizer;->serialVersionUID:J
-Ljava/util/concurrent/locks/ReentrantLock$FairSync;->serialVersionUID:J
-Ljava/util/concurrent/locks/ReentrantLock$NonfairSync;->serialVersionUID:J
-Ljava/util/concurrent/locks/ReentrantLock$Sync;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/util/concurrent/locks/ReentrantLock$Sync;->serialVersionUID:J
-Ljava/util/concurrent/locks/ReentrantLock;->serialVersionUID:J
-Ljava/util/concurrent/locks/ReentrantReadWriteLock$FairSync;->serialVersionUID:J
-Ljava/util/concurrent/locks/ReentrantReadWriteLock$NonfairSync;->serialVersionUID:J
-Ljava/util/concurrent/locks/ReentrantReadWriteLock$ReadLock;->serialVersionUID:J
-Ljava/util/concurrent/locks/ReentrantReadWriteLock$Sync;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/util/concurrent/locks/ReentrantReadWriteLock$Sync;->serialVersionUID:J
-Ljava/util/concurrent/locks/ReentrantReadWriteLock$WriteLock;->serialVersionUID:J
-Ljava/util/concurrent/locks/ReentrantReadWriteLock;->serialVersionUID:J
-Ljava/util/concurrent/locks/StampedLock;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/util/concurrent/locks/StampedLock;->serialVersionUID:J
-Ljava/util/jar/JarException;->serialVersionUID:J
-Ljava/util/jar/JarFile;->manifest:Ljava/util/jar/Manifest;
-Ljava/util/jar/JarVerifier$VerifierCodeSource;->serialVersionUID:J
-Ljava/util/logging/Level;->readResolve()Ljava/lang/Object;
-Ljava/util/logging/Level;->serialVersionUID:J
-Ljava/util/logging/LogRecord;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/util/logging/LogRecord;->serialVersionUID:J
-Ljava/util/logging/LogRecord;->writeObject(Ljava/io/ObjectOutputStream;)V
-Ljava/util/prefs/AbstractPreferences$NodeAddedEvent;->serialVersionUID:J
-Ljava/util/prefs/AbstractPreferences$NodeRemovedEvent;->serialVersionUID:J
-Ljava/util/prefs/BackingStoreException;->serialVersionUID:J
-Ljava/util/prefs/InvalidPreferencesFormatException;->serialVersionUID:J
-Ljava/util/prefs/NodeChangeEvent;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/util/prefs/NodeChangeEvent;->serialVersionUID:J
-Ljava/util/prefs/NodeChangeEvent;->writeObject(Ljava/io/ObjectOutputStream;)V
-Ljava/util/prefs/PreferenceChangeEvent;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/util/prefs/PreferenceChangeEvent;->serialVersionUID:J
-Ljava/util/prefs/PreferenceChangeEvent;->writeObject(Ljava/io/ObjectOutputStream;)V
-Ljava/util/regex/Matcher;->appendPos:I
-Ljava/util/regex/Pattern;->readObject(Ljava/io/ObjectInputStream;)V
-Ljava/util/regex/Pattern;->serialVersionUID:J
-Ljava/util/regex/PatternSyntaxException;->serialVersionUID:J
-Ljava/util/zip/DataFormatException;->serialVersionUID:J
-Ljava/util/zip/Deflater;->buf:[B
-Ljava/util/zip/Deflater;->finish:Z
-Ljava/util/zip/Deflater;->finished:Z
-Ljava/util/zip/Deflater;->len:I
-Ljava/util/zip/Deflater;->level:I
-Ljava/util/zip/Deflater;->off:I
-Ljava/util/zip/Deflater;->setParams:Z
-Ljava/util/zip/Deflater;->strategy:I
-Ljava/util/zip/Inflater;->buf:[B
-Ljava/util/zip/Inflater;->finished:Z
-Ljava/util/zip/Inflater;->len:I
-Ljava/util/zip/Inflater;->needDict:Z
-Ljava/util/zip/Inflater;->off:I
-Ljava/util/zip/ZipEntry;-><init>(Ljava/lang/String;Ljava/lang/String;JJJII[BJ)V
-Ljava/util/zip/ZipError;->serialVersionUID:J
-Ljava/util/zip/ZipException;->serialVersionUID:J
-Ljava/util/zip/ZipFile;->jzfile:J
-Ljavax/crypto/AEADBadTagException;->serialVersionUID:J
-Ljavax/crypto/BadPaddingException;->serialVersionUID:J
-Ljavax/crypto/ExemptionMechanismException;->serialVersionUID:J
-Ljavax/crypto/IllegalBlockSizeException;->serialVersionUID:J
-Ljavax/crypto/NoSuchPaddingException;->serialVersionUID:J
-Ljavax/crypto/SealedObject;->readObject(Ljava/io/ObjectInputStream;)V
-Ljavax/crypto/SealedObject;->serialVersionUID:J
-Ljavax/crypto/ShortBufferException;->serialVersionUID:J
-Ljavax/crypto/spec/SecretKeySpec;->serialVersionUID:J
-Ljavax/net/ssl/HandshakeCompletedEvent;->serialVersionUID:J
-Ljavax/net/ssl/SSLException;->serialVersionUID:J
-Ljavax/net/ssl/SSLHandshakeException;->serialVersionUID:J
-Ljavax/net/ssl/SSLKeyException;->serialVersionUID:J
-Ljavax/net/ssl/SSLPeerUnverifiedException;->serialVersionUID:J
-Ljavax/net/ssl/SSLProtocolException;->serialVersionUID:J
-Ljavax/net/ssl/SSLServerSocketFactory;->defaultServerSocketFactory:Ljavax/net/ssl/SSLServerSocketFactory;
-Ljavax/net/ssl/SSLSessionBindingEvent;->serialVersionUID:J
-Ljavax/net/ssl/SSLSocketFactory;->defaultSocketFactory:Ljavax/net/ssl/SSLSocketFactory;
-Ljavax/security/auth/DestroyFailedException;->serialVersionUID:J
-Ljavax/security/auth/Subject$SecureSet;->readObject(Ljava/io/ObjectInputStream;)V
-Ljavax/security/auth/Subject$SecureSet;->serialPersistentFields:[Ljava/io/ObjectStreamField;
-Ljavax/security/auth/Subject$SecureSet;->serialVersionUID:J
-Ljavax/security/auth/Subject$SecureSet;->writeObject(Ljava/io/ObjectOutputStream;)V
-Ljavax/security/auth/Subject;->readObject(Ljava/io/ObjectInputStream;)V
-Ljavax/security/auth/Subject;->serialVersionUID:J
-Ljavax/security/auth/Subject;->writeObject(Ljava/io/ObjectOutputStream;)V
-Ljavax/security/auth/callback/PasswordCallback;->serialVersionUID:J
-Ljavax/security/auth/callback/UnsupportedCallbackException;->serialVersionUID:J
-Ljavax/security/auth/login/LoginException;->serialVersionUID:J
-Ljavax/security/auth/x500/X500Principal;->readObject(Ljava/io/ObjectInputStream;)V
-Ljavax/security/auth/x500/X500Principal;->serialVersionUID:J
-Ljavax/security/auth/x500/X500Principal;->writeObject(Ljava/io/ObjectOutputStream;)V
-Ljavax/security/cert/CertificateEncodingException;->serialVersionUID:J
-Ljavax/security/cert/CertificateException;->serialVersionUID:J
-Ljavax/security/cert/CertificateExpiredException;->serialVersionUID:J
-Ljavax/security/cert/CertificateNotYetValidException;->serialVersionUID:J
-Ljavax/security/cert/CertificateParsingException;->serialVersionUID:J
-Ljavax/sql/ConnectionEvent;->serialVersionUID:J
-Ljavax/sql/RowSetEvent;->serialVersionUID:J
-Ljavax/xml/datatype/DatatypeConfigurationException;->readObject(Ljava/io/ObjectInputStream;)V
-Ljavax/xml/datatype/DatatypeConfigurationException;->serialVersionUID:J
-Ljavax/xml/namespace/QName;->readObject(Ljava/io/ObjectInputStream;)V
-Ljavax/xml/namespace/QName;->serialVersionUID:J
-Ljavax/xml/transform/TransformerException;->serialVersionUID:J
-Ljavax/xml/xpath/XPathException;->serialVersionUID:J
-Ljavax/xml/xpath/XPathExpressionException;->serialVersionUID:J
-Ljavax/xml/xpath/XPathFactoryConfigurationException;->serialVersionUID:J
-Ljavax/xml/xpath/XPathFunctionException;->serialVersionUID:J
-Llibcore/util/BasicLruCache;->map:Ljava/util/LinkedHashMap;
-Llibcore/util/ZoneInfo;->mTransitions:[J
-Llibcore/util/ZoneInfo;->readObject(Ljava/io/ObjectInputStream;)V
-Llibcore/util/ZoneInfo;->serialVersionUID:J
-Lorg/apache/http/conn/ConnectTimeoutException;->serialVersionUID:J
-Lorg/apache/http/conn/ssl/SSLSocketFactory;-><init>()V
-Lorg/apache/http/conn/ssl/SSLSocketFactory;-><init>(Ljavax/net/ssl/SSLSocketFactory;)V
-Lorg/ccil/cowan/tagsoup/AttributesImpl;->data:[Ljava/lang/String;
-Lorg/ccil/cowan/tagsoup/AttributesImpl;->length:I
-Lorg/json/JSONArray;->values:Ljava/util/List;
-Lorg/json/JSONObject;->append(Ljava/lang/String;Ljava/lang/Object;)Lorg/json/JSONObject;
-Lorg/json/JSONObject;->keySet()Ljava/util/Set;
-Lorg/json/JSONObject;->writeTo(Lorg/json/JSONStringer;)V
-Lorg/w3c/dom/traversal/NodeIterator;->nextNode()Lorg/w3c/dom/Node;
-Lsun/misc/Unsafe;->theUnsafe:Lsun/misc/Unsafe;
-Lsun/security/pkcs/ParsingException;->serialVersionUID:J
-Lsun/security/util/ObjectIdentifier$HugeOidNotSupportedByOldJDK;->serialVersionUID:J
-Lsun/security/util/ObjectIdentifier;->readObject(Ljava/io/ObjectInputStream;)V
-Lsun/security/util/ObjectIdentifier;->serialVersionUID:J
-Lsun/security/util/ObjectIdentifier;->writeObject(Ljava/io/ObjectOutputStream;)V
-Lsun/security/x509/AlgorithmId;->serialVersionUID:J
-Lsun/util/locale/LocaleSyntaxException;->serialVersionUID:J
diff --git a/config/hiddenapi-vendor-list.txt b/config/hiddenapi-vendor-list.txt
index 02719e3f8..45e38cf9 100644
--- a/config/hiddenapi-vendor-list.txt
+++ b/config/hiddenapi-vendor-list.txt
@@ -152,8 +152,8 @@
 Landroid/view/IRemoteAnimationRunner$Stub;-><init>()V
 Landroid/view/IRemoteAnimationRunner;->onAnimationCancelled()V
 Landroid/view/IRemoteAnimationRunner;->onAnimationStart([Landroid/view/RemoteAnimationTarget;Landroid/view/IRemoteAnimationFinishedCallback;)V
-Landroid/view/IWindowManager;->createInputConsumer(Landroid/os/IBinder;Ljava/lang/String;Landroid/view/InputChannel;)V
-Landroid/view/IWindowManager;->destroyInputConsumer(Ljava/lang/String;)Z
+Landroid/view/IWindowManager;->createInputConsumer(Landroid/os/IBinder;Ljava/lang/String;ILandroid/view/InputChannel;)V
+Landroid/view/IWindowManager;->destroyInputConsumer(Ljava/lang/String;I)Z
 Landroid/view/IWindowManager;->endProlongedAnimations()V
 Landroid/view/IWindowManager;->getStableInsets(ILandroid/graphics/Rect;)V
 Landroid/view/IWindowManager;->overridePendingAppTransitionMultiThumbFuture(Landroid/view/IAppTransitionAnimationSpecsFuture;Landroid/os/IRemoteCallback;Z)V
diff --git a/config/preloaded-classes b/config/preloaded-classes
index 63c583f..50e97c5 100644
--- a/config/preloaded-classes
+++ b/config/preloaded-classes
@@ -1436,12 +1436,6 @@
 android.hardware.usb.UsbDeviceConnection
 android.hardware.usb.UsbManager
 android.hardware.usb.UsbRequest
-android.hidl.base.V1_0.DebugInfo
-android.hidl.base.V1_0.IBase
-android.hidl.manager.V1_0.IServiceManager
-android.hidl.manager.V1_0.IServiceManager$Proxy
-android.hidl.manager.V1_0.IServiceNotification
-android.hidl.manager.V1_0.IServiceNotification$Stub
 android.icu.impl.BMPSet
 android.icu.impl.CacheBase
 android.icu.impl.CacheValue
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index 5b73eaa..f2ad268 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -27,6 +27,7 @@
 import android.content.Intent;
 import android.content.pm.ParceledListSlice;
 import android.graphics.Region;
+import android.os.Build;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
@@ -73,7 +74,7 @@
  * follows the established service life cycle. Starting an accessibility service is triggered
  * exclusively by the user explicitly turning the service on in device settings. After the system
  * binds to a service, it calls {@link AccessibilityService#onServiceConnected()}. This method can
- * be overriden by clients that want to perform post binding setup.
+ * be overridden by clients that want to perform post binding setup.
  * </p>
  * <p>
  * An accessibility service stops either when the user turns it off in device settings or when
@@ -399,7 +400,7 @@
     @IntDef(prefix = { "SHOW_MODE_" }, value = {
             SHOW_MODE_AUTO,
             SHOW_MODE_HIDDEN,
-            SHOW_MODE_WITH_HARD_KEYBOARD
+            SHOW_MODE_IGNORE_HARD_KEYBOARD
     })
     public @interface SoftKeyboardShowMode {}
 
@@ -419,7 +420,7 @@
      * 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;
+    public static final int SHOW_MODE_IGNORE_HARD_KEYBOARD = 2;
 
     /**
      * Mask used to cover the show modes supported in public API
@@ -446,7 +447,7 @@
     @UnsupportedAppUsage
     private AccessibilityServiceInfo mInfo;
 
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private IBinder mWindowToken;
 
     private WindowManager mWindowManager;
@@ -1205,7 +1206,7 @@
      *
      * @see AccessibilityService#SHOW_MODE_AUTO
      * @see AccessibilityService#SHOW_MODE_HIDDEN
-     * @see AccessibilityService#SHOW_MODE_WITH_HARD_KEYBOARD
+     * @see AccessibilityService#SHOW_MODE_IGNORE_HARD_KEYBOARD
      */
     public static final class SoftKeyboardController {
         private final AccessibilityService mService;
@@ -1354,7 +1355,7 @@
          *
          * @see AccessibilityService#SHOW_MODE_AUTO
          * @see AccessibilityService#SHOW_MODE_HIDDEN
-         * @see AccessibilityService#SHOW_MODE_WITH_HARD_KEYBOARD
+         * @see AccessibilityService#SHOW_MODE_IGNORE_HARD_KEYBOARD
          */
         @SoftKeyboardShowMode
         public int getShowMode() {
@@ -1384,7 +1385,7 @@
          *
          * @see AccessibilityService#SHOW_MODE_AUTO
          * @see AccessibilityService#SHOW_MODE_HIDDEN
-         * @see AccessibilityService#SHOW_MODE_WITH_HARD_KEYBOARD
+         * @see AccessibilityService#SHOW_MODE_IGNORE_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 f0a0e88..759443d 100644
--- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
+++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
@@ -76,6 +76,7 @@
  * @attr ref android.R.styleable#AccessibilityService_notificationTimeout
  * @attr ref android.R.styleable#AccessibilityService_packageNames
  * @attr ref android.R.styleable#AccessibilityService_settingsActivity
+ * @attr ref android.R.styleable#AccessibilityService_minimumUiTimeout
  * @see AccessibilityService
  * @see android.view.accessibility.AccessibilityEvent
  * @see android.view.accessibility.AccessibilityManager
@@ -426,6 +427,13 @@
     public boolean crashed;
 
     /**
+     * The minimum timeout in milliseconds that UI controls need to remain on the screen.
+     *
+     * @see #setMinimumUiTimeoutMillis
+     */
+    private int mMinimumUiTimeout;
+
+    /**
      * The component name the accessibility service.
      */
     private ComponentName mComponentName;
@@ -529,6 +537,9 @@
             notificationTimeout = asAttributes.getInt(
                     com.android.internal.R.styleable.AccessibilityService_notificationTimeout,
                     0);
+            mMinimumUiTimeout = asAttributes.getInt(
+                    com.android.internal.R.styleable.AccessibilityService_minimumUiTimeout,
+                    0);
             flags = asAttributes.getInt(
                     com.android.internal.R.styleable.AccessibilityService_accessibilityFlags, 0);
             mSettingsActivityName = asAttributes.getString(
@@ -598,6 +609,7 @@
         packageNames = other.packageNames;
         feedbackType = other.feedbackType;
         notificationTimeout = other.notificationTimeout;
+        mMinimumUiTimeout = other.mMinimumUiTimeout;
         flags = other.flags;
     }
 
@@ -755,6 +767,29 @@
         return null;
     }
 
+    /**
+     * Set the minimum time that controls need to remain on the screen to support the user.
+     * <p>
+     *    <strong>This value can be dynamically set at runtime by
+     *    {@link AccessibilityService#setServiceInfo(AccessibilityServiceInfo)}.</strong>
+     * </p>
+     *
+     * @param timeout The timeout in milliseconds.
+     */
+    public void setMinimumUiTimeoutMillis(int timeout) {
+        mMinimumUiTimeout = timeout;
+    }
+
+    /**
+     * Get the minimum ui timeout.
+     *
+     * @see #setMinimumUiTimeoutMillis
+     * @return The timeout in milliseconds.
+     */
+    public int getMinimumUiTimeoutMillis() {
+        return mMinimumUiTimeout;
+    }
+
     /** {@hide} */
     public boolean isDirectBootAware() {
         return ((flags & FLAG_FORCE_DIRECT_BOOT_AWARE) != 0)
@@ -773,6 +808,7 @@
         parcel.writeStringArray(packageNames);
         parcel.writeInt(feedbackType);
         parcel.writeLong(notificationTimeout);
+        parcel.writeInt(mMinimumUiTimeout);
         parcel.writeInt(flags);
         parcel.writeInt(crashed ? 1 : 0);
         parcel.writeParcelable(mComponentName, flagz);
@@ -790,6 +826,7 @@
         packageNames = parcel.readStringArray();
         feedbackType = parcel.readInt();
         notificationTimeout = parcel.readLong();
+        mMinimumUiTimeout = parcel.readInt();
         flags = parcel.readInt();
         crashed = parcel.readInt() != 0;
         mComponentName = parcel.readParcelable(this.getClass().getClassLoader());
@@ -840,6 +877,8 @@
         stringBuilder.append(", ");
         stringBuilder.append("notificationTimeout: ").append(notificationTimeout);
         stringBuilder.append(", ");
+        stringBuilder.append("minimumUiTimeout: ").append(mMinimumUiTimeout);
+        stringBuilder.append(", ");
         appendFlags(stringBuilder, flags);
         stringBuilder.append(", ");
         stringBuilder.append("id: ").append(getId());
diff --git a/core/java/android/accessibilityservice/TEST_MAPPING b/core/java/android/accessibilityservice/TEST_MAPPING
new file mode 100644
index 0000000..c7c4c3a
--- /dev/null
+++ b/core/java/android/accessibilityservice/TEST_MAPPING
@@ -0,0 +1,23 @@
+{
+  "presubmit": [
+    {
+      "name": "CtsAccessibilityServiceTestCases",
+      "options": [
+        {
+          "include-annotation": "android.platform.test.annotations.Presubmit"
+        },
+        {
+          "exclude-annotation": "android.support.test.filters.FlakyTest"
+        }
+      ]
+    }
+  ],
+  "postsubmit": [
+    {
+      "name": "CtsAccessibilityServiceTestCases"
+    },
+    {
+      "name": "CtsAccessibilityTestCases"
+    }
+  ]
+}
diff --git a/core/java/android/accounts/Account.java b/core/java/android/accounts/Account.java
index f07f5ec..d3b2238 100644
--- a/core/java/android/accounts/Account.java
+++ b/core/java/android/accounts/Account.java
@@ -20,13 +20,14 @@
 import android.annotation.Nullable;
 import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
-import android.os.Parcelable;
 import android.os.Parcel;
+import android.os.Parcelable;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.text.TextUtils;
 import android.util.ArraySet;
 import android.util.Log;
+
 import com.android.internal.annotations.GuardedBy;
 
 import java.util.Set;
@@ -45,6 +46,7 @@
 
     public final String name;
     public final String type;
+    private String mSafeName;
     @UnsupportedAppUsage
     private final @Nullable String accessId;
 
@@ -135,4 +137,37 @@
     public String toString() {
         return "Account {name=" + name + ", type=" + type + "}";
     }
+
+    /**
+     * Return a string representation of the account that is safe to print
+     * to logs and other places where PII should be avoided.
+     * @hide
+     */
+    public String toSafeString() {
+        if (mSafeName == null) {
+            mSafeName = toSafeName(name, 'x');
+        }
+        return "Account {name=" + mSafeName + ", type=" + type + "}";
+    }
+
+    /**
+     * Given a name, replace all letter or digits with the replacement char.
+     * @param name The input name string.
+     * @param replacement the replacement character.
+     * @return the string after replacement.
+     * @hide
+     */
+    public static String toSafeName(String name, char replacement) {
+        final StringBuilder builder = new StringBuilder(64);
+        final int len = name.length();
+        for (int i = 0; i < len; i++) {
+            final char c = name.charAt(i);
+            if (Character.isLetterOrDigit(c)) {
+                builder.append(replacement);
+            } else {
+                builder.append(c);
+            }
+        }
+        return builder.toString();
+    }
 }
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index bf2d860..5499d59 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -847,7 +847,7 @@
     /*package*/ ActionBar mActionBar = null;
     private boolean mEnableDefaultActionBarUp;
 
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private VoiceInteractor mVoiceInteractor;
 
     @UnsupportedAppUsage
@@ -2310,7 +2310,7 @@
      *
      * @param newConfig The new device configuration.
      */
-    public void onConfigurationChanged(Configuration newConfig) {
+    public void onConfigurationChanged(@NonNull Configuration newConfig) {
         if (DEBUG_LIFECYCLE) Slog.v(TAG, "onConfigurationChanged " + this + ": " + newConfig);
         mCalled = true;
 
@@ -3523,7 +3523,7 @@
      * {@link android.view.Window#FEATURE_OPTIONS_PANEL} panel,
      * so that subclasses of Activity don't need to deal with feature codes.
      */
-    public boolean onCreatePanelMenu(int featureId, Menu menu) {
+    public boolean onCreatePanelMenu(int featureId, @NonNull Menu menu) {
         if (featureId == Window.FEATURE_OPTIONS_PANEL) {
             boolean show = onCreateOptionsMenu(menu);
             show |= mFragments.dispatchCreateOptionsMenu(menu, getMenuInflater());
@@ -3541,8 +3541,8 @@
      * panel, so that subclasses of
      * Activity don't need to deal with feature codes.
      */
-    public boolean onPreparePanel(int featureId, View view, Menu menu) {
-        if (featureId == Window.FEATURE_OPTIONS_PANEL && menu != null) {
+    public boolean onPreparePanel(int featureId, @Nullable View view, @NonNull Menu menu) {
+        if (featureId == Window.FEATURE_OPTIONS_PANEL) {
             boolean goforit = onPrepareOptionsMenu(menu);
             goforit |= mFragments.dispatchPrepareOptionsMenu(menu);
             return goforit;
@@ -3555,7 +3555,8 @@
      *
      * @return The default implementation returns true.
      */
-    public boolean onMenuOpened(int featureId, Menu menu) {
+    @Override
+    public boolean onMenuOpened(int featureId, @NonNull Menu menu) {
         if (featureId == Window.FEATURE_ACTION_BAR) {
             initWindowDecorActionBar();
             if (mActionBar != null) {
@@ -3576,7 +3577,7 @@
      * panel, so that subclasses of
      * Activity don't need to deal with feature codes.
      */
-    public boolean onMenuItemSelected(int featureId, MenuItem item) {
+    public boolean onMenuItemSelected(int featureId, @NonNull MenuItem item) {
         CharSequence titleCondensed = item.getTitleCondensed();
 
         switch (featureId) {
@@ -3626,7 +3627,7 @@
      * For context menus ({@link Window#FEATURE_CONTEXT_MENU}), the
      * {@link #onContextMenuClosed(Menu)} will be called.
      */
-    public void onPanelClosed(int featureId, Menu menu) {
+    public void onPanelClosed(int featureId, @NonNull Menu menu) {
         switch (featureId) {
             case Window.FEATURE_OPTIONS_PANEL:
                 mFragments.dispatchOptionsMenuClosed(menu);
@@ -3734,7 +3735,7 @@
      *
      * @see #onCreateOptionsMenu
      */
-    public boolean onOptionsItemSelected(MenuItem item) {
+    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
         if (mParent != null) {
             return mParent.onOptionsItemSelected(item);
         }
@@ -3958,7 +3959,7 @@
      * @return boolean Return false to allow normal context menu processing to
      *         proceed, true to consume it here.
      */
-    public boolean onContextItemSelected(MenuItem item) {
+    public boolean onContextItemSelected(@NonNull MenuItem item) {
         if (mParent != null) {
             return mParent.onContextItemSelected(item);
         }
@@ -3972,7 +3973,7 @@
      *
      * @param menu The context menu that is being closed.
      */
-    public void onContextMenuClosed(Menu menu) {
+    public void onContextMenuClosed(@NonNull Menu menu) {
         if (mParent != null) {
             mParent.onContextMenuClosed(menu);
         }
@@ -6350,7 +6351,8 @@
      * @see android.view.Window#getLayoutInflater
      */
     @Nullable
-    public View onCreateView(String name, Context context, AttributeSet attrs) {
+    public View onCreateView(@NonNull String name, @NonNull Context context,
+            @NonNull AttributeSet attrs) {
         return null;
     }
 
@@ -6364,7 +6366,9 @@
      * @see android.view.LayoutInflater#createView
      * @see android.view.Window#getLayoutInflater
      */
-    public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {
+    @Nullable
+    public View onCreateView(@Nullable View parent, @NonNull String name,
+            @NonNull Context context, @NonNull AttributeSet attrs) {
         if (!"fragment".equals(name)) {
             return onCreateView(name, context, attrs);
         }
@@ -6382,11 +6386,13 @@
      * closed for you after you return.
      * @param args additional arguments to the dump request.
      */
-    public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
+    public void dump(@NonNull String prefix, @Nullable FileDescriptor fd,
+            @NonNull PrintWriter writer, @Nullable String[] args) {
         dumpInner(prefix, fd, writer, args);
     }
 
-    void dumpInner(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
+    void dumpInner(@NonNull String prefix, @Nullable FileDescriptor fd,
+            @NonNull PrintWriter writer, @Nullable String[] args) {
         if (args != null && args.length > 0 && args[0].equals("--autofill")) {
             dumpAutofillManager(prefix, writer);
             return;
@@ -7094,7 +7100,7 @@
 
     // ------------------ Internal API ------------------
 
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     final void setParent(Activity parent) {
         mParent = parent;
     }
@@ -7205,7 +7211,7 @@
         mActivityTransitionState.setEnterActivityOptions(this, getActivityOptions());
     }
 
-    final void performNewIntent(Intent intent) {
+    final void performNewIntent(@NonNull Intent intent) {
         mCanEnterPictureInPicture = true;
         onNewIntent(intent);
     }
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 8354235..e86a49d 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -1221,7 +1221,7 @@
          * @return The background color.
          * @hide
          */
-        @UnsupportedAppUsage
+        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
         public int getBackgroundColor() {
             return mColorBackground;
         }
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 9120701..31e9a2d 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -340,7 +340,7 @@
     // An executor that performs multi-step transactions.
     private final TransactionExecutor mTransactionExecutor = new TransactionExecutor(this);
 
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private final ResourcesManager mResourcesManager;
 
     private static final class ProviderKey {
@@ -374,7 +374,7 @@
     @UnsupportedAppUsage
     final ArrayMap<IBinder, ProviderRefCount> mProviderRefCountMap
         = new ArrayMap<IBinder, ProviderRefCount>();
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     final ArrayMap<IBinder, ProviderClientRecord> mLocalProviders
         = new ArrayMap<IBinder, ProviderClientRecord>();
     @UnsupportedAppUsage
@@ -394,7 +394,7 @@
     final GcIdler mGcIdler = new GcIdler();
     boolean mGcIdlerScheduled = false;
 
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     static volatile Handler sMainThreadHandler;  // set once in main()
 
     Bundle mCoreSettings = null;
@@ -456,7 +456,7 @@
         private int mLifecycleState = PRE_ON_CREATE;
 
         @VisibleForTesting
-        @UnsupportedAppUsage
+        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
         public ActivityClientRecord() {
             this.isForward = false;
             init();
@@ -704,7 +704,7 @@
         @UnsupportedAppUsage
         boolean persistent;
         Configuration config;
-        @UnsupportedAppUsage
+        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
         CompatibilityInfo compatInfo;
         String buildSerial;
 
@@ -2088,7 +2088,7 @@
         return mH;
     }
 
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     public final LoadedApk getPackageInfo(String packageName, CompatibilityInfo compatInfo,
             int flags) {
         return getPackageInfo(packageName, compatInfo, flags, UserHandle.myUserId());
@@ -2131,7 +2131,7 @@
             ai = getPackageManager().getApplicationInfo(packageName,
                     PackageManager.GET_SHARED_LIBRARY_FILES
                             | PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
-                    userId);
+                    (userId < 0) ? UserHandle.myUserId() : userId);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -2177,7 +2177,7 @@
         return getPackageInfo(ai, compatInfo, null, false, true, false);
     }
 
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     public final LoadedApk peekPackageInfo(String packageName, boolean includeCode) {
         synchronized (mResourcesManager) {
             WeakReference<LoadedApk> ref;
@@ -2850,7 +2850,7 @@
         return aInfo;
     }
 
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     public final Activity startActivityNow(Activity parent, String id,
         Intent intent, ActivityInfo activityInfo, IBinder token, Bundle state,
         Activity.NonConfigurationInstances lastNonConfigurationInstances) {
diff --git a/core/java/android/app/AlarmManager.java b/core/java/android/app/AlarmManager.java
index ec4c4db..9b13420 100644
--- a/core/java/android/app/AlarmManager.java
+++ b/core/java/android/app/AlarmManager.java
@@ -1151,7 +1151,9 @@
         public void writeToProto(ProtoOutputStream proto, long fieldId) {
             final long token = proto.start(fieldId);
             proto.write(AlarmClockInfoProto.TRIGGER_TIME_MS, mTriggerTime);
-            mShowIntent.writeToProto(proto, AlarmClockInfoProto.SHOW_INTENT);
+            if (mShowIntent != null) {
+                mShowIntent.writeToProto(proto, AlarmClockInfoProto.SHOW_INTENT);
+            }
             proto.end(token);
         }
     }
diff --git a/core/java/android/app/AlertDialog.java b/core/java/android/app/AlertDialog.java
index dbc8c5d..cf40e06 100644
--- a/core/java/android/app/AlertDialog.java
+++ b/core/java/android/app/AlertDialog.java
@@ -397,7 +397,7 @@
      * @param listener The {@link DialogInterface.OnClickListener} to use.
      * @deprecated Use
      *             {@link #setButton(int, CharSequence, android.content.DialogInterface.OnClickListener)}
-     *             with {@link DialogInterface#BUTTON_POSITIVE}
+     *             with {@link DialogInterface#BUTTON_NEUTRAL}
      */
     @Deprecated
     public void setButton3(CharSequence text, final OnClickListener listener) {
diff --git a/core/java/android/app/Application.java b/core/java/android/app/Application.java
index 636366d..68b745d 100644
--- a/core/java/android/app/Application.java
+++ b/core/java/android/app/Application.java
@@ -127,7 +127,7 @@
     }
 
     @CallSuper
-    public void onConfigurationChanged(Configuration newConfig) {
+    public void onConfigurationChanged(@NonNull Configuration newConfig) {
         Object[] callbacks = collectComponentCallbacks();
         if (callbacks != null) {
             for (int i=0; i<callbacks.length; i++) {
diff --git a/core/java/android/app/AutomaticZenRule.java b/core/java/android/app/AutomaticZenRule.java
index cd4ace6..62f6bac 100644
--- a/core/java/android/app/AutomaticZenRule.java
+++ b/core/java/android/app/AutomaticZenRule.java
@@ -16,11 +16,14 @@
 
 package android.app;
 
+import static android.app.NotificationManager.INTERRUPTION_FILTER_PRIORITY;
+
 import android.app.NotificationManager.InterruptionFilter;
 import android.content.ComponentName;
 import android.net.Uri;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.service.notification.ZenPolicy;
 
 import java.util.Objects;
 
@@ -35,6 +38,7 @@
     private Uri conditionId;
     private ComponentName owner;
     private long creationTime;
+    private ZenPolicy mZenPolicy;
 
     /**
      * Creates an automatic zen rule.
@@ -58,7 +62,27 @@
     }
 
     /**
-     * @SystemApi
+     * Creates an automatic zen rule.
+     *
+     * @param name The name of the rule.
+     * @param owner The Condition Provider service that owns this rule.
+     * @param conditionId A representation of the state that should cause the Condition Provider
+     *                    service to apply the given interruption filter.
+     * @param policy The policy defines which notifications are allowed to interrupt the user
+     *               while this rule is active
+     * @param enabled Whether the rule is enabled.
+     */
+    public AutomaticZenRule(String name, ComponentName owner, Uri conditionId, ZenPolicy policy,
+            boolean enabled) {
+        this.name = name;
+        this.owner = owner;
+        this.conditionId = conditionId;
+        this.interruptionFilter = INTERRUPTION_FILTER_PRIORITY;
+        this.enabled = enabled;
+        this.mZenPolicy = policy;
+    }
+
+    /**
      * @hide
      */
     public AutomaticZenRule(String name, ComponentName owner, Uri conditionId,
@@ -67,6 +91,15 @@
         this.creationTime = creationTime;
     }
 
+    /**
+     * @hide
+     */
+    public AutomaticZenRule(String name, ComponentName owner, Uri conditionId, ZenPolicy policy,
+            boolean enabled, long creationTime) {
+        this(name, owner, conditionId, policy, enabled);
+        this.creationTime = creationTime;
+    }
+
     public AutomaticZenRule(Parcel source) {
         enabled = source.readInt() == 1;
         if (source.readInt() == 1) {
@@ -76,6 +109,7 @@
         conditionId = source.readParcelable(null);
         owner = source.readParcelable(null);
         creationTime = source.readLong();
+        mZenPolicy = source.readParcelable(null);
     }
 
     /**
@@ -114,6 +148,13 @@
     }
 
     /**
+     * Gets the zen policy.
+     */
+    public ZenPolicy getZenPolicy() {
+        return this.mZenPolicy.copy();
+    }
+
+    /**
      * Returns the time this rule was created, represented as milliseconds since the epoch.
      */
     public long getCreationTime() {
@@ -149,6 +190,13 @@
         this.enabled = enabled;
     }
 
+    /**
+     * Sets the zen policy.
+     */
+    public void setZenPolicy(ZenPolicy zenPolicy) {
+        this.mZenPolicy = zenPolicy;
+    }
+
     @Override
     public int describeContents() {
         return 0;
@@ -167,6 +215,7 @@
         dest.writeParcelable(conditionId, 0);
         dest.writeParcelable(owner, 0);
         dest.writeLong(creationTime);
+        dest.writeParcelable(mZenPolicy, 0);
     }
 
     @Override
@@ -178,6 +227,7 @@
                 .append(",conditionId=").append(conditionId)
                 .append(",owner=").append(owner)
                 .append(",creationTime=").append(creationTime)
+                .append(",mZenPolicy=").append(mZenPolicy)
                 .append(']').toString();
     }
 
@@ -191,12 +241,14 @@
                 && other.interruptionFilter == interruptionFilter
                 && Objects.equals(other.conditionId, conditionId)
                 && Objects.equals(other.owner, owner)
-                && other.creationTime == creationTime;
+                && other.creationTime == creationTime
+                && Objects.equals(other.mZenPolicy, mZenPolicy);
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(enabled, name, interruptionFilter, conditionId, owner, creationTime);
+        return Objects.hash(enabled, name, interruptionFilter, conditionId, owner, creationTime,
+                mZenPolicy);
     }
 
     public static final Parcelable.Creator<AutomaticZenRule> CREATOR
diff --git a/core/java/android/app/ContentProviderHolder.java b/core/java/android/app/ContentProviderHolder.java
index 1098990..2a13c71 100644
--- a/core/java/android/app/ContentProviderHolder.java
+++ b/core/java/android/app/ContentProviderHolder.java
@@ -20,6 +20,7 @@
 import android.content.ContentProviderNative;
 import android.content.IContentProvider;
 import android.content.pm.ProviderInfo;
+import android.os.Build;
 import android.os.IBinder;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -35,7 +36,7 @@
     @UnsupportedAppUsage
     public IContentProvider provider;
     public IBinder connection;
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     public boolean noReleaseNeeded;
 
     @UnsupportedAppUsage
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index bbaaee8..77f6395 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -164,7 +164,7 @@
      * Map from preference name to generated path.
      */
     @GuardedBy("ContextImpl.class")
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private ArrayMap<String, File> mSharedPrefsPaths;
 
     @UnsupportedAppUsage
@@ -183,7 +183,7 @@
 
     @UnsupportedAppUsage
     private final String mBasePackageName;
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private final String mOpPackageName;
 
     private final @NonNull ResourcesManager mResourcesManager;
@@ -191,7 +191,7 @@
     private @NonNull Resources mResources;
     private @Nullable Display mDisplay; // may be null if default display
 
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private final int mFlags;
 
     @UnsupportedAppUsage
diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java
index b7bac52..6bcfb2e 100644
--- a/core/java/android/app/Dialog.java
+++ b/core/java/android/app/Dialog.java
@@ -34,6 +34,7 @@
 import android.content.res.ResourceId;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
@@ -133,7 +134,7 @@
     private final Handler mHandler = new Handler();
 
     private static final int DISMISS = 0x43;
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private static final int CANCEL = 0x44;
     private static final int SHOW = 0x45;
 
@@ -936,8 +937,8 @@
      * @see Activity#onPreparePanel(int, View, Menu)
      */
     @Override
-    public boolean onPreparePanel(int featureId, View view, Menu menu) {
-        if (featureId == Window.FEATURE_OPTIONS_PANEL && menu != null) {
+    public boolean onPreparePanel(int featureId, @Nullable View view, @NonNull Menu menu) {
+        if (featureId == Window.FEATURE_OPTIONS_PANEL) {
             return onPrepareOptionsMenu(menu) && menu.hasVisibleItems();
         }
         return true;
@@ -947,7 +948,7 @@
      * @see Activity#onMenuOpened(int, Menu)
      */
     @Override
-    public boolean onMenuOpened(int featureId, Menu menu) {
+    public boolean onMenuOpened(int featureId, @NonNull Menu menu) {
         if (featureId == Window.FEATURE_ACTION_BAR) {
             mActionBar.dispatchMenuVisibilityChanged(true);
         }
@@ -958,7 +959,7 @@
      * @see Activity#onMenuItemSelected(int, MenuItem)
      */
     @Override
-    public boolean onMenuItemSelected(int featureId, MenuItem item) {
+    public boolean onMenuItemSelected(int featureId, @NonNull MenuItem item) {
         return false;
     }
 
@@ -966,7 +967,7 @@
      * @see Activity#onPanelClosed(int, Menu)
      */
     @Override
-    public void onPanelClosed(int featureId, Menu menu) {
+    public void onPanelClosed(int featureId, @NonNull Menu menu) {
         if (featureId == Window.FEATURE_ACTION_BAR) {
             mActionBar.dispatchMenuVisibilityChanged(false);
         }
diff --git a/core/java/android/app/DownloadManager.java b/core/java/android/app/DownloadManager.java
index 35999a2..1622c06 100644
--- a/core/java/android/app/DownloadManager.java
+++ b/core/java/android/app/DownloadManager.java
@@ -879,7 +879,7 @@
          * @return this object
          * @hide
          */
-        @UnsupportedAppUsage
+        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
         public Query orderBy(String column, int direction) {
             if (direction != ORDER_ASCENDING && direction != ORDER_DESCENDING) {
                 throw new IllegalArgumentException("Invalid direction: " + direction);
@@ -1011,7 +1011,7 @@
     }
 
     /** {@hide} */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     public void setAccessFilename(boolean accessFilename) {
         mAccessFilename = accessFilename;
     }
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index 9f4157f..49917b4 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -264,7 +264,7 @@
  */
 @Deprecated
 public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListener {
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private static final ArrayMap<String, Class<?>> sClassMap =
             new ArrayMap<String, Class<?>>();
 
diff --git a/core/java/android/app/IBackupAgent.aidl b/core/java/android/app/IBackupAgent.aidl
index 4517446..d3d7c68 100644
--- a/core/java/android/app/IBackupAgent.aidl
+++ b/core/java/android/app/IBackupAgent.aidl
@@ -48,8 +48,7 @@
      *        be echoed back to the backup service binder once the new
      *        data has been written to the data and newState files.
      *
-     * @param callbackBinder Binder on which to indicate operation completion,
-     *        passed here as a convenience to the agent.
+     * @param callbackBinder Binder on which to indicate operation completion.
      *
      * @param transportFlags Flags with additional information about the transport.
      */
@@ -133,8 +132,9 @@
      *                        Could be less than total backup size if backup process was interrupted
      *                        before finish of processing all backup data.
      * @param quotaBytes Current amount of backup data that is allowed for the app.
+     * @param callbackBinder Binder on which to indicate operation completion.
      */
-    void doQuotaExceeded(long backupDataBytes, long quotaBytes);
+    void doQuotaExceeded(long backupDataBytes, long quotaBytes, IBackupCallback callbackBinder);
 
     /**
      * Restore a single "file" to the application.  The file was typically obtained from
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index 3171e3e..357420b 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -112,6 +112,7 @@
 
     ParceledListSlice getActiveNotificationsFromListener(in INotificationListener token, in String[] keys, int trim);
     ParceledListSlice getSnoozedNotificationsFromListener(in INotificationListener token, int trim);
+    void clearRequestedListenerHints(in INotificationListener token);
     void requestHintsFromListener(in INotificationListener token, int hints);
     int getHintsFromListener(in INotificationListener token);
     void requestInterruptionFilterFromListener(in INotificationListener token, int interruptionFilter);
@@ -165,4 +166,9 @@
     void applyRestore(in byte[] payload, int user);
 
     ParceledListSlice getAppActiveNotifications(String callingPkg, int userId);
+
+    void setNotificationDelegate(String callingPkg, String delegate);
+    void revokeNotificationDelegate(String callingPkg);
+    String getNotificationDelegate(String callingPkg);
+    boolean canNotifyAsPackage(String callingPkg, String targetPkg);
 }
diff --git a/core/java/android/app/KeyguardManager.java b/core/java/android/app/KeyguardManager.java
index 3085fe5..b720df8 100644
--- a/core/java/android/app/KeyguardManager.java
+++ b/core/java/android/app/KeyguardManager.java
@@ -29,6 +29,7 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.os.Binder;
+import android.os.Build;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.RemoteException;
@@ -415,7 +416,7 @@
      *
      * @hide
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     public boolean isDeviceLocked(int userId) {
         try {
             return mTrustManager.isDeviceLocked(userId);
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index ddd9441..b827d01 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -111,7 +111,7 @@
     private String mDataDir;
     @UnsupportedAppUsage
     private String mLibDir;
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private File mDataDirFile;
     private File mDeviceProtectedDataDirFile;
     private File mCredentialProtectedDataDirFile;
@@ -141,7 +141,7 @@
         = new ArrayMap<>();
     private final ArrayMap<Context, ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>> mUnregisteredReceivers
         = new ArrayMap<>();
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private final ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>> mServices
         = new ArrayMap<>();
     private final ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>> mUnboundServices
@@ -1358,7 +1358,7 @@
         final IIntentReceiver.Stub mIIntentReceiver;
         @UnsupportedAppUsage
         final BroadcastReceiver mReceiver;
-        @UnsupportedAppUsage
+        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
         final Context mContext;
         final Handler mActivityThread;
         final Instrumentation mInstrumentation;
@@ -1605,7 +1605,7 @@
         private final ServiceDispatcher.InnerConnection mIServiceConnection;
         @UnsupportedAppUsage
         private final ServiceConnection mConnection;
-        @UnsupportedAppUsage
+        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
         private final Context mContext;
         private final Handler mActivityThread;
         private final ServiceConnectionLeaked mLocation;
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 9dca061..217225e 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -1417,7 +1417,7 @@
         public static final int SEMANTIC_ACTION_CALL = 10;
 
         private final Bundle mExtras;
-        @UnsupportedAppUsage
+        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
         private Icon mIcon;
         private final RemoteInput[] mRemoteInputs;
         private boolean mAllowGeneratedReplies = true;
@@ -3499,7 +3499,7 @@
 
         /**
          * Set the small icon, which will be used to represent the notification in the
-         * status bar and content view (unless overriden there by a
+         * status bar and content view (unless overridden there by a
          * {@link #setLargeIcon(Bitmap) large icon}).
          *
          * @param icon An Icon object to use.
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index 4b25b8b..9f819b9 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -18,6 +18,7 @@
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.SdkConstant;
 import android.annotation.SystemService;
 import android.annotation.TestApi;
@@ -352,7 +353,7 @@
     }
 
     /**
-     * Post a notification to be shown in the status bar. If a notification with
+     * Posts a notification to be shown in the status bar. If a notification with
      * the same tag and id has already been posted by your application and has not yet been
      * canceled, it will be replaced by the updated information.
      *
@@ -376,6 +377,42 @@
     }
 
     /**
+     * Posts a notification as a specified package to be shown in the status bar. If a notification
+     * with the same tag and id has already been posted for that package and has not yet been
+     * canceled, it will be replaced by the updated information.
+     *
+     * All {@link android.service.notification.NotificationListenerService listener services} will
+     * be granted {@link Intent#FLAG_GRANT_READ_URI_PERMISSION} access to any {@link Uri uris}
+     * provided on this notification or the
+     * {@link NotificationChannel} this notification is posted to using
+     * {@link Context#grantUriPermission(String, Uri, int)}. Permission will be revoked when the
+     * notification is canceled, or you can revoke permissions with
+     * {@link Context#revokeUriPermission(Uri, int)}.
+     *
+     * @param targetPackage The package to post the notification as. The package must have granted
+     *                      you access to post notifications on their behalf with
+     *                      {@link #setNotificationDelegate(String)}.
+     * @param tag A string identifier for this notification.  May be {@code null}.
+     * @param id An identifier for this notification.  The pair (tag, id) must be unique
+     *        within your application.
+     * @param notification A {@link Notification} object describing what to
+     *        show the user. Must not be null.
+     */
+    public void notifyAsPackage(@NonNull String targetPackage, @NonNull String tag, int id,
+            Notification notification) {
+        INotificationManager service = getService();
+        String sender = mContext.getPackageName();
+
+        try {
+            if (localLOGV) Log.v(TAG, sender + ": notify(" + id + ", " + notification + ")");
+            service.enqueueNotificationWithTag(targetPackage, sender, tag, id,
+                    fixNotification(notification), mContext.getUser().getIdentifier());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * @hide
      */
     @UnsupportedAppUsage
@@ -383,6 +420,18 @@
     {
         INotificationManager service = getService();
         String pkg = mContext.getPackageName();
+
+        try {
+            if (localLOGV) Log.v(TAG, pkg + ": notify(" + id + ", " + notification + ")");
+            service.enqueueNotificationWithTag(pkg, mContext.getOpPackageName(), tag, id,
+                    fixNotification(notification), user.getIdentifier());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    private Notification fixNotification(Notification notification) {
+        String pkg = mContext.getPackageName();
         // Fix the notification as best we can.
         Notification.addFieldsFromContext(mContext, notification);
 
@@ -400,19 +449,12 @@
                         + notification);
             }
         }
-        if (localLOGV) Log.v(TAG, pkg + ": notify(" + id + ", " + notification + ")");
+
         notification.reduceImageSizes(mContext);
 
         ActivityManager am = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
         boolean isLowRam = am.isLowRamDevice();
-        final Notification copy = Builder.maybeCloneStrippedForDelivery(notification, isLowRam,
-                mContext);
-        try {
-            service.enqueueNotificationWithTag(pkg, mContext.getOpPackageName(), tag, id,
-                    copy, user.getIdentifier());
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
+        return Builder.maybeCloneStrippedForDelivery(notification, isLowRam, mContext);
     }
 
     private void fixLegacySmallIcon(Notification n, String pkg) {
@@ -474,6 +516,72 @@
     }
 
     /**
+     * Allows a package to post notifications on your behalf using
+     * {@link #notifyAsPackage(String, String, int, Notification)}.
+     *
+     * This can be used to allow persistent processes to post notifications based on messages
+     * received on your behalf from the cloud, without your process having to wake up.
+     *
+     * You can check if you have an allowed delegate with {@link #getNotificationDelegate()} and
+     * revoke your delegate with {@link #revokeNotificationDelegate()}.
+     *
+     * @param delegate Package name of the app which can send notifications on your behalf.
+     */
+    public void setNotificationDelegate(@NonNull String delegate) {
+        INotificationManager service = getService();
+        String pkg = mContext.getPackageName();
+        if (localLOGV) Log.v(TAG, pkg + ": cancelAll()");
+        try {
+            service.setNotificationDelegate(pkg, delegate);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Revokes permission for your {@link #setNotificationDelegate(String) notification delegate}
+     * to post notifications on your behalf.
+     */
+    public void revokeNotificationDelegate() {
+        INotificationManager service = getService();
+        String pkg = mContext.getPackageName();
+        try {
+            service.revokeNotificationDelegate(pkg);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Returns the {@link #setNotificationDelegate(String) delegate} that can post notifications on
+     * your behalf, if there currently is one.
+     */
+    public @Nullable String getNotificationDelegate() {
+        INotificationManager service = getService();
+        String pkg = mContext.getPackageName();
+        try {
+            return service.getNotificationDelegate(pkg);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Returns whether you are allowed to post notifications on behalf of a given package, with
+     * {@link #notifyAsPackage(String, String, int, Notification)}.
+     *
+     * See {@link #setNotificationDelegate(String)}.
+     */
+    public boolean canNotifyAsPackage(String pkg) {
+        INotificationManager service = getService();
+        try {
+            return service.canNotifyAsPackage(mContext.getPackageName(), pkg);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Creates a group container for {@link NotificationChannel} objects.
      *
      * This can be used to rename an existing group.
@@ -733,9 +841,14 @@
             List<ZenModeConfig.ZenRule> rules = service.getZenRules();
             Map<String, AutomaticZenRule> ruleMap = new HashMap<>();
             for (ZenModeConfig.ZenRule rule : rules) {
-                ruleMap.put(rule.id, new AutomaticZenRule(rule.name, rule.component,
-                        rule.conditionId, zenModeToInterruptionFilter(rule.zenMode), rule.enabled,
-                        rule.creationTime));
+                if (rule.zenPolicy == null) {
+                    ruleMap.put(rule.id, new AutomaticZenRule(rule.name, rule.component,
+                            rule.conditionId, zenModeToInterruptionFilter(rule.zenMode),
+                            rule.enabled, rule.creationTime));
+                } else {
+                    ruleMap.put(rule.id, new AutomaticZenRule(rule.name, rule.component,
+                            rule.conditionId, rule.zenPolicy, rule.enabled, rule.creationTime));
+                }
             }
             return ruleMap;
         } catch (RemoteException e) {
diff --git a/core/java/android/app/UiAutomation.java b/core/java/android/app/UiAutomation.java
index dbb6c3d..c0903b6 100644
--- a/core/java/android/app/UiAutomation.java
+++ b/core/java/android/app/UiAutomation.java
@@ -29,6 +29,7 @@
 import android.graphics.Rect;
 import android.graphics.Region;
 import android.hardware.display.DisplayManagerGlobal;
+import android.os.Build;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.IBinder;
@@ -193,7 +194,7 @@
      *
      * @hide
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     public UiAutomation(Looper looper, IUiAutomationConnection connection) {
         if (looper == null) {
             throw new IllegalArgumentException("Looper cannot be null!");
@@ -210,7 +211,7 @@
      *
      * @hide
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     public void connect() {
         connect(0);
     }
@@ -282,7 +283,7 @@
      *
      * @hide
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     public void disconnect() {
         synchronized (mLock) {
             if (mIsConnecting) {
diff --git a/core/java/android/app/Vr2dDisplayProperties.java b/core/java/android/app/Vr2dDisplayProperties.java
index 2fd82b2..1752131 100644
--- a/core/java/android/app/Vr2dDisplayProperties.java
+++ b/core/java/android/app/Vr2dDisplayProperties.java
@@ -35,6 +35,7 @@
 
     public static final int FLAG_VIRTUAL_DISPLAY_ENABLED = 1;
 
+    /** @hide */
     @Retention(RetentionPolicy.SOURCE)
     @IntDef({
         FLAG_VIRTUAL_DISPLAY_ENABLED
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index 2a263d6..bebe79e 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -1288,7 +1288,7 @@
      * requires permission {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL}.
      * @hide
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     public int setBitmap(Bitmap fullImage, Rect visibleCropHint,
             boolean allowBackup, @SetWallpaperFlags int which, int userId)
             throws IOException {
diff --git a/core/java/android/app/admin/DeviceAdminInfo.java b/core/java/android/app/admin/DeviceAdminInfo.java
index 5fe1af0..beb1c78 100644
--- a/core/java/android/app/admin/DeviceAdminInfo.java
+++ b/core/java/android/app/admin/DeviceAdminInfo.java
@@ -74,12 +74,10 @@
      * that the user can select, via {@link DevicePolicyManager#setPasswordQuality}
      * and {@link DevicePolicyManager#setPasswordMinimumLength}.
      *
-     * <p>To control this policy, the device admin must have a "limit-password"
-     * tag in the "uses-policies" section of its meta-data.
-     *
-     * <p>This policy is deprecated for use by a device admin.  In future releases, it will
-     * only be possible for a device owner or profile owner to enforce constraints on user
-     * passwords.
+     * <p>To control this policy, the device admin must be a device owner or profile owner,
+     * and must have a "limit-password" tag in the "uses-policies" section of its meta-data.
+     * If used by a device owner, the policy only affects the primary user and its profiles,
+     * but not any secondary users on the device.
      */
     public static final int USES_POLICY_LIMIT_PASSWORD = 0;
 
@@ -139,11 +137,10 @@
      * A type of policy that this device admin can use: force the user to
      * change their password after an administrator-defined time limit.
      *
-     * <p>To control this policy, the device admin must have an "expire-password"
-     * tag in the "uses-policies" section of its meta-data.
-     *
-     * <p>This policy is deprecated for use by a device admin.  In future releases, it will
-     * only be possible for a device owner or profile owner to enforce password expiry.
+     * <p>To control this policy, the device admin must be a device owner or profile owner,
+     * and must have an "expire-password" tag in the "uses-policies" section of its meta-data.
+     * If used by a device owner, the policy only affects the primary user and its profiles,
+     * but not any secondary users on the device.
      */
     public static final int USES_POLICY_EXPIRE_PASSWORD = 6;
 
@@ -158,23 +155,19 @@
     /**
      * A type of policy that this device admin can use: disables use of all device cameras.
      *
-     * <p>To control this policy, the device admin must have a "disable-camera"
-     * tag in the "uses-policies" section of its meta-data.
-     *
-     * <p>This policy is deprecated for use by a device admin.  In future releases, it will
-     * only be possible for a device owner or profile owner to disable use of the camera.
+     * <p>To control this policy, the device admin must be a device owner or profile owner,
+     * and must have a "disable-camera" tag in the "uses-policies" section of its meta-data.
+     * If used by a device owner, the policy affects all users on the device.
      */
     public static final int USES_POLICY_DISABLE_CAMERA = 8;
 
     /**
      * A type of policy that this device admin can use: disables use of keyguard features.
      *
-     * <p>To control this policy, the device admin must have a "disable-keyguard-features"
-     * tag in the "uses-policies" section of its meta-data.
-     *
-     * <p>This policy is deprecated for use by a device admin.  In future releases, it will
-     * only be possible for a device owner or profile owner to disable use of keyguard
-     * features.
+     * <p>To control this policy, the device admin must be a device owner or profile owner,
+     * and must have a "disable-keyguard-features" tag in the "uses-policies" section of its
+     * meta-data.  If used by a device owner, the policy only affects the primary user and
+     * its profiles, but not any secondary users on the device.
      */
     public static final int USES_POLICY_DISABLE_KEYGUARD_FEATURES = 9;
 
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index d1ecf1e..bd7a2dd 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -1183,14 +1183,6 @@
     public static final String POLICY_DISABLE_SCREEN_CAPTURE = "policy_disable_screen_capture";
 
     /**
-     * Constant to indicate the feature of mandatory backups. Used as argument to
-     * {@link #createAdminSupportIntent(String)}.
-     * @see #setMandatoryBackupTransport(ComponentName, ComponentName)
-     * @hide
-     */
-    public static final String POLICY_MANDATORY_BACKUPS = "policy_mandatory_backups";
-
-    /**
      * Constant to indicate the feature of suspending app. Use it as the value of
      * {@link #EXTRA_RESTRICTION}.
      * @hide
@@ -1200,8 +1192,7 @@
     /**
      * A String indicating a specific restricted feature. Can be a user restriction from the
      * {@link UserManager}, e.g. {@link UserManager#DISALLOW_ADJUST_VOLUME}, or one of the values
-     * {@link #POLICY_DISABLE_CAMERA}, {@link #POLICY_DISABLE_SCREEN_CAPTURE} or
-     * {@link #POLICY_MANDATORY_BACKUPS}.
+     * {@link #POLICY_DISABLE_CAMERA} or {@link #POLICY_DISABLE_SCREEN_CAPTURE}.
      * @see #createAdminSupportIntent(String)
      * @hide
      */
@@ -6919,7 +6910,7 @@
      * @param restriction Indicates for which feature the dialog should be displayed. Can be a
      *            user restriction from {@link UserManager}, e.g.
      *            {@link UserManager#DISALLOW_ADJUST_VOLUME}, or one of the constants
-     *            {@link #POLICY_DISABLE_CAMERA}, {@link #POLICY_DISABLE_SCREEN_CAPTURE}.
+     *            {@link #POLICY_DISABLE_CAMERA} or {@link #POLICY_DISABLE_SCREEN_CAPTURE}.
      * @return Intent An intent to be used to start the dialog-activity if the restriction is
      *            set by an admin, or null if the restriction does not exist or no admin set it.
      */
@@ -8917,55 +8908,6 @@
     }
 
     /**
-     * Makes backups mandatory and enforces the usage of the specified backup transport.
-     *
-     * <p>When a {@code null} backup transport is specified, backups are made optional again.
-     * <p>Only device owner can call this method.
-     * <p>If backups were disabled and a non-null backup transport {@link ComponentName} is
-     * specified, backups will be enabled.
-     * <p> If the backup service is disabled after the mandatory backup transport has been set, the
-     * mandatory backup transport is cleared.
-     *
-     * <p>NOTE: The method shouldn't be called on the main thread.
-     *
-     * @param admin admin Which {@link DeviceAdminReceiver} this request is associated with.
-     * @param backupTransportComponent The backup transport layer to be used for mandatory backups.
-     * @return {@code true} if the backup transport was successfully set; {@code false} otherwise.
-     * @throws SecurityException if {@code admin} is not a device owner.
-     * @hide
-     */
-    @WorkerThread
-    public boolean setMandatoryBackupTransport(
-            @NonNull ComponentName admin,
-            @Nullable ComponentName backupTransportComponent) {
-        throwIfParentInstance("setMandatoryBackupTransport");
-        try {
-            return mService.setMandatoryBackupTransport(admin, backupTransportComponent);
-        } catch (RemoteException re) {
-            throw re.rethrowFromSystemServer();
-        }
-    }
-
-    /**
-     * Returns the backup transport which has to be used for backups if backups are mandatory or
-     * {@code null} if backups are not mandatory.
-     *
-     * @return a {@link ComponentName} of the backup transport layer to be used if backups are
-     *         mandatory or {@code null} if backups are not mandatory.
-     * @hide
-     */
-    @UnsupportedAppUsage
-    public ComponentName getMandatoryBackupTransport() {
-        throwIfParentInstance("getMandatoryBackupTransport");
-        try {
-            return mService.getMandatoryBackupTransport();
-        } catch (RemoteException re) {
-            throw re.rethrowFromSystemServer();
-        }
-    }
-
-
-    /**
      * Called by a device owner to control the network logging feature.
      *
      * <p> Network logs contain DNS lookup and connect() library call events. The following library
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 6a5f3de..35ea250 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -362,8 +362,6 @@
 
     void setBackupServiceEnabled(in ComponentName admin, boolean enabled);
     boolean isBackupServiceEnabled(in ComponentName admin);
-    boolean setMandatoryBackupTransport(in ComponentName admin, in ComponentName backupTransportComponent);
-    ComponentName getMandatoryBackupTransport();
 
     void setNetworkLoggingEnabled(in ComponentName admin, boolean enabled);
     boolean isNetworkLoggingEnabled(in ComponentName admin);
diff --git a/core/java/android/app/backup/BackupAgent.java b/core/java/android/app/backup/BackupAgent.java
index 097dd9c..df27d58 100644
--- a/core/java/android/app/backup/BackupAgent.java
+++ b/core/java/android/app/backup/BackupAgent.java
@@ -126,6 +126,11 @@
     private static final boolean DEBUG = false;
 
     /** @hide */
+    public static final int RESULT_SUCCESS = 0;
+    /** @hide */
+    public static final int RESULT_ERROR = -1;
+
+    /** @hide */
     public static final int TYPE_EOF = 0;
 
     /**
@@ -955,8 +960,10 @@
             BackupDataOutput output = new BackupDataOutput(
                     data.getFileDescriptor(), quotaBytes, transportFlags);
 
+            long result = RESULT_ERROR;
             try {
                 BackupAgent.this.onBackup(oldState, output, newState);
+                result = RESULT_SUCCESS;
             } catch (IOException ex) {
                 Log.d(TAG, "onBackup (" + BackupAgent.this.getClass().getName() + ") threw", ex);
                 throw new RuntimeException(ex);
@@ -971,9 +978,9 @@
 
                 Binder.restoreCallingIdentity(ident);
                 try {
-                    callbackBinder.operationComplete(0);
+                    callbackBinder.operationComplete(result);
                 } catch (RemoteException e) {
-                    // we'll time out anyway, so we're safe
+                    // We will time out anyway.
                 }
 
                 // Don't close the fd out from under the system service if this was local
@@ -1155,10 +1162,16 @@
         }
 
         @Override
-        public void doQuotaExceeded(long backupDataBytes, long quotaBytes) {
+        public void doQuotaExceeded(
+                long backupDataBytes,
+                long quotaBytes,
+                IBackupCallback callbackBinder) {
             long ident = Binder.clearCallingIdentity();
+
+            long result = RESULT_ERROR;
             try {
                 BackupAgent.this.onQuotaExceeded(backupDataBytes, quotaBytes);
+                result = RESULT_SUCCESS;
             } catch (Exception e) {
                 Log.d(TAG, "onQuotaExceeded(" + BackupAgent.this.getClass().getName() + ") threw",
                         e);
@@ -1166,6 +1179,12 @@
             } finally {
                 waitForSharedPrefs();
                 Binder.restoreCallingIdentity(ident);
+
+                try {
+                    callbackBinder.operationComplete(result);
+                } catch (RemoteException e) {
+                    // We will time out anyway.
+                }
             }
         }
     }
diff --git a/core/java/android/app/backup/IBackupManager.aidl b/core/java/android/app/backup/IBackupManager.aidl
index 1c55d8a..3e20748 100644
--- a/core/java/android/app/backup/IBackupManager.aidl
+++ b/core/java/android/app/backup/IBackupManager.aidl
@@ -299,8 +299,7 @@
      *
      * @param transport ComponentName of the service hosting the transport. This is different from
      *                  the transport's name that is returned by {@link BackupTransport#name()}.
-     * @param listener A listener object to get a callback on the transport being selected. It may
-     *                 be {@code null}.
+     * @param listener A listener object to get a callback on the transport being selected.
      */
     void selectBackupTransportAsync(in ComponentName transport, ISelectBackupTransportCallback listener);
 
diff --git a/core/java/android/app/job/JobInfo.java b/core/java/android/app/job/JobInfo.java
index 9baa16f..556ffa24 100644
--- a/core/java/android/app/job/JobInfo.java
+++ b/core/java/android/app/job/JobInfo.java
@@ -36,6 +36,7 @@
 import android.net.NetworkSpecifier;
 import android.net.Uri;
 import android.os.BaseBundle;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -311,7 +312,7 @@
     private final long initialBackoffMillis;
     private final int backoffPolicy;
     private final int priority;
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private final int flags;
 
     /**
diff --git a/core/java/android/app/usage/UsageStatsManager.java b/core/java/android/app/usage/UsageStatsManager.java
index 0994332..dbb00eb 100644
--- a/core/java/android/app/usage/UsageStatsManager.java
+++ b/core/java/android/app/usage/UsageStatsManager.java
@@ -25,6 +25,7 @@
 import android.app.PendingIntent;
 import android.content.Context;
 import android.content.pm.ParceledListSlice;
+import android.os.Build;
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.util.ArrayMap;
@@ -235,7 +236,7 @@
     @UnsupportedAppUsage
     private static final UsageEvents sEmptyResults = new UsageEvents();
 
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private final Context mContext;
     @UnsupportedAppUsage
     private final IUsageStatsManager mService;
diff --git a/core/java/android/appwidget/AppWidgetProviderInfo.java b/core/java/android/appwidget/AppWidgetProviderInfo.java
index 53315cc..d148afb 100644
--- a/core/java/android/appwidget/AppWidgetProviderInfo.java
+++ b/core/java/android/appwidget/AppWidgetProviderInfo.java
@@ -400,7 +400,7 @@
         that.initialLayout = this.initialLayout;
         that.initialKeyguardLayout = this.initialKeyguardLayout;
         that.configure = this.configure == null ? null : this.configure.clone();
-        that.label = this.label == null ? null : this.label.substring(0);
+        that.label = this.label;
         that.icon = this.icon;
         that.previewImage = this.previewImage;
         that.autoAdvanceViewId = this.autoAdvanceViewId;
diff --git a/core/java/android/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java
index d21f76d..466b9ce 100644
--- a/core/java/android/bluetooth/BluetoothA2dp.java
+++ b/core/java/android/bluetooth/BluetoothA2dp.java
@@ -27,6 +27,7 @@
 import android.content.Intent;
 import android.content.ServiceConnection;
 import android.os.Binder;
+import android.os.Build;
 import android.os.IBinder;
 import android.os.ParcelUuid;
 import android.os.RemoteException;
@@ -571,7 +572,7 @@
      * @hide
      */
     @RequiresPermission(Manifest.permission.BLUETOOTH)
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     public int getPriority(BluetoothDevice device) {
         if (VDBG) log("getPriority(" + device + ")");
         try {
diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java
index 78248ef..29d5a1c 100644
--- a/core/java/android/bluetooth/BluetoothGatt.java
+++ b/core/java/android/bluetooth/BluetoothGatt.java
@@ -17,6 +17,7 @@
 package android.bluetooth;
 
 import android.annotation.UnsupportedAppUsage;
+import android.os.Build;
 import android.os.Handler;
 import android.os.ParcelUuid;
 import android.os.RemoteException;
@@ -52,7 +53,7 @@
     private BluetoothDevice mDevice;
     @UnsupportedAppUsage
     private boolean mAutoConnect;
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private int mAuthRetryState;
     private int mConnState;
     private final Object mStateLock = new Object();
diff --git a/core/java/android/bluetooth/BluetoothProfile.java b/core/java/android/bluetooth/BluetoothProfile.java
index 9777b5c..3c3a01b 100644
--- a/core/java/android/bluetooth/BluetoothProfile.java
+++ b/core/java/android/bluetooth/BluetoothProfile.java
@@ -21,6 +21,7 @@
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.annotation.UnsupportedAppUsage;
+import android.os.Build;
 
 import java.util.List;
 
@@ -86,7 +87,7 @@
      *
      * @hide
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     int PAN = 5;
 
     /**
diff --git a/core/java/android/content/BroadcastReceiver.java b/core/java/android/content/BroadcastReceiver.java
index b55fe76..8691ed4 100644
--- a/core/java/android/content/BroadcastReceiver.java
+++ b/core/java/android/content/BroadcastReceiver.java
@@ -21,6 +21,7 @@
 import android.app.ActivityThread;
 import android.app.IActivityManager;
 import android.app.QueuedWork;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.RemoteException;
@@ -71,22 +72,22 @@
         /** @hide */
         public static final int TYPE_UNREGISTERED = 2;
 
-        @UnsupportedAppUsage
+        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
         final int mType;
         @UnsupportedAppUsage
         final boolean mOrderedHint;
         @UnsupportedAppUsage
         final boolean mInitialStickyHint;
-        @UnsupportedAppUsage
+        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
         final IBinder mToken;
         @UnsupportedAppUsage
         final int mSendingUser;
-        @UnsupportedAppUsage
+        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
         final int mFlags;
 
-        @UnsupportedAppUsage
+        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
         int mResultCode;
-        @UnsupportedAppUsage
+        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
         String mResultData;
         @UnsupportedAppUsage
         Bundle mResultExtras;
@@ -96,7 +97,7 @@
         boolean mFinished;
 
         /** @hide */
-        @UnsupportedAppUsage
+        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
         public PendingResult(int resultCode, String resultData, Bundle resultExtras, int type,
                 boolean ordered, boolean sticky, IBinder token, int userId, int flags) {
             mResultCode = resultCode;
diff --git a/core/java/android/content/ClipData.java b/core/java/android/content/ClipData.java
index 2b7ea66..089cf10 100644
--- a/core/java/android/content/ClipData.java
+++ b/core/java/android/content/ClipData.java
@@ -25,6 +25,7 @@
 import android.content.res.AssetFileDescriptor;
 import android.graphics.Bitmap;
 import android.net.Uri;
+import android.os.Build;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.StrictMode;
@@ -198,7 +199,7 @@
         final CharSequence mText;
         final String mHtmlText;
         final Intent mIntent;
-        @UnsupportedAppUsage
+        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
         Uri mUri;
 
         /** @hide */
diff --git a/core/java/android/content/ComponentCallbacks.java b/core/java/android/content/ComponentCallbacks.java
index b96c8d3..428545d 100644
--- a/core/java/android/content/ComponentCallbacks.java
+++ b/core/java/android/content/ComponentCallbacks.java
@@ -16,6 +16,7 @@
 
 package android.content;
 
+import android.annotation.NonNull;
 import android.content.res.Configuration;
 
 /**
@@ -44,7 +45,7 @@
      *
      * @param newConfig The new device configuration.
      */
-    void onConfigurationChanged(Configuration newConfig);
+    void onConfigurationChanged(@NonNull Configuration newConfig);
 
     /**
      * This is called when the overall system is running low on memory, and
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index f5339ef..bd1e6a4 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -37,6 +37,7 @@
 import android.net.Uri;
 import android.os.AsyncTask;
 import android.os.Binder;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.CancellationSignal;
 import android.os.IBinder;
@@ -163,7 +164,7 @@
      * in the test, which is available via {@link #getPathPermissions()}.
      * @hide
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     public ContentProvider(
             Context context,
             String readPermission,
diff --git a/core/java/android/content/ContentProviderClient.java b/core/java/android/content/ContentProviderClient.java
index 04be572..d315f49 100644
--- a/core/java/android/content/ContentProviderClient.java
+++ b/core/java/android/content/ContentProviderClient.java
@@ -24,6 +24,7 @@
 import android.database.Cursor;
 import android.net.Uri;
 import android.os.Binder;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.CancellationSignal;
 import android.os.DeadObjectException;
@@ -73,7 +74,7 @@
     private final ContentResolver mContentResolver;
     @UnsupportedAppUsage
     private final IContentProvider mContentProvider;
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private final String mPackageName;
     private final boolean mStable;
 
diff --git a/core/java/android/content/ContentUris.java b/core/java/android/content/ContentUris.java
index dbe8a7c..fd7b372 100644
--- a/core/java/android/content/ContentUris.java
+++ b/core/java/android/content/ContentUris.java
@@ -18,6 +18,8 @@
 
 import android.net.Uri;
 
+import java.util.List;
+
 /**
 * Utility methods useful for working with {@link android.net.Uri} objects
 * that use the &quot;content&quot; (content://) scheme.
@@ -109,4 +111,30 @@
     public static Uri withAppendedId(Uri contentUri, long id) {
         return appendId(contentUri.buildUpon(), id).build();
     }
+
+    /**
+     * Removes any ID from the end of the path.
+     *
+     * @param contentUri that ends with an ID
+     * @return a new URI with the ID removed from the end of the path
+     * @throws IllegalArgumentException when the given URI has no ID to remove
+     *             from the end of the path
+     */
+    public static Uri removeId(Uri contentUri) {
+        // Verify that we have a valid ID to actually remove
+        final String last = contentUri.getLastPathSegment();
+        if (last == null) {
+            throw new IllegalArgumentException("No path segments to remove");
+        } else {
+            Long.parseLong(last);
+        }
+
+        final List<String> segments = contentUri.getPathSegments();
+        final Uri.Builder builder = contentUri.buildUpon();
+        builder.path(null);
+        for (int i = 0; i < segments.size() - 1; i++) {
+            builder.appendPath(segments.get(i));
+        }
+        return builder.build();
+    }
 }
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index ddd12a5..f929545 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -3407,7 +3407,7 @@
 
     /**
      * Use with {@link #getSystemService(String)} to retrieve a
-     * {@link android.app.NotificationManager} for controlling keyguard.
+     * {@link android.app.KeyguardManager} for controlling keyguard.
      *
      * @see #getSystemService(String)
      * @see android.app.KeyguardManager
@@ -3431,7 +3431,7 @@
      *
      * @hide
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     public static final String COUNTRY_DETECTOR = "country_detector";
 
     /**
@@ -4792,6 +4792,7 @@
      * @hide
      */
     @SystemApi
+    @TestApi
     public Context createPackageContextAsUser(
             String packageName, @CreatePackageOptions int flags, UserHandle user)
             throws PackageManager.NameNotFoundException {
diff --git a/core/java/android/content/IContentProvider.java b/core/java/android/content/IContentProvider.java
index d814e67..044ed61 100644
--- a/core/java/android/content/IContentProvider.java
+++ b/core/java/android/content/IContentProvider.java
@@ -21,6 +21,7 @@
 import android.content.res.AssetFileDescriptor;
 import android.database.Cursor;
 import android.net.Uri;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.ICancellationSignal;
@@ -80,7 +81,7 @@
             Bundle opts, ICancellationSignal signal) throws RemoteException, FileNotFoundException;
 
     /* IPC constants */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     static final String descriptor = "android.content.IContentProvider";
 
     @UnsupportedAppUsage
diff --git a/core/java/android/content/IntentFilter.java b/core/java/android/content/IntentFilter.java
index 212e132..0dd6186 100644
--- a/core/java/android/content/IntentFilter.java
+++ b/core/java/android/content/IntentFilter.java
@@ -20,6 +20,7 @@
 import android.annotation.SystemApi;
 import android.annotation.UnsupportedAppUsage;
 import android.net.Uri;
+import android.os.Build;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.PatternMatcher;
@@ -655,7 +656,7 @@
      *
      * @hide
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     public final boolean isVerified() {
         if ((mVerifyState & STATE_NEED_VERIFY_CHECKED) == STATE_NEED_VERIFY_CHECKED) {
             return ((mVerifyState & STATE_NEED_VERIFY) == STATE_NEED_VERIFY);
diff --git a/core/java/android/content/RestrictionsManager.java b/core/java/android/content/RestrictionsManager.java
index 33395ec..bbdab04 100644
--- a/core/java/android/content/RestrictionsManager.java
+++ b/core/java/android/content/RestrictionsManager.java
@@ -25,6 +25,7 @@
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.res.TypedArray;
 import android.content.res.XmlResourceParser;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.PersistableBundle;
 import android.os.RemoteException;
@@ -403,7 +404,7 @@
     private static final String TAG_RESTRICTION = "restriction";
 
     private final Context mContext;
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private final IRestrictionsManager mService;
 
     /**
diff --git a/core/java/android/content/SyncRequest.java b/core/java/android/content/SyncRequest.java
index fd12d7a..c18b282 100644
--- a/core/java/android/content/SyncRequest.java
+++ b/core/java/android/content/SyncRequest.java
@@ -18,6 +18,7 @@
 
 import android.accounts.Account;
 import android.annotation.UnsupportedAppUsage;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -33,10 +34,10 @@
     @UnsupportedAppUsage
     private final Account mAccountToSync;
     /** Authority string that corresponds to a ContentProvider. */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private final String mAuthority;
     /** Bundle containing user info as well as sync settings. */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private final Bundle mExtras;
     /** Don't allow this sync request on metered networks. */
     private final boolean mDisallowMetered;
diff --git a/core/java/android/content/pm/AndroidHidlUpdater.java b/core/java/android/content/pm/AndroidHidlUpdater.java
new file mode 100644
index 0000000..69cc94f
--- /dev/null
+++ b/core/java/android/content/pm/AndroidHidlUpdater.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 android.content.pm;
+
+import static android.content.pm.SharedLibraryNames.ANDROID_HIDL_BASE;
+import static android.content.pm.SharedLibraryNames.ANDROID_HIDL_MANAGER;
+
+import android.content.pm.PackageParser.Package;
+import android.os.Build;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+/**
+ * Updates a package to ensure that if it targets <= P that the android.hidl.base-V1.0-java
+ * and android.hidl.manager-V1.0-java libraries are included by default.
+ *
+ * @hide
+ */
+@VisibleForTesting
+public class AndroidHidlUpdater extends PackageSharedLibraryUpdater {
+
+    @Override
+    public void updatePackage(Package pkg) {
+        // This was the default <= P and is maintained for backwards compatibility.
+        if (pkg.applicationInfo.targetSdkVersion <= Build.VERSION_CODES.P) {
+            prefixRequiredLibrary(pkg, ANDROID_HIDL_BASE);
+            prefixRequiredLibrary(pkg, ANDROID_HIDL_MANAGER);
+        }
+    }
+}
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 1108f93..225b6cf 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -615,6 +615,13 @@
     public static final int PRIVATE_FLAG_PRODUCT = 1 << 19;
 
     /**
+     * Value for {@link #privateFlags}: whether this app is signed with the
+     * platform key.
+     * @hide
+     */
+    public static final int PRIVATE_FLAG_SIGNED_WITH_PLATFORM_KEY = 1 << 20;
+
+    /**
      * Value for {@link #privateFlags}: whether this app is pre-installed on the
      * google partition of the system image.
      * @hide
@@ -622,11 +629,11 @@
     public static final int PRIVATE_FLAG_PRODUCT_SERVICES = 1 << 21;
 
     /**
-     * Value for {@link #privateFlags}: whether this app is signed with the
-     * platform key.
+     * Indicates whether this package requires access to non-SDK APIs.
+     * Only system apps and tests are allowed to use this property.
      * @hide
      */
-    public static final int PRIVATE_FLAG_SIGNED_WITH_PLATFORM_KEY = 1 << 20;
+    public static final int PRIVATE_FLAG_USES_NON_SDK_API = 1 << 22;
 
     /** @hide */
     @IntDef(flag = true, prefix = { "PRIVATE_FLAG_" }, value = {
@@ -1009,13 +1016,6 @@
     public String appComponentFactory;
 
     /**
-     * Indicates whether this package requires access to non-SDK APIs. Only system apps
-     * and tests are allowed to use this property.
-     * @hide
-     */
-    public boolean usesNonSdkApi;
-
-    /**
      * The category of this app. Categories are used to cluster multiple apps
      * together into meaningful groups, such as when summarizing battery,
      * network, or disk usage. Apps should only define this value when they fit
@@ -1294,6 +1294,7 @@
                 pw.println(prefix + "category=" + category);
             }
             pw.println(prefix + "HiddenApiEnforcementPolicy=" + getHiddenApiEnforcementPolicy());
+            pw.println(prefix + "usesNonSdkApi=" + usesNonSdkApi());
         }
         super.dumpBack(pw, prefix);
     }
@@ -1718,11 +1719,18 @@
         return SystemConfig.getInstance().getHiddenApiWhitelistedApps().contains(packageName);
     }
 
+    /**
+     * @hide
+     */
+    public boolean usesNonSdkApi() {
+        return (privateFlags & PRIVATE_FLAG_USES_NON_SDK_API) != 0;
+    }
+
     private boolean isAllowedToUseHiddenApis() {
         if (isSignedWithPlatformKey()) {
             return true;
         } else if (isSystemApp() || isUpdatedSystemApp()) {
-            return usesNonSdkApi || isPackageWhitelistedForHiddenApis();
+            return usesNonSdkApi() || isPackageWhitelistedForHiddenApis();
         } else {
             return false;
         }
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index 46877ca..44e652f 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -42,6 +42,7 @@
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.Icon;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
@@ -136,7 +137,7 @@
             "android.content.pm.extra.PIN_ITEM_REQUEST";
 
     private final Context mContext;
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private final ILauncherApps mService;
     @UnsupportedAppUsage
     private final PackageManager mPm;
diff --git a/core/java/android/content/pm/PackageBackwardCompatibility.java b/core/java/android/content/pm/PackageBackwardCompatibility.java
index a16f81b..03eefed 100644
--- a/core/java/android/content/pm/PackageBackwardCompatibility.java
+++ b/core/java/android/content/pm/PackageBackwardCompatibility.java
@@ -53,6 +53,8 @@
                 "android.content.pm.OrgApacheHttpLegacyUpdater",
                 RemoveUnnecessaryOrgApacheHttpLegacyLibrary::new);
 
+        packageUpdaters.add(new AndroidHidlUpdater());
+
         // Add this before adding AndroidTestBaseUpdater so that android.test.base comes before
         // android.test.mock.
         packageUpdaters.add(new AndroidTestRunnerSplitUpdater());
diff --git a/core/java/android/content/pm/PackageInfo.java b/core/java/android/content/pm/PackageInfo.java
index d9d1777..9e20503 100644
--- a/core/java/android/content/pm/PackageInfo.java
+++ b/core/java/android/content/pm/PackageInfo.java
@@ -234,7 +234,7 @@
     /**
      * Array of all signatures read from the package file. This is only filled
      * in if the flag {@link PackageManager#GET_SIGNATURES} was set. A package
-     * must be singed with at least one certificate which is at position zero.
+     * must be signed with at least one certificate which is at position zero.
      * The package can be signed with additional certificates which appear as
      * subsequent entries.
      *
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 316ace1..c901ba3 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -32,6 +32,7 @@
 import android.content.pm.PackageManager.InstallReason;
 import android.graphics.Bitmap;
 import android.net.Uri;
+import android.os.Build;
 import android.os.FileBridge;
 import android.os.Handler;
 import android.os.Looper;
@@ -1091,7 +1092,7 @@
         public static final int UID_UNKNOWN = -1;
 
         /** {@hide} */
-        @UnsupportedAppUsage
+        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
         public int mode = MODE_INVALID;
         /** {@hide} */
         @UnsupportedAppUsage
@@ -1104,13 +1105,13 @@
         @UnsupportedAppUsage
         public long sizeBytes = -1;
         /** {@hide} */
-        @UnsupportedAppUsage
+        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
         public String appPackageName;
         /** {@hide} */
         @UnsupportedAppUsage
         public Bitmap appIcon;
         /** {@hide} */
-        @UnsupportedAppUsage
+        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
         public String appLabel;
         /** {@hide} */
         public long appIconLastModified = -1;
@@ -1435,40 +1436,40 @@
     public static class SessionInfo implements Parcelable {
 
         /** {@hide} */
-        @UnsupportedAppUsage
+        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
         public int sessionId;
         /** {@hide} */
-        @UnsupportedAppUsage
+        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
         public String installerPackageName;
         /** {@hide} */
         @UnsupportedAppUsage
         public String resolvedBaseCodePath;
         /** {@hide} */
-        @UnsupportedAppUsage
+        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
         public float progress;
         /** {@hide} */
         @UnsupportedAppUsage
         public boolean sealed;
         /** {@hide} */
-        @UnsupportedAppUsage
+        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
         public boolean active;
 
         /** {@hide} */
-        @UnsupportedAppUsage
+        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
         public int mode;
         /** {@hide} */
         public @InstallReason int installReason;
         /** {@hide} */
-        @UnsupportedAppUsage
+        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
         public long sizeBytes;
         /** {@hide} */
-        @UnsupportedAppUsage
+        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
         public String appPackageName;
         /** {@hide} */
-        @UnsupportedAppUsage
+        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
         public Bitmap appIcon;
         /** {@hide} */
-        @UnsupportedAppUsage
+        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
         public CharSequence appLabel;
 
         /** {@hide} */
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 7d8ff4c..1b4878c 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -2274,7 +2274,6 @@
     /**
      * Feature for {@link #getSystemAvailableFeatures} and
      * {@link #hasSystemFeature}: The device has biometric hardware to perform face authentication.
-     * @hide
      */
     @SdkConstant(SdkConstantType.FEATURE)
     public static final String FEATURE_FACE = "android.hardware.face";
@@ -2282,7 +2281,6 @@
     /**
      * Feature for {@link #getSystemAvailableFeatures} and
      * {@link #hasSystemFeature}: The device has biometric hardware to perform iris authentication.
-     * @hide
      */
     @SdkConstant(SdkConstantType.FEATURE)
     public static final String FEATURE_IRIS = "android.hardware.iris";
@@ -3278,11 +3276,14 @@
             @PermissionInfoFlags int flags) throws NameNotFoundException;
 
     /**
-     * Returns true if some permissions are individually controlled
+     * Returns true if some permissions are individually controlled.
+     *
+     * <p>The user usually grants and revokes permission-groups. If this option is set some
+     * dangerous system permissions can be revoked/granted by the user separately from their group.
      *
      * @hide
      */
-    @TestApi
+    @TestApi @SystemApi
     public abstract boolean arePermissionsIndividuallyControlled();
 
     /**
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 8b058dc..03a3d1f 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -1902,7 +1902,7 @@
      * @throws XmlPullParserException
      * @throws IOException
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private Package parseBaseApk(String apkPath, Resources res, XmlResourceParser parser, int flags,
             String[] outError) throws XmlPullParserException, IOException {
         final String splitName;
@@ -3659,8 +3659,10 @@
             ai.appComponentFactory = buildClassName(ai.packageName, factory, outError);
         }
 
-        ai.usesNonSdkApi = sa.getBoolean(
-                com.android.internal.R.styleable.AndroidManifestApplication_usesNonSdkApi, false);
+        if (sa.getBoolean(
+                com.android.internal.R.styleable.AndroidManifestApplication_usesNonSdkApi, false)) {
+            ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_USES_NON_SDK_API;
+        }
 
         if (outError[0] == null) {
             CharSequence pname;
diff --git a/core/java/android/content/pm/ParceledListSlice.java b/core/java/android/content/pm/ParceledListSlice.java
index 2eef165..dccc524 100644
--- a/core/java/android/content/pm/ParceledListSlice.java
+++ b/core/java/android/content/pm/ParceledListSlice.java
@@ -17,6 +17,7 @@
 package android.content.pm;
 
 import android.annotation.UnsupportedAppUsage;
+import android.os.Build;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -72,7 +73,7 @@
     }
 
     @SuppressWarnings("unchecked")
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     public static final Parcelable.ClassLoaderCreator<ParceledListSlice> CREATOR =
             new Parcelable.ClassLoaderCreator<ParceledListSlice>() {
         public ParceledListSlice createFromParcel(Parcel in) {
diff --git a/core/java/android/content/pm/SharedLibraryNames.java b/core/java/android/content/pm/SharedLibraryNames.java
index 83e8663..387d29e8 100644
--- a/core/java/android/content/pm/SharedLibraryNames.java
+++ b/core/java/android/content/pm/SharedLibraryNames.java
@@ -22,6 +22,10 @@
  */
 public class SharedLibraryNames {
 
+    static final String ANDROID_HIDL_BASE = "android.hidl.base-V1.0-java";
+
+    static final String ANDROID_HIDL_MANAGER = "android.hidl.manager-V1.0-java";
+
     static final String ANDROID_TEST_BASE = "android.test.base";
 
     static final String ANDROID_TEST_MOCK = "android.test.mock";
diff --git a/core/java/android/content/pm/ShortcutInfo.java b/core/java/android/content/pm/ShortcutInfo.java
index 546c213..ec2e2fd 100644
--- a/core/java/android/content/pm/ShortcutInfo.java
+++ b/core/java/android/content/pm/ShortcutInfo.java
@@ -30,6 +30,7 @@
 import android.content.res.Resources.NotFoundException;
 import android.graphics.Bitmap;
 import android.graphics.drawable.Icon;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -1243,7 +1244,7 @@
      * @hide
      */
     @Nullable
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     public Icon getIcon() {
         return mIcon;
     }
diff --git a/core/java/android/content/pm/ShortcutManager.java b/core/java/android/content/pm/ShortcutManager.java
index 60ac1f0..2d59003 100644
--- a/core/java/android/content/pm/ShortcutManager.java
+++ b/core/java/android/content/pm/ShortcutManager.java
@@ -26,6 +26,7 @@
 import android.content.Intent;
 import android.content.IntentSender;
 import android.graphics.drawable.AdaptiveIconDrawable;
+import android.os.Build;
 import android.os.Build.VERSION_CODES;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -55,7 +56,7 @@
     private static final String TAG = "ShortcutManager";
 
     private final Context mContext;
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private final IShortcutService mService;
 
     /**
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index f7aea97..121b432 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -1096,7 +1096,9 @@
         protoOutputStream.write(FONT_SCALE, fontScale);
         protoOutputStream.write(MCC, mcc);
         protoOutputStream.write(MNC, mnc);
-        mLocaleList.writeToProto(protoOutputStream, LOCALES);
+        if (mLocaleList != null) {
+            mLocaleList.writeToProto(protoOutputStream, LOCALES);
+        }
         protoOutputStream.write(SCREEN_LAYOUT, screenLayout);
         protoOutputStream.write(COLOR_MODE, colorMode);
         protoOutputStream.write(TOUCHSCREEN, touchscreen);
@@ -1111,7 +1113,9 @@
         protoOutputStream.write(SCREEN_HEIGHT_DP, screenHeightDp);
         protoOutputStream.write(SMALLEST_SCREEN_WIDTH_DP, smallestScreenWidthDp);
         protoOutputStream.write(DENSITY_DPI, densityDpi);
-        windowConfiguration.writeToProto(protoOutputStream, WINDOW_CONFIGURATION);
+        if (windowConfiguration != null) {
+            windowConfiguration.writeToProto(protoOutputStream, WINDOW_CONFIGURATION);
+        }
         protoOutputStream.end(token);
     }
 
@@ -2072,17 +2076,6 @@
                 break;
         }
 
-        switch (config.colorMode & Configuration.COLOR_MODE_HDR_MASK) {
-            case Configuration.COLOR_MODE_HDR_YES:
-                parts.add("highdr");
-                break;
-            case Configuration.COLOR_MODE_HDR_NO:
-                parts.add("lowdr");
-                break;
-            default:
-                break;
-        }
-
         switch (config.colorMode & Configuration.COLOR_MODE_WIDE_COLOR_GAMUT_MASK) {
             case Configuration.COLOR_MODE_WIDE_COLOR_GAMUT_YES:
                 parts.add("widecg");
@@ -2094,6 +2087,17 @@
                 break;
         }
 
+        switch (config.colorMode & Configuration.COLOR_MODE_HDR_MASK) {
+            case Configuration.COLOR_MODE_HDR_YES:
+                parts.add("highdr");
+                break;
+            case Configuration.COLOR_MODE_HDR_NO:
+                parts.add("lowdr");
+                break;
+            default:
+                break;
+        }
+
         switch (config.orientation) {
             case Configuration.ORIENTATION_LANDSCAPE:
                 parts.add("land");
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index 43e1612..88b1c88 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -1129,10 +1129,8 @@
      *
      * @throws NotFoundException Throws NotFoundException if the given ID does
      *         not exist or is not a floating-point value.
-     * @hide Pending API council approval.
      */
-    @UnsupportedAppUsage
-    public float getFloat(int id) {
+    public float getFloat(@DimenRes int id) {
         final TypedValue value = obtainTempTypedValue();
         try {
             mResourcesImpl.getValue(id, value, true);
diff --git a/core/java/android/database/AbstractCursor.java b/core/java/android/database/AbstractCursor.java
index c6c2aa5..8bcaa45 100644
--- a/core/java/android/database/AbstractCursor.java
+++ b/core/java/android/database/AbstractCursor.java
@@ -19,6 +19,7 @@
 import android.annotation.UnsupportedAppUsage;
 import android.content.ContentResolver;
 import android.net.Uri;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.UserHandle;
 import android.util.Log;
@@ -79,7 +80,7 @@
     private final DataSetObservable mDataSetObservable = new DataSetObservable();
     private final ContentObservable mContentObservable = new ContentObservable();
 
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private Bundle mExtras = Bundle.EMPTY;
 
     /* -------------------------------------------------------- */
diff --git a/core/java/android/database/sqlite/SQLiteCustomFunction.java b/core/java/android/database/sqlite/SQLiteCustomFunction.java
index ec20458..41b78d3 100644
--- a/core/java/android/database/sqlite/SQLiteCustomFunction.java
+++ b/core/java/android/database/sqlite/SQLiteCustomFunction.java
@@ -17,6 +17,7 @@
 package android.database.sqlite;
 
 import android.annotation.UnsupportedAppUsage;
+import android.os.Build;
 
 /**
  * Describes a custom SQL function.
@@ -24,7 +25,7 @@
  * @hide
  */
 public final class SQLiteCustomFunction {
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     public final String name;
     @UnsupportedAppUsage
     public final int numArgs;
diff --git a/core/java/android/database/sqlite/SQLiteOpenHelper.java b/core/java/android/database/sqlite/SQLiteOpenHelper.java
index 1377806..19c6745 100644
--- a/core/java/android/database/sqlite/SQLiteOpenHelper.java
+++ b/core/java/android/database/sqlite/SQLiteOpenHelper.java
@@ -49,7 +49,7 @@
  * <p class="note"><strong>Note:</strong> this class assumes
  * monotonically increasing version numbers for upgrades.</p>
  */
-public abstract class SQLiteOpenHelper {
+public abstract class SQLiteOpenHelper implements AutoCloseable {
     private static final String TAG = SQLiteOpenHelper.class.getSimpleName();
 
     private final Context mContext;
diff --git a/core/java/android/database/sqlite/SQLiteQueryBuilder.java b/core/java/android/database/sqlite/SQLiteQueryBuilder.java
index b705ebb..4fce2d7 100644
--- a/core/java/android/database/sqlite/SQLiteQueryBuilder.java
+++ b/core/java/android/database/sqlite/SQLiteQueryBuilder.java
@@ -34,6 +34,7 @@
 
 import java.util.Arrays;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Objects;
@@ -50,6 +51,8 @@
             Pattern.compile("\\s*\\d+\\s*(,\\s*\\d+\\s*)?");
 
     private Map<String, String> mProjectionMap = null;
+    private List<Pattern> mProjectionGreylist = null;
+
     @UnsupportedAppUsage
     private String mTables = "";
     @UnsupportedAppUsage
@@ -164,6 +167,17 @@
     }
 
     /**
+     * Sets a projection greylist of columns that will be allowed through, even
+     * when {@link #setStrict(boolean)} is enabled. This provides a way for
+     * abusive custom columns like {@code COUNT(*)} to continue working.
+     *
+     * @hide
+     */
+    public void setProjectionGreylist(List<Pattern> projectionGreylist) {
+        mProjectionGreylist = projectionGreylist;
+    }
+
+    /**
      * Sets the cursor factory to be used for the query.  You can use
      * one factory for all queries on a database but it is normally
      * easier to specify the factory when doing this query.
@@ -809,6 +823,24 @@
                         continue;
                     }
 
+                    // If greylist is configured, we might be willing to let
+                    // this custom column bypass our strict checks.
+                    if (mProjectionGreylist != null) {
+                        boolean match = false;
+                        for (Pattern p : mProjectionGreylist) {
+                            if (p.matcher(userColumn).matches()) {
+                                match = true;
+                                break;
+                            }
+                        }
+
+                        if (match) {
+                            Log.w(TAG, "Allowing abusive custom column: " + userColumn);
+                            projection[i] = userColumn;
+                            continue;
+                        }
+                    }
+
                     throw new IllegalArgumentException("Invalid column "
                             + projectionIn[i]);
                 }
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index 8e96f56..ac863b2 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -31,6 +31,7 @@
 import android.graphics.SurfaceTexture;
 import android.media.AudioAttributes;
 import android.media.IAudioService;
+import android.os.Build;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
@@ -165,7 +166,7 @@
     private static final int CAMERA_MSG_PREVIEW_METADATA = 0x400;
     private static final int CAMERA_MSG_FOCUS_MOVE       = 0x800;
 
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private long mNativeContext; // accessed by native methods
     private EventHandler mEventHandler;
     private ShutterCallback mShutterCallback;
@@ -721,7 +722,7 @@
     /**
      * @hide
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     public native final void setPreviewSurface(Surface surface) throws IOException;
 
     /**
diff --git a/core/java/android/hardware/HardwareBuffer.java b/core/java/android/hardware/HardwareBuffer.java
index c17aabb..d2c0e7b 100644
--- a/core/java/android/hardware/HardwareBuffer.java
+++ b/core/java/android/hardware/HardwareBuffer.java
@@ -20,6 +20,7 @@
 import android.annotation.LongDef;
 import android.annotation.NonNull;
 import android.annotation.UnsupportedAppUsage;
+import android.os.Build;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -184,7 +185,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
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private HardwareBuffer(long nativeObject) {
         mNativeObject = nativeObject;
 
diff --git a/core/java/android/hardware/OWNERS b/core/java/android/hardware/OWNERS
index b8fea55..29a339a 100644
--- a/core/java/android/hardware/OWNERS
+++ b/core/java/android/hardware/OWNERS
@@ -1,7 +1,2 @@
 # Camera
-per-file *Camera* = cychen@google.com
-per-file *Camera* = epeev@google.com
-per-file *Camera* = etalvala@google.com
-per-file *Camera* = shuzhenwang@google.com
-per-file *Camera* = yinchiayeh@google.com
-per-file *Camera* = zhijunhe@google.com
+per-file *Camera* = cychen@google.com,epeev@google.com,etalvala@google.com,shuzhenwang@google.com,yinchiayeh@google.com,zhijunhe@google.com
diff --git a/core/java/android/hardware/biometrics/BiometricAuthenticator.java b/core/java/android/hardware/biometrics/BiometricAuthenticator.java
index 59195dc..dbb2527 100644
--- a/core/java/android/hardware/biometrics/BiometricAuthenticator.java
+++ b/core/java/android/hardware/biometrics/BiometricAuthenticator.java
@@ -30,6 +30,21 @@
 public interface BiometricAuthenticator {
 
     /**
+     * @hide
+     */
+    int TYPE_FINGERPRINT = 1;
+
+    /**
+     * @hide
+     */
+    int TYPE_IRIS = 2;
+
+    /**
+     * @hide
+     */
+    int TYPE_FACE = 3;
+
+    /**
      * Container for biometric data
      * @hide
      */
@@ -196,6 +211,22 @@
     }
 
     /**
+     * @param acquireInfo
+     * @param vendorCode
+     * @return the help string associated with this code
+     */
+    default String getAcquiredString(int acquireInfo, int vendorCode) {
+        throw new UnsupportedOperationException("Stub!");
+    }
+
+    /**
+     * @return one of {@link #TYPE_FINGERPRINT} {@link #TYPE_IRIS} or {@link #TYPE_FACE}
+     */
+    default int getType() {
+        throw new UnsupportedOperationException("Stub!");
+    }
+
+    /**
      * This call warms up the hardware and starts scanning for valid biometrics. It terminates
      * when {@link AuthenticationCallback#onAuthenticationError(int,
      * CharSequence)} is called or when {@link AuthenticationCallback#onAuthenticationSucceeded(
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index 35584ae..46e66e0 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -188,6 +188,7 @@
     @UnsupportedAppUsage
     private final CameraMetadataNative mProperties;
     private List<CameraCharacteristics.Key<?>> mKeys;
+    private List<CameraCharacteristics.Key<?>> mKeysNeedingPermission;
     private List<CaptureRequest.Key<?>> mAvailableRequestKeys;
     private List<CaptureRequest.Key<?>> mAvailableSessionKeys;
     private List<CaptureRequest.Key<?>> mAvailablePhysicalRequestKeys;
@@ -268,11 +269,50 @@
         }
 
         mKeys = Collections.unmodifiableList(
-                getKeys(getClass(), getKeyClass(), this, filterTags));
+                getKeys(getClass(), getKeyClass(), this, filterTags, true));
         return mKeys;
     }
 
     /**
+     * <p>Returns a subset of the list returned by {@link #getKeys} with all keys that
+     * require camera clients to obtain the {@link android.Manifest.permission#CAMERA} permission.
+     * </p>
+     *
+     * <p>If an application calls {@link CameraManager#getCameraCharacteristics} without holding the
+     * {@link android.Manifest.permission#CAMERA} permission,
+     * all keys in this list will not be available, and calling {@link #get} will
+     * return null for those keys. If the application obtains the
+     * {@link android.Manifest.permission#CAMERA} permission, then the
+     * CameraCharacteristics from a call to a subsequent
+     * {@link CameraManager#getCameraCharacteristics} will have the keys available.</p>
+     *
+     * <p>The list returned is not modifiable, so any attempts to modify it will throw
+     * a {@code UnsupportedOperationException}.</p>
+     *
+     * <p>Each key is only listed once in the list. The order of the keys is undefined.</p>
+     *
+     * @return List of camera characteristic keys that require the
+     *         {@link android.Manifest.permission#CAMERA} permission. The list can be null in case
+     *         there are no currently present keys that need additional permission.
+     */
+    public List<Key<?>> getKeysNeedingPermission() {
+        if (mKeysNeedingPermission == null) {
+            Object crKey = CameraCharacteristics.Key.class;
+            Class<CameraCharacteristics.Key<?>> crKeyTyped =
+                (Class<CameraCharacteristics.Key<?>>)crKey;
+
+            int[] filterTags = get(REQUEST_CHARACTERISTIC_KEYS_NEEDING_PERMISSION);
+            if (filterTags == null) {
+                return null;
+            }
+            mKeysNeedingPermission =
+                getAvailableKeyList(CameraCharacteristics.class, crKeyTyped, filterTags,
+                        /*includeSynthetic*/ false);
+        }
+        return mKeysNeedingPermission;
+    }
+
+    /**
      * <p>Returns a subset of {@link #getAvailableCaptureRequestKeys} keys that the
      * camera device can pass as part of the capture session initialization.</p>
      *
@@ -328,17 +368,18 @@
                 return null;
             }
             mAvailableSessionKeys =
-                    getAvailableKeyList(CaptureRequest.class, crKeyTyped, filterTags);
+                    getAvailableKeyList(CaptureRequest.class, crKeyTyped, filterTags,
+                            /*includeSynthetic*/ false);
         }
         return mAvailableSessionKeys;
     }
 
     /**
      * <p>Returns a subset of {@link #getAvailableCaptureRequestKeys} keys that can
-     * be overriden for physical devices backing a logical multi-camera.</p>
+     * be overridden for physical devices backing a logical multi-camera.</p>
      *
      * <p>This is a subset of android.request.availableRequestKeys which contains a list
-     * of keys that can be overriden using {@link CaptureRequest.Builder#setPhysicalCameraKey }.
+     * of keys that can be overridden using {@link CaptureRequest.Builder#setPhysicalCameraKey }.
      * The respective value of such request key can be obtained by calling
      * {@link CaptureRequest.Builder#getPhysicalCameraKey }. Capture requests that contain
      * individual physical device requests must be built via
@@ -353,7 +394,7 @@
      *
      * <p>Each key is only listed once in the list. The order of the keys is undefined.</p>
      *
-     * @return List of keys that can be overriden in individual physical device requests.
+     * @return List of keys that can be overridden in individual physical device requests.
      * In case the camera device doesn't support such keys the list can be null.
      */
     @SuppressWarnings({"unchecked"})
@@ -367,7 +408,8 @@
                 return null;
             }
             mAvailablePhysicalRequestKeys =
-                    getAvailableKeyList(CaptureRequest.class, crKeyTyped, filterTags);
+                    getAvailableKeyList(CaptureRequest.class, crKeyTyped, filterTags,
+                            /*includeSynthetic*/ false);
         }
         return mAvailablePhysicalRequestKeys;
     }
@@ -399,7 +441,8 @@
                         + "in the characteristics");
             }
             mAvailableRequestKeys =
-                    getAvailableKeyList(CaptureRequest.class, crKeyTyped, filterTags);
+                    getAvailableKeyList(CaptureRequest.class, crKeyTyped, filterTags,
+                            /*includeSynthetic*/ true);
         }
         return mAvailableRequestKeys;
     }
@@ -430,7 +473,8 @@
                 throw new AssertionError("android.request.availableResultKeys must be non-null "
                         + "in the characteristics");
             }
-            mAvailableResultKeys = getAvailableKeyList(CaptureResult.class, crKeyTyped, filterTags);
+            mAvailableResultKeys = getAvailableKeyList(CaptureResult.class, crKeyTyped, filterTags,
+                    /*includeSynthetic*/ true);
         }
         return mAvailableResultKeys;
     }
@@ -445,13 +489,16 @@
      *
      * @param metadataClass The subclass of CameraMetadata that you want to get the keys for.
      * @param keyClass The class of the metadata key, e.g. CaptureRequest.Key.class
+     * @param filterTags An array of tags to be used for filtering
+     * @param includeSynthetic Include public syntethic tag by default.
      *
      * @return List of keys supported by this CameraDevice for metadataClass.
      *
      * @throws IllegalArgumentException if metadataClass is not a subclass of CameraMetadata
      */
     private <TKey> List<TKey>
-    getAvailableKeyList(Class<?> metadataClass, Class<TKey> keyClass, int[] filterTags) {
+    getAvailableKeyList(Class<?> metadataClass, Class<TKey> keyClass, int[] filterTags,
+            boolean includeSynthetic) {
 
         if (metadataClass.equals(CameraMetadata.class)) {
             throw new AssertionError(
@@ -462,7 +509,7 @@
         }
 
         List<TKey> staticKeyList = getKeys(
-                metadataClass, keyClass, /*instance*/null, filterTags);
+                metadataClass, keyClass, /*instance*/null, filterTags, includeSynthetic);
         return Collections.unmodifiableList(staticKeyList);
     }
 
@@ -474,6 +521,13 @@
      * REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA capability. If the camera device
      * doesn't have the capability, the return value will be an empty set. </p>
      *
+     * <p>Prior to API level 29, all returned IDs are guaranteed to be returned by {@link
+     * CameraManager#getCameraIdList}, and can be opened directly by
+     * {@link CameraManager#openCamera}. Starting from API level 29, for each of the returned ID,
+     * if it's also returned by {@link CameraManager#getCameraIdList}, it can be used as a
+     * standalone camera by {@link CameraManager#openCamera}. Otherwise, the camera ID can only be
+     * used as part of the current logical camera.</p>
+     *
      * <p>The set returned is not modifiable, so any attempts to modify it will throw
      * a {@code UnsupportedOperationException}.</p>
      *
@@ -1103,6 +1157,7 @@
      * <p><b>Limited capability</b> -
      * Present on all camera devices that report being at least {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED HARDWARE_LEVEL_LIMITED} devices in the
      * {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL android.info.supportedHardwareLevel} key</p>
+     * <p><b>Permission {@link android.Manifest.permission#CAMERA } is needed to access this property</b></p>
      *
      * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
      * @see CameraCharacteristics#LENS_INFO_FOCUS_DISTANCE_CALIBRATION
@@ -1124,6 +1179,7 @@
      * <p><b>Limited capability</b> -
      * Present on all camera devices that report being at least {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED HARDWARE_LEVEL_LIMITED} devices in the
      * {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL android.info.supportedHardwareLevel} key</p>
+     * <p><b>Permission {@link android.Manifest.permission#CAMERA } is needed to access this property</b></p>
      *
      * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
      * @see CameraCharacteristics#LENS_INFO_FOCUS_DISTANCE_CALIBRATION
@@ -1238,6 +1294,7 @@
      * <p><b>Units</b>:
      * Quaternion coefficients</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+     * <p><b>Permission {@link android.Manifest.permission#CAMERA } is needed to access this property</b></p>
      */
     @PublicKey
     public static final Key<float[]> LENS_POSE_ROTATION =
@@ -1273,6 +1330,7 @@
      * with PRIMARY_CAMERA.</p>
      * <p><b>Units</b>: Meters</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+     * <p><b>Permission {@link android.Manifest.permission#CAMERA } is needed to access this property</b></p>
      *
      * @see CameraCharacteristics#LENS_DISTORTION
      * @see CameraCharacteristics#LENS_INTRINSIC_CALIBRATION
@@ -1344,6 +1402,7 @@
      * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}
      * coordinate system.</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+     * <p><b>Permission {@link android.Manifest.permission#CAMERA } is needed to access this property</b></p>
      *
      * @see CameraCharacteristics#LENS_DISTORTION
      * @see CameraCharacteristics#LENS_POSE_ROTATION
@@ -1387,6 +1446,7 @@
      * <p><b>Units</b>:
      * Unitless coefficients.</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+     * <p><b>Permission {@link android.Manifest.permission#CAMERA } is needed to access this property</b></p>
      *
      * @see CameraCharacteristics#LENS_INTRINSIC_CALIBRATION
      * @deprecated
@@ -1411,6 +1471,7 @@
      *   <li>{@link #LENS_POSE_REFERENCE_GYROSCOPE GYROSCOPE}</li>
      * </ul></p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+     * <p><b>Permission {@link android.Manifest.permission#CAMERA } is needed to access this property</b></p>
      *
      * @see CameraCharacteristics#LENS_POSE_TRANSLATION
      * @see #LENS_POSE_REFERENCE_PRIMARY_CAMERA
@@ -1452,6 +1513,7 @@
      * <p><b>Units</b>:
      * Unitless coefficients.</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+     * <p><b>Permission {@link android.Manifest.permission#CAMERA } is needed to access this property</b></p>
      *
      * @see CameraCharacteristics#LENS_INTRINSIC_CALIBRATION
      * @see CameraCharacteristics#LENS_RADIAL_DISTORTION
@@ -1860,10 +1922,10 @@
             new Key<int[]>("android.request.availableSessionKeys", int[].class);
 
     /**
-     * <p>A subset of the available request keys that can be overriden for
+     * <p>A subset of the available request keys that can be overridden for
      * physical devices backing a logical multi-camera.</p>
      * <p>This is a subset of android.request.availableRequestKeys which contains a list
-     * of keys that can be overriden using {@link CaptureRequest.Builder#setPhysicalCameraKey }.
+     * of keys that can be overridden using {@link CaptureRequest.Builder#setPhysicalCameraKey }.
      * The respective value of such request key can be obtained by calling
      * {@link CaptureRequest.Builder#getPhysicalCameraKey }. Capture requests that contain
      * individual physical device requests must be built via
@@ -1880,6 +1942,21 @@
             new Key<int[]>("android.request.availablePhysicalCameraRequestKeys", int[].class);
 
     /**
+     * <p>A list of camera characteristics keys that are only available
+     * in case the camera client has camera permission.</p>
+     * <p>The entry contains a subset of
+     * {@link android.hardware.camera2.CameraCharacteristics#getKeys } that require camera clients
+     * to acquire the {@link android.Manifest.permission#CAMERA } permission before calling
+     * {@link android.hardware.camera2.CameraManager#getCameraCharacteristics }. If the
+     * permission is not held by the camera client, then the values of the repsective properties
+     * will not be present in {@link android.hardware.camera2.CameraCharacteristics }.</p>
+     * <p>This key is available on all devices.</p>
+     * @hide
+     */
+    public static final Key<int[]> REQUEST_CHARACTERISTIC_KEYS_NEEDING_PERMISSION =
+            new Key<int[]>("android.request.characteristicKeysNeedingPermission", int[].class);
+
+    /**
      * <p>The list of image formats that are supported by this
      * camera device for output streams.</p>
      * <p>All camera devices will support JPEG and YUV_420_888 formats.</p>
@@ -2703,6 +2780,7 @@
      *   <li>{@link #SENSOR_REFERENCE_ILLUMINANT1_ISO_STUDIO_TUNGSTEN ISO_STUDIO_TUNGSTEN}</li>
      * </ul></p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+     * <p><b>Permission {@link android.Manifest.permission#CAMERA } is needed to access this property</b></p>
      *
      * @see CameraCharacteristics#SENSOR_CALIBRATION_TRANSFORM1
      * @see CameraCharacteristics#SENSOR_COLOR_TRANSFORM1
@@ -2744,6 +2822,7 @@
      * <p><b>Range of valid values:</b><br>
      * Any value listed in {@link CameraCharacteristics#SENSOR_REFERENCE_ILLUMINANT1 android.sensor.referenceIlluminant1}</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+     * <p><b>Permission {@link android.Manifest.permission#CAMERA } is needed to access this property</b></p>
      *
      * @see CameraCharacteristics#SENSOR_CALIBRATION_TRANSFORM2
      * @see CameraCharacteristics#SENSOR_COLOR_TRANSFORM2
@@ -2766,6 +2845,7 @@
      * space under the first reference illuminant
      * ({@link CameraCharacteristics#SENSOR_REFERENCE_ILLUMINANT1 android.sensor.referenceIlluminant1}).</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+     * <p><b>Permission {@link android.Manifest.permission#CAMERA } is needed to access this property</b></p>
      *
      * @see CameraCharacteristics#SENSOR_REFERENCE_ILLUMINANT1
      */
@@ -2788,6 +2868,7 @@
      * <p>This matrix will only be present if the second reference
      * illuminant is present.</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+     * <p><b>Permission {@link android.Manifest.permission#CAMERA } is needed to access this property</b></p>
      *
      * @see CameraCharacteristics#SENSOR_REFERENCE_ILLUMINANT2
      */
@@ -2811,6 +2892,7 @@
      * match the standard white point for the first reference illuminant
      * (i.e. no chromatic adaptation will be applied by this transform).</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+     * <p><b>Permission {@link android.Manifest.permission#CAMERA } is needed to access this property</b></p>
      *
      * @see CameraCharacteristics#SENSOR_REFERENCE_ILLUMINANT1
      */
@@ -2836,6 +2918,7 @@
      * <p>This matrix will only be present if the second reference
      * illuminant is present.</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+     * <p><b>Permission {@link android.Manifest.permission#CAMERA } is needed to access this property</b></p>
      *
      * @see CameraCharacteristics#SENSOR_REFERENCE_ILLUMINANT2
      */
@@ -2857,6 +2940,7 @@
      * illuminant in the reference sensor colorspace is mapped to D50 in the
      * CIE XYZ colorspace.</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+     * <p><b>Permission {@link android.Manifest.permission#CAMERA } is needed to access this property</b></p>
      *
      * @see CameraCharacteristics#SENSOR_REFERENCE_ILLUMINANT1
      */
@@ -2880,6 +2964,7 @@
      * <p>This matrix will only be present if the second reference
      * illuminant is present.</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+     * <p><b>Permission {@link android.Manifest.permission#CAMERA } is needed to access this property</b></p>
      *
      * @see CameraCharacteristics#SENSOR_REFERENCE_ILLUMINANT2
      */
diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java
index 7ebe0f9..44d7364 100644
--- a/core/java/android/hardware/camera2/CameraManager.java
+++ b/core/java/android/hardware/camera2/CameraManager.java
@@ -34,7 +34,6 @@
 import android.os.DeadObjectException;
 import android.os.Handler;
 import android.os.IBinder;
-import android.os.Looper;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.ServiceSpecificException;
@@ -45,7 +44,6 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Comparator;
-
 import java.util.concurrent.Executor;
 import java.util.concurrent.Executors;
 import java.util.concurrent.RejectedExecutionException;
@@ -97,6 +95,9 @@
      * identifiers, while removable cameras have a unique identifier for each
      * individual device, even if they are the same model.</p>
      *
+     * <p>This list doesn't contain physical cameras that can only used as part of a logical
+     * multi-camera device.</p>
+     *
      * @return The list of currently connected camera devices.
      */
     @NonNull
@@ -234,7 +235,13 @@
      * <p>Query the capabilities of a camera device. These capabilities are
      * immutable for a given camera.</p>
      *
-     * @param cameraId The id of the camera device to query
+     * <p>From API level 29, this function can also be used to query the capabilities of physical
+     * cameras that can only be used as part of logical multi-camera. These cameras cannot not be
+     * opened directly via {@link #openCamera}</p>
+     *
+     * @param cameraId The id of the camera device to query. This could be either a standalone
+     * camera ID which can be directly opened by {@link #openCamera}, or a physical camera ID that
+     * can only used as part of a logical multi-camera.
      * @return The properties of the given camera
      *
      * @throws IllegalArgumentException if the cameraId does not match any
@@ -262,7 +269,9 @@
                         "Camera service is currently unavailable");
             }
             try {
-                if (!supportsCamera2ApiLocked(cameraId)) {
+                // First check isHiddenPhysicalCamera to avoid supportsCamera2ApiLocked throwing
+                // exception in case cameraId is a hidden physical camera.
+                if (!isHiddenPhysicalCamera(cameraId) && !supportsCamera2ApiLocked(cameraId)) {
                     // Legacy backwards compatibility path; build static info from the camera
                     // parameters
                     int id = Integer.parseInt(cameraId);
@@ -454,7 +463,7 @@
      *
      * @throws IllegalArgumentException if cameraId or the callback was null,
      * or the cameraId does not match any currently or previously available
-     * camera device.
+     * camera device returned by {@link #getCameraIdList}.
      *
      * @throws SecurityException if the application does not have permission to
      * access the camera
@@ -778,6 +787,29 @@
     }
 
     /**
+     * Queries the camera service if a cameraId is a hidden physical camera that belongs to a
+     * logical camera device.
+     *
+     * A hidden physical camera is a camera that cannot be opened by the application. But it
+     * can be used as part of a logical camera.
+     *
+     * @param cameraId a non-{@code null} camera identifier
+     * @return {@code true} if cameraId is a hidden physical camera device
+     */
+    private boolean isHiddenPhysicalCamera(String cameraId) {
+        try {
+            ICameraService cameraService = CameraManagerGlobal.get().getCameraService();
+            // If no camera service, no support
+            if (cameraService == null) return false;
+
+            return cameraService.isHiddenPhysicalCamera(cameraId);
+        } catch (RemoteException e) {
+            // Camera service is now down, no support for any API level
+        }
+        return false;
+    }
+
+    /**
      * A per-process global camera manager instance, to retain a connection to the camera service,
      * and to distribute camera availability notices to API-registered callbacks
      */
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index caa99d5..486b054 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -116,7 +116,8 @@
     public List<TKey> getKeys() {
         Class<CameraMetadata<TKey>> thisClass = (Class<CameraMetadata<TKey>>) getClass();
         return Collections.unmodifiableList(
-                getKeys(thisClass, getKeyClass(), this, /*filterTags*/null));
+                getKeys(thisClass, getKeyClass(), this, /*filterTags*/null,
+                    /*includeSynthetic*/ true));
     }
 
     /**
@@ -131,13 +132,14 @@
      * Optionally, if {@code filterTags} is not {@code null}, then filter out any keys
      * whose native {@code tag} is not in {@code filterTags}. The {@code filterTags} array will be
      * sorted as a side effect.
+     * {@code includeSynthetic} Includes public syntenthic fields by default.
      * </p>
      */
      /*package*/ @SuppressWarnings("unchecked")
     <TKey> ArrayList<TKey> getKeys(
              Class<?> type, Class<TKey> keyClass,
              CameraMetadata<TKey> instance,
-             int[] filterTags) {
+             int[] filterTags, boolean includeSynthetic) {
 
         if (DEBUG) Log.v(TAG, "getKeysStatic for " + type);
 
@@ -168,7 +170,7 @@
                 }
 
                 if (instance == null || instance.getProtected(key) != null) {
-                    if (shouldKeyBeAdded(key, field, filterTags)) {
+                    if (shouldKeyBeAdded(key, field, filterTags, includeSynthetic)) {
                         keyList.add(key);
 
                         if (DEBUG) {
@@ -215,7 +217,8 @@
     }
 
     @SuppressWarnings("rawtypes")
-    private static <TKey> boolean shouldKeyBeAdded(TKey key, Field field, int[] filterTags) {
+    private static <TKey> boolean shouldKeyBeAdded(TKey key, Field field, int[] filterTags,
+            boolean includeSynthetic) {
         if (key == null) {
             throw new NullPointerException("key must not be null");
         }
@@ -249,8 +252,7 @@
         if (field.getAnnotation(SyntheticKey.class) != null) {
             // This key is synthetic, so calling #getTag will throw IAE
 
-            // TODO: don't just assume all public+synthetic keys are always available
-            return true;
+            return includeSynthetic;
         }
 
         /*
@@ -811,8 +813,14 @@
     public static final int REQUEST_AVAILABLE_CAPABILITIES_MOTION_TRACKING = 10;
 
     /**
-     * <p>The camera device is a logical camera backed by two or more physical cameras that are
-     * also exposed to the application.</p>
+     * <p>The camera device is a logical camera backed by two or more physical cameras. In
+     * API level 28, the physical cameras must also be exposed to the application via
+     * {@link android.hardware.camera2.CameraManager#getCameraIdList }. Starting from API
+     * level 29, some or all physical cameras may not be independently exposed to the
+     * application, in which case the physical camera IDs will not be available in
+     * {@link android.hardware.camera2.CameraManager#getCameraIdList }. But the application
+     * can still query the physical cameras' characteristics by calling
+     * {@link android.hardware.camera2.CameraManager#getCameraCharacteristics }.</p>
      * <p>Camera application shouldn't assume that there are at most 1 rear camera and 1 front
      * camera in the system. For an application that switches between front and back cameras,
      * the recommendation is to switch between the first rear camera and the first front
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index 3c6c11d..a7e185c 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -2841,6 +2841,7 @@
      * <p><b>Units</b>:
      * Quaternion coefficients</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+     * <p><b>Permission {@link android.Manifest.permission#CAMERA } is needed to access this property</b></p>
      */
     @PublicKey
     public static final Key<float[]> LENS_POSE_ROTATION =
@@ -2876,6 +2877,7 @@
      * with PRIMARY_CAMERA.</p>
      * <p><b>Units</b>: Meters</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+     * <p><b>Permission {@link android.Manifest.permission#CAMERA } is needed to access this property</b></p>
      *
      * @see CameraCharacteristics#LENS_DISTORTION
      * @see CameraCharacteristics#LENS_INTRINSIC_CALIBRATION
@@ -2947,6 +2949,7 @@
      * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}
      * coordinate system.</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+     * <p><b>Permission {@link android.Manifest.permission#CAMERA } is needed to access this property</b></p>
      *
      * @see CameraCharacteristics#LENS_DISTORTION
      * @see CameraCharacteristics#LENS_POSE_ROTATION
@@ -2990,6 +2993,7 @@
      * <p><b>Units</b>:
      * Unitless coefficients.</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+     * <p><b>Permission {@link android.Manifest.permission#CAMERA } is needed to access this property</b></p>
      *
      * @see CameraCharacteristics#LENS_INTRINSIC_CALIBRATION
      * @deprecated
@@ -3036,6 +3040,7 @@
      * <p><b>Units</b>:
      * Unitless coefficients.</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+     * <p><b>Permission {@link android.Manifest.permission#CAMERA } is needed to access this property</b></p>
      *
      * @see CameraCharacteristics#LENS_INTRINSIC_CALIBRATION
      * @see CameraCharacteristics#LENS_RADIAL_DISTORTION
diff --git a/core/java/android/hardware/camera2/params/OutputConfiguration.java b/core/java/android/hardware/camera2/params/OutputConfiguration.java
index 1ee3c93..cb33659 100644
--- a/core/java/android/hardware/camera2/params/OutputConfiguration.java
+++ b/core/java/android/hardware/camera2/params/OutputConfiguration.java
@@ -58,7 +58,7 @@
  * execute in parallel with any {@link Surface} initialization, such as waiting for a
  * {@link android.view.SurfaceView} to be ready as part of the UI initialization.</li>
  *
- * <li>The third and most complex usage pattern inlvolves surface sharing. Once instantiated an
+ * <li>The third and most complex usage pattern involves surface sharing. Once instantiated an
  * OutputConfiguration can be enabled for surface sharing via {@link #enableSurfaceSharing}. This
  * must be done before creating a new capture session and enables calls to
  * {@link CameraCaptureSession#updateOutputConfiguration}. An OutputConfiguration with enabled
diff --git a/core/java/android/hardware/display/BrightnessConfiguration.java b/core/java/android/hardware/display/BrightnessConfiguration.java
index 6d9ba77..7e52ca3 100644
--- a/core/java/android/hardware/display/BrightnessConfiguration.java
+++ b/core/java/android/hardware/display/BrightnessConfiguration.java
@@ -141,13 +141,6 @@
         private String mDescription;
 
         /**
-         * STOPSHIP remove when app has stopped using this.
-         * @hide
-         */
-        public Builder() {
-        }
-
-        /**
          * Constructs the builder with the control points for the brightness curve.
          *
          * Brightness curves must have strictly increasing ambient brightness values in lux and
@@ -159,24 +152,6 @@
          * @throws IllegalArgumentException if the nit levels are not monotonically increasing.
          */
         public Builder(float[] lux, float[] nits) {
-            setCurve(lux, nits);
-        }
-
-        /**
-         * Sets the control points for the brightness curve.
-         *
-         * Brightness curves must have strictly increasing ambient brightness values in lux and
-         * monotonically increasing display brightness values in nits. In addition, the initial
-         * control point must be 0 lux.
-         *
-         * @throws IllegalArgumentException if the initial control point is not at 0 lux.
-         * @throws IllegalArgumentException if the lux levels are not strictly increasing.
-         * @throws IllegalArgumentException if the nit levels are not monotonically increasing.
-         *
-         * STOPSHIP remove when app has stopped using this.
-         * @hide
-         */
-        public Builder setCurve(float[] lux, float[] nits) {
             Preconditions.checkNotNull(lux);
             Preconditions.checkNotNull(nits);
             if (lux.length == 0 || nits.length == 0) {
@@ -190,11 +165,10 @@
             }
             Preconditions.checkArrayElementsInRange(lux, 0, Float.MAX_VALUE, "lux");
             Preconditions.checkArrayElementsInRange(nits, 0, Float.MAX_VALUE, "nits");
-            checkMonotonic(lux, true/*strictly increasing*/, "lux");
+            checkMonotonic(lux, true /*strictly increasing*/, "lux");
             checkMonotonic(nits, false /*strictly increasing*/, "nits");
             mCurveLux = lux;
             mCurveNits = nits;
-            return this;
         }
 
         /**
diff --git a/core/java/android/hardware/display/DisplayViewport.java b/core/java/android/hardware/display/DisplayViewport.java
index b4955ea..496f34c 100644
--- a/core/java/android/hardware/display/DisplayViewport.java
+++ b/core/java/android/hardware/display/DisplayViewport.java
@@ -30,6 +30,12 @@
  * @hide Only for use within the system server.
  */
 public final class DisplayViewport {
+
+    // Viewport constants defined in InputReader.h.
+    public static final int VIEWPORT_INTERNAL = 1;
+    public static final int VIEWPORT_EXTERNAL = 2;
+    public static final int VIEWPORT_VIRTUAL = 3;
+
     // True if this viewport is valid.
     public boolean valid;
 
diff --git a/core/java/android/hardware/face/FaceManager.java b/core/java/android/hardware/face/FaceManager.java
index b3b962f..0f83c8b 100644
--- a/core/java/android/hardware/face/FaceManager.java
+++ b/core/java/android/hardware/face/FaceManager.java
@@ -552,6 +552,7 @@
     /**
      * @hide
      */
+    @Override
     public String getAcquiredString(int acquireInfo, int vendorCode) {
         switch (acquireInfo) {
             case FACE_ACQUIRED_GOOD:
@@ -591,6 +592,14 @@
     }
 
     /**
+     * @hide
+     */
+    @Override
+    public int getType() {
+        return TYPE_FACE;
+    }
+
+    /**
      * Used so BiometricPrompt can map the face ones onto existing public constants.
      * @hide
      */
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index 44b8faf..b380a2e 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -979,6 +979,7 @@
     /**
      * @hide
      */
+    @Override
     public String getAcquiredString(int acquireInfo, int vendorCode) {
         switch (acquireInfo) {
             case FINGERPRINT_ACQUIRED_GOOD:
@@ -1010,6 +1011,14 @@
         return null;
     }
 
+    /**
+     * @hide
+     */
+    @Override
+    public int getType() {
+        return TYPE_FINGERPRINT;
+    }
+
     private IFingerprintServiceReceiver mServiceReceiver = new IFingerprintServiceReceiver.Stub() {
 
         @Override // binder call
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index 6ca5f0c..bfb7c58 100644
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.java
@@ -25,6 +25,7 @@
 import android.content.Context;
 import android.media.AudioAttributes;
 import android.os.Binder;
+import android.os.Build;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
@@ -65,7 +66,7 @@
 
     private static InputManager sInstance;
 
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private final IInputManager mIm;
 
     // Guarded by mInputDevicesLock
diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java
index 3141be4..4111941 100644
--- a/core/java/android/hardware/usb/UsbManager.java
+++ b/core/java/android/hardware/usb/UsbManager.java
@@ -32,6 +32,7 @@
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.hardware.usb.gadget.V1_0.GadgetFunction;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.ParcelFileDescriptor;
 import android.os.Process;
@@ -300,6 +301,23 @@
     public static final String EXTRA_PERMISSION_GRANTED = "permission";
 
     /**
+     * Name of extra added to start systemui.usb.UsbPermissionActivity
+     * containing package name of the app which requests USB permission.
+     *
+     * @hide
+     */
+    public static final String EXTRA_PACKAGE = "android.hardware.usb.extra.PACKAGE";
+
+    /**
+     * Name of extra added to start systemui.usb.UsbPermissionActivity
+     * containing the whether the app which requests USB permission can be set as default handler
+     * for USB device attach event or USB accessory attach event or not.
+     *
+     * @hide
+     */
+    public static final String EXTRA_CAN_BE_DEFAULT = "android.hardware.usb.extra.CAN_BE_DEFAULT";
+
+    /**
      * Code for the charging usb function. Passed into {@link #setCurrentFunctions(long)}
      * {@hide}
      */
@@ -368,7 +386,7 @@
     /**
      * {@hide}
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     public UsbManager(Context context, IUsbManager service) {
         mContext = context;
         mService = service;
diff --git a/core/java/android/inputmethodservice/AbstractInputMethodService.java b/core/java/android/inputmethodservice/AbstractInputMethodService.java
index 185215a..b0fca00 100644
--- a/core/java/android/inputmethodservice/AbstractInputMethodService.java
+++ b/core/java/android/inputmethodservice/AbstractInputMethodService.java
@@ -252,4 +252,12 @@
         return;
     }
 
+    /**
+     * Called when the user took some actions that should be taken into consideration to update the
+     * MRU list for input method rotation.
+     *
+     * @hide
+     */
+    public void notifyUserActionIfNecessary() {
+    }
 }
diff --git a/core/java/android/inputmethodservice/IInputMethodWrapper.java b/core/java/android/inputmethodservice/IInputMethodWrapper.java
index 2c7e51a..1030694 100644
--- a/core/java/android/inputmethodservice/IInputMethodWrapper.java
+++ b/core/java/android/inputmethodservice/IInputMethodWrapper.java
@@ -35,6 +35,7 @@
 import android.view.inputmethod.InputMethodSession;
 import android.view.inputmethod.InputMethodSubtype;
 
+import com.android.internal.inputmethod.IInputMethodPrivilegedOperations;
 import com.android.internal.os.HandlerCaller;
 import com.android.internal.os.SomeArgs;
 import com.android.internal.view.IInputContext;
@@ -60,7 +61,7 @@
     private static final String TAG = "InputMethodWrapper";
 
     private static final int DO_DUMP = 1;
-    private static final int DO_ATTACH_TOKEN = 10;
+    private static final int DO_INITIALIZE_INTERNAL = 10;
     private static final int DO_SET_INPUT_CONTEXT = 20;
     private static final int DO_UNSET_INPUT_CONTEXT = 30;
     private static final int DO_START_INPUT = 32;
@@ -86,8 +87,8 @@
      * guarantees that {@link #bindInput(InputBinding)},
      * {@link #startInput(IBinder, IInputContext, int, EditorInfo, boolean)}, and
      * {@link #unbindInput()} are called with the same order as the original calls
-     * in {@link com.android.server.InputMethodManagerService}.  See {@link IBinder#FLAG_ONEWAY}
-     * for detailed semantics.</p>
+     * in {@link com.android.server.inputmethod.InputMethodManagerService}.
+     * See {@link IBinder#FLAG_ONEWAY} for detailed semantics.</p>
      */
     AtomicBoolean mIsUnbindIssued = null;
 
@@ -159,9 +160,14 @@
                 args.recycle();
                 return;
             }
-            
-            case DO_ATTACH_TOKEN: {
-                inputMethod.attachToken((IBinder)msg.obj);
+            case DO_INITIALIZE_INTERNAL: {
+                SomeArgs args = (SomeArgs) msg.obj;
+                try {
+                    inputMethod.initializeInternal((IBinder) args.arg1, msg.arg1,
+                            (IInputMethodPrivilegedOperations) args.arg2);
+                } finally {
+                    args.recycle();
+                }
                 return;
             }
             case DO_SET_INPUT_CONTEXT: {
@@ -246,8 +252,10 @@
 
     @BinderThread
     @Override
-    public void attachToken(IBinder token) {
-        mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_ATTACH_TOKEN, token));
+    public void initializeInternal(IBinder token, int displayId,
+            IInputMethodPrivilegedOperations privOps) {
+        mCaller.executeOrSendMessage(
+                mCaller.obtainMessageIOO(DO_INITIALIZE_INTERNAL, displayId, token, privOps));
     }
 
     @BinderThread
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 46671b2..34fa5b6 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -16,12 +16,14 @@
 
 package android.inputmethodservice;
 
+import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
 import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
 import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
 
 import static java.lang.annotation.RetentionPolicy.SOURCE;
 
+import android.annotation.AnyThread;
 import android.annotation.CallSuper;
 import android.annotation.DrawableRes;
 import android.annotation.IntDef;
@@ -62,7 +64,6 @@
 import android.view.ViewTreeObserver;
 import android.view.Window;
 import android.view.WindowManager;
-import android.view.WindowManager.BadTokenException;
 import android.view.animation.AnimationUtils;
 import android.view.inputmethod.CompletionInfo;
 import android.view.inputmethod.CursorAnchorInfo;
@@ -80,6 +81,11 @@
 import android.widget.LinearLayout;
 import android.widget.TextView;
 
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.inputmethod.IInputContentUriToken;
+import com.android.internal.inputmethod.IInputMethodPrivilegedOperations;
+import com.android.internal.inputmethod.InputMethodPrivilegedOperations;
+
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.lang.annotation.Retention;
@@ -343,7 +349,8 @@
     private static final int BACK_DISPOSITION_MAX = BACK_DISPOSITION_ADJUST_NOTHING;
 
     InputMethodManager mImm;
-    
+    private InputMethodPrivilegedOperations mPrivOps = new InputMethodPrivilegedOperations();
+
     @UnsupportedAppUsage
     int mTheme = 0;
     
@@ -354,7 +361,6 @@
     SoftInputWindow mWindow;
     boolean mInitialized;
     boolean mWindowCreated;
-    boolean mWindowAdded;
     boolean mWindowVisible;
     boolean mWindowWasVisible;
     boolean mInShowWindow;
@@ -399,6 +405,10 @@
     @BackDispositionMode
     int mBackDisposition;
 
+    private Object mLock = new Object();
+    @GuardedBy("mLock")
+    private boolean mNotifyUserActionSent;
+
     /**
      * {@code true} when the previous IME had non-empty inset at the bottom of the screen and we
      * have not shown our own window yet.  In this situation, the previous inset continues to be
@@ -448,13 +458,45 @@
     public class InputMethodImpl extends AbstractInputMethodImpl {
         /**
          * {@inheritDoc}
+         * @hide
+         */
+        @MainThread
+        @Override
+        public final void initializeInternal(IBinder token, int displayId,
+                IInputMethodPrivilegedOperations privilegedOperations) {
+            mPrivOps.set(privilegedOperations);
+            mImm.registerInputMethodPrivOps(token, mPrivOps);
+            updateInputMethodDisplay(displayId);
+            attachToken(token);
+        }
+
+        /**
+         * {@inheritDoc}
          */
         @MainThread
         @Override
         public void attachToken(IBinder token) {
-            if (mToken == null) {
-                mToken = token;
-                mWindow.setToken(token);
+            if (mToken != null) {
+                throw new IllegalStateException(
+                        "attachToken() must be called at most once. token=" + token);
+            }
+            mToken = token;
+            mWindow.setToken(token);
+        }
+
+        /**
+         * {@inheritDoc}
+         * @hide
+         */
+        @MainThread
+        @Override
+        public void updateInputMethodDisplay(int displayId) {
+            // Update display for adding IME window to the right display.
+            if (displayId != DEFAULT_DISPLAY) {
+                // TODO(b/111364446) Need to address context lifecycle issue if need to re-create
+                // for update resources & configuration correctly when show soft input
+                // in non-default display.
+                updateDisplay(displayId);
             }
         }
 
@@ -470,9 +512,7 @@
             mInputConnection = binding.getConnection();
             if (DEBUG) Log.v(TAG, "bindInput(): binding=" + binding
                     + " ic=" + mInputConnection);
-            if (mImm != null && mToken != null) {
-                mImm.reportFullscreenMode(mToken, mIsFullscreen);
-            }
+            reportFullscreenMode();
             initialize();
             onBindInput();
         }
@@ -521,8 +561,7 @@
         public void dispatchStartInputWithToken(@Nullable InputConnection inputConnection,
                 @NonNull EditorInfo editorInfo, boolean restarting,
                 @NonNull IBinder startInputToken) {
-            mImm.reportStartInput(mToken, startInputToken);
-
+            mPrivOps.reportStartInput(startInputToken);
             // This needs to be dispatched to interface methods rather than doStartInput().
             // Otherwise IME developers who have overridden those interface methods will lose
             // notifications.
@@ -559,21 +598,12 @@
             if (DEBUG) Log.v(TAG, "showSoftInput()");
             boolean wasVis = isInputViewShown();
             if (dispatchOnShowInputRequested(flags, false)) {
-                try {
-                    showWindow(true);
-                } catch (BadTokenException e) {
-                    // We have ignored BadTokenException here since Jelly Bean MR-2 (API Level 18).
-                    // We could ignore BadTokenException in InputMethodService#showWindow() instead,
-                    // but it may break assumptions for those who override #showWindow() that we can
-                    // detect errors in #showWindow() by checking BadTokenException.
-                    // TODO: Investigate its feasibility.  Update JavaDoc of #showWindow() of
-                    // whether it's OK to override #showWindow() or not.
-                }
+                showWindow(true);
             }
             clearInsetOfPreviousIme();
             // If user uses hard keyboard, IME button should always be shown.
-            mImm.setImeWindowStatus(mToken, mapToImeWindowStatus(isInputViewShown()),
-                    mBackDisposition);
+            setImeWindowStatus(mapToImeWindowStatus(isInputViewShown()), mBackDisposition);
+
             if (resultReceiver != null) {
                 resultReceiver.send(wasVis != isInputViewShown()
                         ? InputMethodManager.RESULT_SHOWN
@@ -588,10 +618,14 @@
         @MainThread
         @Override
         public void changeInputMethodSubtype(InputMethodSubtype subtype) {
-            onCurrentInputMethodSubtypeChanged(subtype);
+            dispatchOnCurrentInputMethodSubtypeChanged(subtype);
         }
     }
 
+    private void setImeWindowStatus(int visibilityFlags, int backDisposition) {
+        mPrivOps.setImeWindowStatus(visibilityFlags, backDisposition);
+    }
+
     /**
      * Concrete implementation of
      * {@link AbstractInputMethodService.AbstractInputMethodSessionImpl} that provides
@@ -914,6 +948,9 @@
         // If the previous IME has occupied non-empty inset in the screen, we need to decide whether
         // we continue to use the same size of the inset or update it
         mShouldClearInsetOfPreviousIme = (mImm.getInputMethodWindowVisibleHeight() > 0);
+        // TODO(b/111364446) Need to address context lifecycle issue if need to re-create
+        // for update resources & configuration correctly when show soft input
+        // in non-default display.
         mInflater = (LayoutInflater)getSystemService(
                 Context.LAYOUT_INFLATER_SERVICE);
         mWindow = new SoftInputWindow(this, "InputMethod", mTheme, null, null, mDispatcherState,
@@ -986,17 +1023,16 @@
         mRootView.getViewTreeObserver().removeOnComputeInternalInsetsListener(
                 mInsetsComputer);
         doFinishInput();
-        if (mWindowAdded) {
-            // Disable exit animation for the current IME window
-            // to avoid the race condition between the exit and enter animations
-            // when the current IME is being switched to another one.
-            mWindow.getWindow().setWindowAnimations(0);
-            mWindow.dismiss();
-        }
+        mWindow.dismissForDestroyIfNecessary();
         if (mSettingsObserver != null) {
             mSettingsObserver.unregister();
             mSettingsObserver = null;
         }
+        if (mToken != null) {
+            // This is completely optional, but allows us to show more explicit error messages
+            // when IME developers are doing something unsupported.
+            mImm.unregisterInputMethodPrivOps(mToken);
+        }
     }
 
     /**
@@ -1054,8 +1090,7 @@
             }
             // If user uses hard keyboard, IME button should always be shown.
             boolean showing = onEvaluateInputViewShown();
-            mImm.setImeWindowStatus(mToken, IME_ACTIVE | (showing ? IME_VISIBLE : 0),
-                    mBackDisposition);
+            setImeWindowStatus(IME_ACTIVE | (showing ? IME_VISIBLE : 0), mBackDisposition);
         }
     }
 
@@ -1105,7 +1140,7 @@
             return;
         }
         mBackDisposition = disposition;
-        mImm.setImeWindowStatus(mToken, mapToImeWindowStatus(isInputViewShown()), mBackDisposition);
+        setImeWindowStatus(mapToImeWindowStatus(isInputViewShown()), mBackDisposition);
     }
 
     /**
@@ -1168,7 +1203,7 @@
      * used input method and subtype.
      */
     public final boolean switchToPreviousInputMethod() {
-        return mImm.switchToPreviousInputMethodInternal(mToken);
+        return mPrivOps.switchToPreviousInputMethod();
     }
 
     /**
@@ -1180,7 +1215,7 @@
      * input method and subtype.
      */
     public final boolean switchToNextInputMethod(boolean onlyCurrentIme) {
-        return mImm.switchToNextInputMethodInternal(mToken, onlyCurrentIme);
+        return mPrivOps.switchToNextInputMethod(onlyCurrentIme);
     }
 
     /**
@@ -1193,7 +1228,7 @@
      * between IMEs and subtypes.
      */
     public final boolean shouldOfferSwitchingToNextInputMethod() {
-        return mImm.shouldOfferSwitchingToNextInputMethodInternal(mToken);
+        return mPrivOps.shouldOfferSwitchingToNextInputMethod();
     }
 
     public boolean getCurrentInputStarted() {
@@ -1203,7 +1238,11 @@
     public EditorInfo getCurrentInputEditorInfo() {
         return mInputEditorInfo;
     }
-    
+
+    private void reportFullscreenMode() {
+        mPrivOps.reportFullscreenMode(mIsFullscreen);
+    }
+
     /**
      * Re-evaluate whether the input method should be running in fullscreen
      * mode, and update its UI if this has changed since the last time it
@@ -1218,9 +1257,7 @@
         if (mIsFullscreen != isFullscreen || !mFullscreenApplied) {
             changed = true;
             mIsFullscreen = isFullscreen;
-            if (mImm != null && mToken != null) {
-                mImm.reportFullscreenMode(mToken, mIsFullscreen);
-            }
+            reportFullscreenMode();
             mFullscreenApplied = true;
             initialize();
             LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)
@@ -1509,12 +1546,12 @@
 
     public void showStatusIcon(@DrawableRes int iconResId) {
         mStatusIcon = iconResId;
-        mImm.showStatusIconInternal(mToken, getPackageName(), iconResId);
+        mPrivOps.updateStatusIcon(getPackageName(), iconResId);
     }
 
     public void hideStatusIcon() {
         mStatusIcon = 0;
-        mImm.hideStatusIconInternal(mToken);
+        mPrivOps.updateStatusIcon(null, 0);
     }
 
     /**
@@ -1525,7 +1562,7 @@
      * @param id Unique identifier of the new input method to start.
      */
     public void switchInputMethod(String id) {
-        mImm.setInputMethodInternal(mToken, id);
+        mPrivOps.setInputMethod(id);
     }
 
     /**
@@ -1537,7 +1574,7 @@
      * @param subtype The new subtype of the new input method to be switched to.
      */
     public final void switchInputMethod(String id, InputMethodSubtype subtype) {
-        mImm.setInputMethodAndSubtypeInternal(mToken, id, subtype);
+        mPrivOps.setInputMethodAndSubtype(id, subtype);
     }
 
     public void setExtractView(View view) {
@@ -1778,7 +1815,6 @@
     public void showWindow(boolean showInput) {
         if (DEBUG) Log.v(TAG, "Showing window: showInput=" + showInput
                 + " mShowInputRequested=" + mShowInputRequested
-                + " mWindowAdded=" + mWindowAdded
                 + " mWindowCreated=" + mWindowCreated
                 + " mWindowVisible=" + mWindowVisible
                 + " mInputStarted=" + mInputStarted
@@ -1788,27 +1824,12 @@
             Log.w(TAG, "Re-entrance in to showWindow");
             return;
         }
-        
-        try {
-            mWindowWasVisible = mWindowVisible;
-            mInShowWindow = true;
-            showWindowInner(showInput);
-        } catch (BadTokenException e) {
-            // BadTokenException is a normal consequence in certain situations, e.g., swapping IMEs
-            // while there is a DO_SHOW_SOFT_INPUT message in the IIMethodWrapper queue.
-            if (DEBUG) Log.v(TAG, "BadTokenException: IME is done.");
-            mWindowVisible = false;
-            mWindowAdded = false;
-            // Rethrow the exception to preserve the existing behavior.  Some IMEs may have directly
-            // called this method and relied on this exception for some clean-up tasks.
-            // TODO: Give developers a clear guideline of whether it's OK to call this method or
-            // InputMethodService#requestShowSelf(int) should always be used instead.
-            throw e;
-        } finally {
-            // TODO: Is it OK to set true when we get BadTokenException?
-            mWindowWasVisible = true;
-            mInShowWindow = false;
-        }
+
+        mWindowWasVisible = mWindowVisible;
+        mInShowWindow = true;
+        showWindowInner(showInput);
+        mWindowWasVisible = true;
+        mInShowWindow = false;
     }
 
     void showWindowInner(boolean showInput) {
@@ -1825,9 +1846,8 @@
         initialize();
         updateFullscreenMode();
         updateInputViewShown();
-        
-        if (!mWindowAdded || !mWindowCreated) {
-            mWindowAdded = true;
+
+        if (!mWindowCreated) {
             mWindowCreated = true;
             initialize();
             if (DEBUG) Log.v(TAG, "CALL: onCreateCandidatesView");
@@ -1855,7 +1875,7 @@
 
         final int nextImeWindowStatus = mapToImeWindowStatus(isInputViewShown());
         if (previousImeWindowStatus != nextImeWindowStatus) {
-            mImm.setImeWindowStatus(mToken, nextImeWindowStatus, mBackDisposition);
+            setImeWindowStatus(nextImeWindowStatus, mBackDisposition);
         }
         if ((previousImeWindowStatus & IME_ACTIVE) == 0) {
             if (DEBUG) Log.v(TAG, "showWindow: showing!");
@@ -1880,7 +1900,7 @@
     }
 
     private void doHideWindow() {
-        mImm.setImeWindowStatus(mToken, 0, mBackDisposition);
+        setImeWindowStatus(0, mBackDisposition);
         hideWindow();
     }
 
@@ -1921,11 +1941,24 @@
                 + " mShouldClearInsetOfPreviousIme=" + mShouldClearInsetOfPreviousIme);
         if (!mShouldClearInsetOfPreviousIme) return;
 
-        mImm.clearLastInputMethodWindowForTransition(mToken);
+        clearLastInputMethodWindowForTransition();
         mShouldClearInsetOfPreviousIme = false;
     }
 
     /**
+     * Tells the system that the IME decided to not show a window and the system no longer needs to
+     * use the previous IME's inset.
+     *
+     * <p>Caveat: {@link android.inputmethodservice.InputMethodService#clearInsetOfPreviousIme()}
+     * is the only expected caller of this method.  Do not depend on this anywhere else.</p>
+     *
+     * <p>TODO: We probably need to reconsider how IME should be handled.</p>
+     */
+    private void clearLastInputMethodWindowForTransition() {
+        mPrivOps.clearLastInputMethodWindowForTransition();
+    }
+
+    /**
      * Called when a new client has bound to the input method.  This
      * may be followed by a series of {@link #onStartInput(EditorInfo, boolean)}
      * and {@link #onFinishInput()} calls as the user navigates through its
@@ -2132,7 +2165,7 @@
      * @param flags Provides additional operating flags.
      */
     public void requestHideSelf(int flags) {
-        mImm.hideSoftInputFromInputMethodInternal(mToken, flags);
+        mPrivOps.hideMySoftInput(flags);
     }
 
     /**
@@ -2144,7 +2177,7 @@
      * @param flags Provides additional operating flags.
      */
     public final void requestShowSelf(int flags) {
-        mImm.showSoftInputFromInputMethodInternal(mToken, flags);
+        mPrivOps.showMySoftInput(flags);
     }
 
     private boolean handleBack(boolean doIt) {
@@ -2786,6 +2819,13 @@
         }
     }
 
+    private void dispatchOnCurrentInputMethodSubtypeChanged(InputMethodSubtype newSubtype) {
+        synchronized (mLock) {
+            mNotifyUserActionSent = false;
+        }
+        onCurrentInputMethodSubtypeChanged(newSubtype);
+    }
+
     // TODO: Handle the subtype change event
     /**
      * Called when the subtype was changed.
@@ -2838,7 +2878,48 @@
         if (getCurrentInputConnection() != inputConnection) {
             return;
         }
-        mImm.exposeContent(mToken, inputContentInfo, getCurrentInputEditorInfo());
+        exposeContentInternal(inputContentInfo, getCurrentInputEditorInfo());
+    }
+
+    /**
+     * {@inheritDoc}
+     * @hide
+     */
+    @AnyThread
+    @Override
+    public final void notifyUserActionIfNecessary() {
+        synchronized (mLock) {
+            if (mNotifyUserActionSent) {
+                return;
+            }
+            mPrivOps.notifyUserActionAsync();
+            mNotifyUserActionSent = true;
+        }
+    }
+
+    /**
+     * Allow the receiver of {@link InputContentInfo} to obtain a temporary read-only access
+     * permission to the content.
+     *
+     * <p>See {@link android.inputmethodservice.InputMethodService#exposeContent(InputContentInfo,
+     * InputConnection)} for details.</p>
+     *
+     * @param inputContentInfo Content to be temporarily exposed from the input method to the
+     * application.
+     * This cannot be {@code null}.
+     * @param editorInfo The editor that receives {@link InputContentInfo}.
+     */
+    private void exposeContentInternal(@NonNull InputContentInfo inputContentInfo,
+            @NonNull EditorInfo editorInfo) {
+        final Uri contentUri = inputContentInfo.getContentUri();
+        final IInputContentUriToken uriToken =
+                mPrivOps.createInputContentUriToken(contentUri, editorInfo.packageName);
+        if (uriToken == null) {
+            Log.e(TAG, "createInputContentAccessToken failed. contentUri=" + contentUri.toString()
+                    + " packageName=" + editorInfo.packageName);
+            return;
+        }
+        inputContentInfo.setUriToken(uriToken);
     }
 
     private static int mapToImeWindowStatus(boolean isInputViewShown) {
@@ -2852,8 +2933,7 @@
     @Override protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
         final Printer p = new PrintWriterPrinter(fout);
         p.println("Input method service state for " + this + ":");
-        p.println("  mWindowCreated=" + mWindowCreated
-                + " mWindowAdded=" + mWindowAdded);
+        p.println("  mWindowCreated=" + mWindowCreated);
         p.println("  mWindowVisible=" + mWindowVisible
                 + " mWindowWasVisible=" + mWindowWasVisible
                 + " mInShowWindow=" + mInShowWindow);
diff --git a/core/java/android/inputmethodservice/Keyboard.java b/core/java/android/inputmethodservice/Keyboard.java
index ec5f050..51d33b2 100644
--- a/core/java/android/inputmethodservice/Keyboard.java
+++ b/core/java/android/inputmethodservice/Keyboard.java
@@ -25,6 +25,7 @@
 import android.content.res.TypedArray;
 import android.content.res.XmlResourceParser;
 import android.graphics.drawable.Drawable;
+import android.os.Build;
 import android.text.TextUtils;
 import android.util.Log;
 import android.util.TypedValue;
@@ -627,7 +628,7 @@
         rows.add(row);
     }
 
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     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/SoftInputWindow.java b/core/java/android/inputmethodservice/SoftInputWindow.java
index 795117e..b4b8887 100644
--- a/core/java/android/inputmethodservice/SoftInputWindow.java
+++ b/core/java/android/inputmethodservice/SoftInputWindow.java
@@ -16,15 +16,22 @@
 
 package android.inputmethodservice;
 
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import android.annotation.IntDef;
 import android.app.Dialog;
 import android.content.Context;
 import android.graphics.Rect;
+import android.os.Debug;
 import android.os.IBinder;
+import android.util.Log;
 import android.view.Gravity;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.WindowManager;
 
+import java.lang.annotation.Retention;
+
 /**
  * A SoftInputWindow is a Dialog that is intended to be used for a top-level input
  * method window.  It will be displayed along the edge of the screen, moving
@@ -33,6 +40,9 @@
  * @hide
  */
 public class SoftInputWindow extends Dialog {
+    private static final boolean DEBUG = false;
+    private static final String TAG = "SoftInputWindow";
+
     final String mName;
     final Callback mCallback;
     final KeyEvent.Callback mKeyEventCallback;
@@ -42,16 +52,65 @@
     final boolean mTakesFocus;
     private final Rect mBounds = new Rect();
 
+    @Retention(SOURCE)
+    @IntDef(value = {SoftInputWindowState.TOKEN_PENDING, SoftInputWindowState.TOKEN_SET,
+            SoftInputWindowState.SHOWN_AT_LEAST_ONCE, SoftInputWindowState.REJECTED_AT_LEAST_ONCE})
+    private @interface SoftInputWindowState {
+        /**
+         * The window token is not set yet.
+         */
+        int TOKEN_PENDING = 0;
+        /**
+         * The window token was set, but the window is not shown yet.
+         */
+        int TOKEN_SET = 1;
+        /**
+         * The window was shown at least once.
+         */
+        int SHOWN_AT_LEAST_ONCE = 2;
+        /**
+         * {@link android.view.WindowManager.BadTokenException} was sent when calling
+         * {@link Dialog#show()} at least once.
+         */
+        int REJECTED_AT_LEAST_ONCE = 3;
+        /**
+         * The window is considered destroyed.  Any incoming request should be ignored.
+         */
+        int DESTROYED = 4;
+    }
+
+    @SoftInputWindowState
+    private int mWindowState = SoftInputWindowState.TOKEN_PENDING;
+
     public interface Callback {
         public void onBackPressed();
     }
 
     public void setToken(IBinder token) {
-        WindowManager.LayoutParams lp = getWindow().getAttributes();
-        lp.token = token;
-        getWindow().setAttributes(lp);
+        switch (mWindowState) {
+            case SoftInputWindowState.TOKEN_PENDING:
+                // Normal scenario.  Nothing to worry about.
+                WindowManager.LayoutParams lp = getWindow().getAttributes();
+                lp.token = token;
+                getWindow().setAttributes(lp);
+                updateWindowState(SoftInputWindowState.TOKEN_SET);
+                return;
+            case SoftInputWindowState.TOKEN_SET:
+            case SoftInputWindowState.SHOWN_AT_LEAST_ONCE:
+            case SoftInputWindowState.REJECTED_AT_LEAST_ONCE:
+                throw new IllegalStateException("setToken can be called only once");
+            case SoftInputWindowState.DESTROYED:
+                // Just ignore.  Since there are multiple event queues from the token is issued
+                // in the system server to the timing when it arrives here, it can be delivered
+                // after the is already destroyed.  No one should be blamed because of such an
+                // unfortunate but possible scenario.
+                Log.i(TAG, "Ignoring setToken() because window is already destroyed.");
+                return;
+            default:
+                throw new IllegalStateException("Unexpected state=" + mWindowState);
+        }
     }
-    
+
     /**
      * Create a SoftInputWindow that uses a custom style.
      * 
@@ -190,4 +249,109 @@
 
         getWindow().setFlags(windowSetFlags, windowModFlags);
     }
+
+    @Override
+    public final void show() {
+        switch (mWindowState) {
+            case SoftInputWindowState.TOKEN_PENDING:
+                throw new IllegalStateException("Window token is not set yet.");
+            case SoftInputWindowState.TOKEN_SET:
+            case SoftInputWindowState.SHOWN_AT_LEAST_ONCE:
+                // Normal scenario.  Nothing to worry about.
+                try {
+                    super.show();
+                    updateWindowState(SoftInputWindowState.SHOWN_AT_LEAST_ONCE);
+                } catch (WindowManager.BadTokenException e) {
+                    // Just ignore this exception.  Since show() can be requested from other
+                    // components such as the system and there could be multiple event queues before
+                    // the request finally arrives here, the system may have already invalidated the
+                    // window token attached to our window.  In such a scenario, receiving
+                    // BadTokenException here is an expected behavior.  We just ignore it and update
+                    // the state so that we do not touch this window later.
+                    Log.i(TAG, "Probably the IME window token is already invalidated."
+                            + " show() does nothing.");
+                    updateWindowState(SoftInputWindowState.REJECTED_AT_LEAST_ONCE);
+                }
+                return;
+            case SoftInputWindowState.REJECTED_AT_LEAST_ONCE:
+                // Just ignore.  In general we cannot completely avoid this kind of race condition.
+                Log.i(TAG, "Not trying to call show() because it was already rejected once.");
+                return;
+            case SoftInputWindowState.DESTROYED:
+                // Just ignore.  In general we cannot completely avoid this kind of race condition.
+                Log.i(TAG, "Ignoring show() because the window is already destroyed.");
+                return;
+            default:
+                throw new IllegalStateException("Unexpected state=" + mWindowState);
+        }
+    }
+
+    final void dismissForDestroyIfNecessary() {
+        switch (mWindowState) {
+            case SoftInputWindowState.TOKEN_PENDING:
+            case SoftInputWindowState.TOKEN_SET:
+                // nothing to do because the window has never been shown.
+                updateWindowState(SoftInputWindowState.DESTROYED);
+                return;
+            case SoftInputWindowState.SHOWN_AT_LEAST_ONCE:
+                // Disable exit animation for the current IME window
+                // to avoid the race condition between the exit and enter animations
+                // when the current IME is being switched to another one.
+                try {
+                    getWindow().setWindowAnimations(0);
+                    dismiss();
+                } catch (WindowManager.BadTokenException e) {
+                    // Just ignore this exception.  Since show() can be requested from other
+                    // components such as the system and there could be multiple event queues before
+                    // the request finally arrives here, the system may have already invalidated the
+                    // window token attached to our window.  In such a scenario, receiving
+                    // BadTokenException here is an expected behavior.  We just ignore it and update
+                    // the state so that we do not touch this window later.
+                    Log.i(TAG, "Probably the IME window token is already invalidated. "
+                            + "No need to dismiss it.");
+                }
+                // Either way, consider that the window is destroyed.
+                updateWindowState(SoftInputWindowState.DESTROYED);
+                return;
+            case SoftInputWindowState.REJECTED_AT_LEAST_ONCE:
+                // Just ignore.  In general we cannot completely avoid this kind of race condition.
+                Log.i(TAG,
+                        "Not trying to dismiss the window because it is most likely unnecessary.");
+                // Anyway, consider that the window is destroyed.
+                updateWindowState(SoftInputWindowState.DESTROYED);
+                return;
+            case SoftInputWindowState.DESTROYED:
+                throw new IllegalStateException(
+                        "dismissForDestroyIfNecessary can be called only once");
+            default:
+                throw new IllegalStateException("Unexpected state=" + mWindowState);
+        }
+    }
+
+    private void updateWindowState(@SoftInputWindowState int newState) {
+        if (DEBUG) {
+            if (mWindowState != newState) {
+                Log.d(TAG, "WindowState: " + stateToString(mWindowState) + " -> "
+                        + stateToString(newState) + " @ " + Debug.getCaller());
+            }
+        }
+        mWindowState = newState;
+    }
+
+    private static String stateToString(@SoftInputWindowState int state) {
+        switch (state) {
+            case SoftInputWindowState.TOKEN_PENDING:
+                return "TOKEN_PENDING";
+            case SoftInputWindowState.TOKEN_SET:
+                return "TOKEN_SET";
+            case SoftInputWindowState.SHOWN_AT_LEAST_ONCE:
+                return "SHOWN_AT_LEAST_ONCE";
+            case SoftInputWindowState.REJECTED_AT_LEAST_ONCE:
+                return "REJECTED_AT_LEAST_ONCE";
+            case SoftInputWindowState.DESTROYED:
+                return "DESTROYED";
+            default:
+                throw new IllegalStateException("Unknown state=" + state);
+        }
+    }
 }
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index fd1e5f2..12b6f9e 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -21,6 +21,7 @@
 import android.annotation.TestApi;
 import android.annotation.UnsupportedAppUsage;
 import android.net.ConnectivityManager.NetworkCallback;
+import android.os.Build;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.ArraySet;
@@ -904,7 +905,7 @@
      *         specifier. See {@link #setNetworkSpecifier}.
      * @hide
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     public NetworkSpecifier getNetworkSpecifier() {
         return mNetworkSpecifier;
     }
diff --git a/core/java/android/net/NetworkFactory.java b/core/java/android/net/NetworkFactory.java
index 010d72f..9c836c3 100644
--- a/core/java/android/net/NetworkFactory.java
+++ b/core/java/android/net/NetworkFactory.java
@@ -211,7 +211,7 @@
      * Called for every request every time a new NetworkRequest is seen
      * and whenever the filterScore or filterNetworkCapabilities change.
      *
-     * acceptRequest can be overriden to provide complex filter behavior
+     * acceptRequest can be overridden to provide complex filter behavior
      * for the incoming requests
      *
      * For output, this class will call {@link #needNetworkFor} and
diff --git a/core/java/android/net/NetworkSpecifier.java b/core/java/android/net/NetworkSpecifier.java
index 9ce2a5b..be2f955 100644
--- a/core/java/android/net/NetworkSpecifier.java
+++ b/core/java/android/net/NetworkSpecifier.java
@@ -35,7 +35,7 @@
     public abstract boolean satisfiedBy(NetworkSpecifier other);
 
     /**
-     * Optional method which can be overriden by concrete implementations of NetworkSpecifier to
+     * Optional method which can be overridden by concrete implementations of NetworkSpecifier to
      * check a self-reported UID. A concrete implementation may contain a UID which would be self-
      * reported by the caller (since NetworkSpecifier implementations should be non-mutable). This
      * function is called by ConnectivityService and is passed the actual UID of the caller -
diff --git a/core/java/android/net/NetworkState.java b/core/java/android/net/NetworkState.java
index c545ee2..97fb3fb 100644
--- a/core/java/android/net/NetworkState.java
+++ b/core/java/android/net/NetworkState.java
@@ -17,6 +17,7 @@
 package android.net;
 
 import android.annotation.UnsupportedAppUsage;
+import android.os.Build;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.Slog;
@@ -34,7 +35,7 @@
     public final NetworkInfo networkInfo;
     public final LinkProperties linkProperties;
     public final NetworkCapabilities networkCapabilities;
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     public final Network network;
     public final String subscriberId;
     public final String networkId;
diff --git a/core/java/android/net/SSLCertificateSocketFactory.java b/core/java/android/net/SSLCertificateSocketFactory.java
index 31494d9..abc1cac 100644
--- a/core/java/android/net/SSLCertificateSocketFactory.java
+++ b/core/java/android/net/SSLCertificateSocketFactory.java
@@ -17,6 +17,7 @@
 package android.net;
 
 import android.annotation.UnsupportedAppUsage;
+import android.os.Build;
 import android.os.SystemProperties;
 import android.util.Log;
 
@@ -87,7 +88,7 @@
  * requires root access.
  */
 public class SSLCertificateSocketFactory extends SSLSocketFactory {
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private static final String TAG = "SSLCertificateSocketFactory";
 
     @UnsupportedAppUsage
@@ -384,7 +385,7 @@
      * @throws IllegalArgumentException if the socket was not created by this factory.
      * @hide
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     public byte[] getAlpnSelectedProtocol(Socket socket) {
         return castToOpenSSLSocket(socket).getAlpnSelectedProtocol();
     }
@@ -410,7 +411,7 @@
      *
      * @hide
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     public void setChannelIdPrivateKey(PrivateKey privateKey) {
         mChannelIdPrivateKey = privateKey;
     }
diff --git a/core/java/android/net/Uri.java b/core/java/android/net/Uri.java
index 9bcc600..40465ce 100644
--- a/core/java/android/net/Uri.java
+++ b/core/java/android/net/Uri.java
@@ -197,7 +197,7 @@
      *
      * <p>Example: "//www.google.com/search?q=android"
      *
-     * @return the decoded scheme-specific-part
+     * @return the encoded scheme-specific-part
      */
     public abstract String getEncodedSchemeSpecificPart();
 
diff --git a/core/java/android/nfc/NfcManager.java b/core/java/android/nfc/NfcManager.java
index 71199c9..030066e 100644
--- a/core/java/android/nfc/NfcManager.java
+++ b/core/java/android/nfc/NfcManager.java
@@ -19,6 +19,7 @@
 import android.annotation.SystemService;
 import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
+import android.os.Build;
 
 /**
  * High level manager used to obtain an instance of an {@link NfcAdapter}.
@@ -45,7 +46,7 @@
     /**
      * @hide
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     public NfcManager(Context context) {
         NfcAdapter adapter;
         context = context.getApplicationContext();
diff --git a/core/java/android/os/BaseBundle.java b/core/java/android/os/BaseBundle.java
index 0fef78d..3d4c00c 100644
--- a/core/java/android/os/BaseBundle.java
+++ b/core/java/android/os/BaseBundle.java
@@ -1601,12 +1601,13 @@
     private void readFromParcelInner(Parcel parcel, int length) {
         if (length < 0) {
             throw new RuntimeException("Bad length in parcel: " + length);
-
         } else if (length == 0) {
             // Empty Bundle or end of data.
             mParcelledData = NoImagePreloadHolder.EMPTY_PARCEL;
             mParcelledByNative = false;
             return;
+        } else if (length % 4 != 0) {
+            throw new IllegalStateException("Bundle length is not aligned by 4: " + length);
         }
 
         final int magic = parcel.readInt();
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index 347f60f..3c43fd18 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -16,6 +16,7 @@
 
 package android.os;
 
+import android.annotation.SystemApi;
 import android.annotation.TestApi;
 import android.app.admin.DevicePolicyManager;
 import android.content.Context;
@@ -165,6 +166,7 @@
      *
      * @hide
      */
+    @SystemApi
     public static File getOemDirectory() {
         return DIR_OEM_ROOT;
     }
@@ -175,6 +177,7 @@
      *
      * @hide
      */
+    @SystemApi
     public static File getOdmDirectory() {
         return DIR_ODM_ROOT;
     }
@@ -184,6 +187,7 @@
      * software that should persist across simple reflashing of the "system" partition.
      * @hide
      */
+    @SystemApi
     public static File getVendorDirectory() {
         return DIR_VENDOR_ROOT;
     }
@@ -194,6 +198,7 @@
      *
      * @hide
      */
+    @SystemApi
     public static File getProductDirectory() {
         return DIR_PRODUCT_ROOT;
     }
@@ -204,6 +209,7 @@
      *
      * @hide
      */
+    @SystemApi
     public static File getProductServicesDirectory() {
         return DIR_PRODUCT_SERVICES_ROOT;
     }
@@ -1063,7 +1069,6 @@
         return cur;
     }
 
-
     /**
      * If the given path exists on emulated external storage, return the
      * translated backing path hosted on internal storage. This bypasses any
@@ -1074,8 +1079,10 @@
      * must hold {@link android.Manifest.permission#WRITE_MEDIA_STORAGE}
      * permission.
      *
+     * @deprecated disabled now that FUSE has been replaced by sdcardfs
      * @hide
      */
+    @Deprecated
     public static File maybeTranslateEmulatedPathToInternal(File path) {
         return StorageManager.maybeTranslateEmulatedPathToInternal(path);
     }
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java
index 1c8029c..a9cb0d9 100644
--- a/core/java/android/os/FileUtils.java
+++ b/core/java/android/os/FileUtils.java
@@ -16,6 +16,18 @@
 
 package android.os;
 
+import static android.os.ParcelFileDescriptor.MODE_APPEND;
+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 android.os.ParcelFileDescriptor.MODE_WRITE_ONLY;
+import static android.system.OsConstants.O_APPEND;
+import static android.system.OsConstants.O_CREAT;
+import static android.system.OsConstants.O_RDONLY;
+import static android.system.OsConstants.O_RDWR;
+import static android.system.OsConstants.O_TRUNC;
+import static android.system.OsConstants.O_WRONLY;
 import static android.system.OsConstants.SPLICE_F_MORE;
 import static android.system.OsConstants.SPLICE_F_MOVE;
 import static android.system.OsConstants.S_ISFIFO;
@@ -1061,8 +1073,13 @@
                 mimeTypeFromExt = ContentResolver.MIME_TYPE_DEFAULT;
             }
 
-            final String extFromMimeType = MimeTypeMap.getSingleton().getExtensionFromMimeType(
-                    mimeType);
+            final String extFromMimeType;
+            if (ContentResolver.MIME_TYPE_DEFAULT.equals(mimeType)) {
+                extFromMimeType = null;
+            } else {
+                extFromMimeType = MimeTypeMap.getSingleton().getExtensionFromMimeType(mimeType);
+            }
+
             if (Objects.equals(mimeType, mimeTypeFromExt) || Objects.equals(ext, extFromMimeType)) {
                 // Extension maps back to requested MIME type; allow it
             } else {
@@ -1180,6 +1197,96 @@
     }
 
     /** {@hide} */
+    public static int translateModeStringToPosix(String mode) {
+        int res = 0;
+        if (mode.startsWith("rw")) {
+            res |= O_RDWR | O_CREAT;
+        } else if (mode.startsWith("w")) {
+            res |= O_WRONLY | O_CREAT;
+        } else if (mode.startsWith("r")) {
+            res |= O_RDONLY;
+        } else {
+            throw new IllegalArgumentException("Bad mode: " + mode);
+        }
+        if (mode.indexOf('t') != -1) {
+            res |= O_TRUNC;
+        }
+        if (mode.indexOf('a') != -1) {
+            res |= O_APPEND;
+        }
+        return res;
+    }
+
+    /** {@hide} */
+    public static String translateModePosixToString(int mode) {
+        String res = "";
+        if ((mode & O_RDWR) == O_RDWR) {
+            res += "rw";
+        } else if ((mode & O_WRONLY) == O_WRONLY) {
+            res += "w";
+        } else if ((mode & O_RDONLY) == O_RDONLY) {
+            res += "r";
+        } else {
+            throw new IllegalArgumentException("Bad mode: " + mode);
+        }
+        if ((mode & O_TRUNC) == O_TRUNC) {
+            res += "t";
+        }
+        if ((mode & O_APPEND) == O_APPEND) {
+            res += "a";
+        }
+        return res;
+    }
+
+    /** {@hide} */
+    public static int translateModePosixToPfd(int mode) {
+        int res = 0;
+        if ((mode & O_RDWR) == O_RDWR) {
+            res |= MODE_READ_WRITE;
+        } else if ((mode & O_WRONLY) == O_WRONLY) {
+            res |= MODE_WRITE_ONLY;
+        } else if ((mode & O_RDONLY) == O_RDONLY) {
+            res |= MODE_READ_ONLY;
+        } else {
+            throw new IllegalArgumentException("Bad mode: " + mode);
+        }
+        if ((mode & O_CREAT) == O_CREAT) {
+            res |= MODE_CREATE;
+        }
+        if ((mode & O_TRUNC) == O_TRUNC) {
+            res |= MODE_TRUNCATE;
+        }
+        if ((mode & O_APPEND) == O_APPEND) {
+            res |= MODE_APPEND;
+        }
+        return res;
+    }
+
+    /** {@hide} */
+    public static int translateModePfdToPosix(int mode) {
+        int res = 0;
+        if ((mode & MODE_READ_WRITE) == MODE_READ_WRITE) {
+            res |= O_RDWR;
+        } else if ((mode & MODE_WRITE_ONLY) == MODE_WRITE_ONLY) {
+            res |= O_WRONLY;
+        } else if ((mode & MODE_READ_ONLY) == MODE_READ_ONLY) {
+            res |= O_RDONLY;
+        } else {
+            throw new IllegalArgumentException("Bad mode: " + mode);
+        }
+        if ((mode & MODE_CREATE) == MODE_CREATE) {
+            res |= O_CREAT;
+        }
+        if ((mode & MODE_TRUNCATE) == MODE_TRUNCATE) {
+            res |= O_TRUNC;
+        }
+        if ((mode & MODE_APPEND) == MODE_APPEND) {
+            res |= O_APPEND;
+        }
+        return res;
+    }
+
+    /** {@hide} */
     @VisibleForTesting
     public static class MemoryPipe extends Thread implements AutoCloseable {
         private final FileDescriptor[] pipe;
diff --git a/core/java/android/os/Handler.java b/core/java/android/os/Handler.java
index 9b202f2..e03af9d 100644
--- a/core/java/android/os/Handler.java
+++ b/core/java/android/os/Handler.java
@@ -33,7 +33,7 @@
  * them as they come out of the message queue.
  * 
  * <p>There are two main uses for a Handler: (1) to schedule messages and
- * runnables to be executed as some point in the future; and (2) to enqueue
+ * runnables to be executed at some point in the future; and (2) to enqueue
  * an action to be performed on a different thread than your own.
  * 
  * <p>Scheduling messages is accomplished with the
diff --git a/core/java/android/os/Looper.java b/core/java/android/os/Looper.java
index f17e0f0..ded3a19 100644
--- a/core/java/android/os/Looper.java
+++ b/core/java/android/os/Looper.java
@@ -18,7 +18,6 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.os.LooperProto;
 import android.util.Log;
 import android.util.Printer;
 import android.util.Slog;
@@ -70,6 +69,7 @@
     // sThreadLocal.get() will return null unless you've called prepare().
     static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
     private static Looper sMainLooper;  // guarded by Looper.class
+    private static Observer sObserver;
 
     final MessageQueue mQueue;
     final Thread mThread;
@@ -131,6 +131,15 @@
     }
 
     /**
+     * Set the transaction observer for all Loopers in this process.
+     *
+     * @hide
+     */
+    public static void setObserver(@Nullable Observer observer) {
+        sObserver = observer;
+    }
+
+    /**
      * Run the message queue in this thread. Be sure to call
      * {@link #quit()} to end the loop.
      */
@@ -169,6 +178,8 @@
                 logging.println(">>>>> Dispatching to " + msg.target + " " +
                         msg.callback + ": " + msg.what);
             }
+            // Make sure the observer won't change while processing a transaction.
+            final Observer observer = sObserver;
 
             final long traceTag = me.mTraceTag;
             long slowDispatchThresholdMs = me.mSlowDispatchThresholdMs;
@@ -189,9 +200,21 @@
 
             final long dispatchStart = needStartTime ? SystemClock.uptimeMillis() : 0;
             final long dispatchEnd;
+            Object token = null;
+            if (observer != null) {
+                token = observer.messageDispatchStarting();
+            }
             try {
                 msg.target.dispatchMessage(msg);
+                if (observer != null) {
+                    observer.messageDispatched(token, msg);
+                }
                 dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;
+            } catch (Exception exception) {
+                if (observer != null) {
+                    observer.dispatchingThrewException(token, msg, exception);
+                }
+                throw exception;
             } finally {
                 if (traceTag != 0) {
                     Trace.traceEnd(traceTag);
@@ -386,7 +409,9 @@
         final long looperToken = proto.start(fieldId);
         proto.write(LooperProto.THREAD_NAME, mThread.getName());
         proto.write(LooperProto.THREAD_ID, mThread.getId());
-        mQueue.writeToProto(proto, LooperProto.QUEUE);
+        if (mQueue != null) {
+            mQueue.writeToProto(proto, LooperProto.QUEUE);
+        }
         proto.end(looperToken);
     }
 
@@ -395,4 +420,39 @@
         return "Looper (" + mThread.getName() + ", tid " + mThread.getId()
                 + ") {" + Integer.toHexString(System.identityHashCode(this)) + "}";
     }
+
+    /** {@hide} */
+    public interface Observer {
+        /**
+         * Called right before a message is dispatched.
+         *
+         * <p> The token type is not specified to allow the implementation to specify its own type.
+         *
+         * @return a token used for collecting telemetry when dispatching a single message.
+         *         The token token must be passed back exactly once to either
+         *         {@link Observer#messageDispatched} or {@link Observer#dispatchingThrewException}
+         *         and must not be reused again.
+         *
+         */
+        Object messageDispatchStarting();
+
+        /**
+         * Called when a message was processed by a Handler.
+         *
+         * @param token Token obtained by previously calling
+         *              {@link Observer#messageDispatchStarting} on the same Observer instance.
+         * @param msg The message that was dispatched.
+         */
+        void messageDispatched(Object token, Message msg);
+
+        /**
+         * Called when an exception was thrown while processing a message.
+         *
+         * @param token Token obtained by previously calling
+         *              {@link Observer#messageDispatchStarting} on the same Observer instance.
+         * @param msg The message that was dispatched and caused an exception.
+         * @param exception The exception that was thrown.
+         */
+        void dispatchingThrewException(Object token, Message msg, Exception exception);
+    }
 }
diff --git a/core/java/android/os/ParcelFileDescriptor.java b/core/java/android/os/ParcelFileDescriptor.java
index c9edc53..a54c589 100644
--- a/core/java/android/os/ParcelFileDescriptor.java
+++ b/core/java/android/os/ParcelFileDescriptor.java
@@ -559,28 +559,7 @@
      * @throws IllegalArgumentException if the given string does not match a known file mode.
      */
     public static int parseMode(String mode) {
-        final int modeBits;
-        if ("r".equals(mode)) {
-            modeBits = ParcelFileDescriptor.MODE_READ_ONLY;
-        } else if ("w".equals(mode) || "wt".equals(mode)) {
-            modeBits = ParcelFileDescriptor.MODE_WRITE_ONLY
-                    | ParcelFileDescriptor.MODE_CREATE
-                    | ParcelFileDescriptor.MODE_TRUNCATE;
-        } else if ("wa".equals(mode)) {
-            modeBits = ParcelFileDescriptor.MODE_WRITE_ONLY
-                    | ParcelFileDescriptor.MODE_CREATE
-                    | ParcelFileDescriptor.MODE_APPEND;
-        } else if ("rw".equals(mode)) {
-            modeBits = ParcelFileDescriptor.MODE_READ_WRITE
-                    | ParcelFileDescriptor.MODE_CREATE;
-        } else if ("rwt".equals(mode)) {
-            modeBits = ParcelFileDescriptor.MODE_READ_WRITE
-                    | ParcelFileDescriptor.MODE_CREATE
-                    | ParcelFileDescriptor.MODE_TRUNCATE;
-        } else {
-            throw new IllegalArgumentException("Bad mode '" + mode + "'");
-        }
-        return modeBits;
+        return FileUtils.translateModePosixToPfd(FileUtils.translateModeStringToPosix(mode));
     }
 
     /**
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 7caf0b1..5cd2ffc 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -16,6 +16,8 @@
 
 package android.os;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.TestApi;
 import android.system.Os;
 import android.system.OsConstants;
@@ -475,6 +477,7 @@
      * @param instructionSet null-ok the instruction set to use.
      * @param appDataDir null-ok the data directory of the app.
      * @param invokeWith null-ok the command to invoke with.
+     * @param packageName null-ok the name of the package this process belongs to.
      * @param zygoteArgs Additional arguments to supply to the zygote process.
      * 
      * @return An object that describes the result of the attempt to start the process.
@@ -482,36 +485,36 @@
      * 
      * {@hide}
      */
-    public static final ProcessStartResult start(final String processClass,
-                                  final String niceName,
-                                  int uid, int gid, int[] gids,
+    public static final ProcessStartResult start(@NonNull final String processClass,
+                                  @Nullable final String niceName,
+                                  int uid, int gid, @Nullable int[] gids,
                                   int runtimeFlags, int mountExternal,
                                   int targetSdkVersion,
-                                  String seInfo,
-                                  String abi,
-                                  String instructionSet,
-                                  String appDataDir,
-                                  String invokeWith,
-                                  String packageName,
-                                  String[] zygoteArgs) {
+                                  @Nullable String seInfo,
+                                  @NonNull String abi,
+                                  @Nullable String instructionSet,
+                                  @Nullable String appDataDir,
+                                  @Nullable String invokeWith,
+                                  @Nullable String packageName,
+                                  @Nullable String[] zygoteArgs) {
         return zygoteProcess.start(processClass, niceName, uid, gid, gids,
                     runtimeFlags, mountExternal, targetSdkVersion, seInfo,
                     abi, instructionSet, appDataDir, invokeWith, packageName, zygoteArgs);
     }
 
     /** @hide */
-    public static final ProcessStartResult startWebView(final String processClass,
-                                  final String niceName,
-                                  int uid, int gid, int[] gids,
+    public static final ProcessStartResult startWebView(@NonNull final String processClass,
+                                  @Nullable final String niceName,
+                                  int uid, int gid, @Nullable int[] gids,
                                   int runtimeFlags, int mountExternal,
                                   int targetSdkVersion,
-                                  String seInfo,
-                                  String abi,
-                                  String instructionSet,
-                                  String appDataDir,
-                                  String invokeWith,
-                                  String packageName,
-                                  String[] zygoteArgs) {
+                                  @Nullable String seInfo,
+                                  @NonNull String abi,
+                                  @Nullable String instructionSet,
+                                  @Nullable String appDataDir,
+                                  @Nullable String invokeWith,
+                                  @Nullable String packageName,
+                                  @Nullable String[] zygoteArgs) {
         return WebViewZygote.getProcess().start(processClass, niceName, uid, gid, gids,
                     runtimeFlags, mountExternal, targetSdkVersion, seInfo,
                     abi, instructionSet, appDataDir, invokeWith, packageName, zygoteArgs);
diff --git a/core/java/android/os/StatsLogEventWrapper.java b/core/java/android/os/StatsLogEventWrapper.java
index 7b3ea57..b13bcac 100644
--- a/core/java/android/os/StatsLogEventWrapper.java
+++ b/core/java/android/os/StatsLogEventWrapper.java
@@ -127,6 +127,15 @@
     }
 
     /**
+     * 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);
+    }
+
+    /**
      * Writes the stored fields to a byte array. Will first write a new-line character to denote
      * END_LIST before writing contents to byte array.
      */
diff --git a/core/java/android/os/UserHandle.java b/core/java/android/os/UserHandle.java
index 995156a..4fe2d58 100644
--- a/core/java/android/os/UserHandle.java
+++ b/core/java/android/os/UserHandle.java
@@ -38,12 +38,16 @@
     public static final @UserIdInt int USER_ALL = -1;
 
     /** @hide A user handle to indicate all users on the device */
+    @SystemApi
+    @TestApi
     public static final UserHandle ALL = new UserHandle(USER_ALL);
 
     /** @hide A user id to indicate the currently active user */
     public static final @UserIdInt int USER_CURRENT = -2;
 
     /** @hide A user handle to indicate the current user of the device */
+    @SystemApi
+    @TestApi
     public static final UserHandle CURRENT = new UserHandle(USER_CURRENT);
 
     /** @hide A user id to indicate that we would like to send to the current
@@ -83,6 +87,7 @@
     public static final int USER_SERIAL_SYSTEM = 0;
 
     /** @hide A user handle to indicate the "system" user of the device */
+    @SystemApi
     @TestApi
     public static final UserHandle SYSTEM = new UserHandle(USER_SYSTEM);
 
diff --git a/core/java/android/os/ZygoteProcess.java b/core/java/android/os/ZygoteProcess.java
index 732d377..99181ac 100644
--- a/core/java/android/os/ZygoteProcess.java
+++ b/core/java/android/os/ZygoteProcess.java
@@ -16,6 +16,8 @@
 
 package android.os;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.net.LocalSocket;
 import android.net.LocalSocketAddress;
 import android.util.Log;
@@ -212,23 +214,24 @@
      * @param instructionSet null-ok the instruction set to use.
      * @param appDataDir null-ok the data directory of the app.
      * @param invokeWith null-ok the command to invoke with.
+     * @param packageName null-ok the name of the package this process belongs to.
      * @param zygoteArgs Additional arguments to supply to the zygote process.
      *
      * @return An object that describes the result of the attempt to start the process.
      * @throws RuntimeException on fatal start failure
      */
-    public final Process.ProcessStartResult start(final String processClass,
+    public final Process.ProcessStartResult start(@NonNull final String processClass,
                                                   final String niceName,
-                                                  int uid, int gid, int[] gids,
+                                                  int uid, int gid, @Nullable int[] gids,
                                                   int runtimeFlags, int mountExternal,
                                                   int targetSdkVersion,
-                                                  String seInfo,
-                                                  String abi,
-                                                  String instructionSet,
-                                                  String appDataDir,
-                                                  String invokeWith,
-                                                  String packageName,
-                                                  String[] zygoteArgs) {
+                                                  @Nullable String seInfo,
+                                                  @NonNull String abi,
+                                                  @Nullable String instructionSet,
+                                                  @Nullable String appDataDir,
+                                                  @Nullable String invokeWith,
+                                                  @Nullable String packageName,
+                                                  @Nullable String[] zygoteArgs) {
         try {
             return startViaZygote(processClass, niceName, uid, gid, gids,
                     runtimeFlags, mountExternal, targetSdkVersion, seInfo,
@@ -351,24 +354,25 @@
      * @param appDataDir null-ok the data directory of the app.
      * @param startChildZygote Start a sub-zygote. This creates a new zygote process
      * that has its state cloned from this zygote process.
+     * @param packageName null-ok the name of the package this process belongs to.
      * @param extraArgs Additional arguments to supply to the zygote process.
      * @return An object that describes the result of the attempt to start the process.
      * @throws ZygoteStartFailedEx if process start failed for any reason
      */
-    private Process.ProcessStartResult startViaZygote(final String processClass,
-                                                      final String niceName,
+    private Process.ProcessStartResult startViaZygote(@NonNull final String processClass,
+                                                      @Nullable final String niceName,
                                                       final int uid, final int gid,
-                                                      final int[] gids,
+                                                      @Nullable final int[] gids,
                                                       int runtimeFlags, int mountExternal,
                                                       int targetSdkVersion,
-                                                      String seInfo,
-                                                      String abi,
-                                                      String instructionSet,
-                                                      String appDataDir,
-                                                      String invokeWith,
+                                                      @Nullable String seInfo,
+                                                      @NonNull String abi,
+                                                      @Nullable String instructionSet,
+                                                      @Nullable String appDataDir,
+                                                      @Nullable String invokeWith,
                                                       boolean startChildZygote,
-                                                      String packageName,
-                                                      String[] extraArgs)
+                                                      @Nullable String packageName,
+                                                      @Nullable String[] extraArgs)
                                                       throws ZygoteStartFailedEx {
         ArrayList<String> argsForZygote = new ArrayList<String>();
 
diff --git a/core/java/android/os/health/SystemHealthManager.java b/core/java/android/os/health/SystemHealthManager.java
index f303674..71eda19 100644
--- a/core/java/android/os/health/SystemHealthManager.java
+++ b/core/java/android/os/health/SystemHealthManager.java
@@ -20,6 +20,7 @@
 import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.os.BatteryStats;
+import android.os.Build;
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -65,7 +66,7 @@
      *
      * @hide
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     public static SystemHealthManager from(Context context) {
         return (SystemHealthManager)context.getSystemService(Context.SYSTEM_HEALTH_SERVICE);
     }
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index 8d5017b..50ca4ab 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -1521,7 +1521,11 @@
         return SystemProperties.getBoolean(PROP_HAS_ADOPTABLE, false);
     }
 
-    /** {@hide} */
+    /**
+     * @deprecated disabled now that FUSE has been replaced by sdcardfs
+     * @hide
+     */
+    @Deprecated
     public static File maybeTranslateEmulatedPathToInternal(File path) {
         // Disabled now that FUSE has been replaced by sdcardfs
         return path;
diff --git a/core/java/android/os/storage/StorageVolume.java b/core/java/android/os/storage/StorageVolume.java
index deff693..5bef7ee 100644
--- a/core/java/android/os/storage/StorageVolume.java
+++ b/core/java/android/os/storage/StorageVolume.java
@@ -22,6 +22,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.net.Uri;
+import android.os.Build;
 import android.os.Environment;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -249,7 +250,7 @@
     }
 
     /** {@hide} */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     public UserHandle getOwner() {
         return mOwner;
     }
diff --git a/core/java/android/preference/Preference.java b/core/java/android/preference/Preference.java
index 98b69a8..2387657 100644
--- a/core/java/android/preference/Preference.java
+++ b/core/java/android/preference/Preference.java
@@ -27,6 +27,7 @@
 import android.content.SharedPreferences;
 import android.content.res.TypedArray;
 import android.graphics.drawable.Drawable;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -1167,7 +1168,7 @@
      * @return True if the Preference handled the key. Returns false by default.
      * @hide
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     public boolean onKey(View v, int keyCode, KeyEvent event) {
         return false;
     }
diff --git a/core/java/android/preference/PreferenceManager.java b/core/java/android/preference/PreferenceManager.java
index c76c8d3..dfee1af 100644
--- a/core/java/android/preference/PreferenceManager.java
+++ b/core/java/android/preference/PreferenceManager.java
@@ -30,6 +30,7 @@
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ResolveInfo;
 import android.content.res.XmlResourceParser;
+import android.os.Build;
 import android.os.Bundle;
 import android.util.Log;
 
@@ -68,7 +69,7 @@
      * Fragment that owns this instance.
      */
     @Nullable
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private PreferenceFragment mFragment;
 
     /**
@@ -201,7 +202,7 @@
     /**
      * Sets the owning preference fragment
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     void setFragment(PreferenceFragment fragment) {
         mFragment = fragment;
     }
diff --git a/core/java/android/preference/SeekBarVolumizer.java b/core/java/android/preference/SeekBarVolumizer.java
index e8daf21..a871425 100644
--- a/core/java/android/preference/SeekBarVolumizer.java
+++ b/core/java/android/preference/SeekBarVolumizer.java
@@ -104,7 +104,7 @@
 
     @UnsupportedAppUsage
     public SeekBarVolumizer(Context context, int streamType, Uri defaultUri, Callback callback) {
-        this(context, streamType, defaultUri, callback, true /* playSample */);
+        this(context, streamType, defaultUri, callback, false /* playSample */);
     }
 
     public SeekBarVolumizer(
diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java
index b12d9cf..ee64ca2 100644
--- a/core/java/android/provider/DocumentsContract.java
+++ b/core/java/android/provider/DocumentsContract.java
@@ -1555,7 +1555,7 @@
      *
      * <p>Note, that due to internal limitations, if there is already a web link
      * intent created for the specified document but with different options,
-     * then it may be overriden.
+     * then it may be overridden.
      *
      * <p>Providers are required to show confirmation UI for all new permissions granted
      * for the linked document.
diff --git a/core/java/android/provider/DocumentsProvider.java b/core/java/android/provider/DocumentsProvider.java
index 81b1921..0e782d7 100644
--- a/core/java/android/provider/DocumentsProvider.java
+++ b/core/java/android/provider/DocumentsProvider.java
@@ -771,7 +771,7 @@
     }
 
     /**
-     * Implementation is provided by the parent class. Cannot be overriden.
+     * Implementation is provided by the parent class. Cannot be overridden.
      *
      * @see #queryRoots(String[])
      * @see #queryRecentDocuments(String, String[])
@@ -828,7 +828,7 @@
     }
 
     /**
-     * Implementation is provided by the parent class. Cannot be overriden.
+     * Implementation is provided by the parent class. Cannot be overridden.
      *
      * @see #getDocumentType(String)
      */
@@ -903,7 +903,7 @@
 
     /**
      * Implementation is provided by the parent class. Throws by default, and
-     * cannot be overriden.
+     * cannot be overridden.
      *
      * @see #createDocument(String, String, String)
      */
@@ -914,7 +914,7 @@
 
     /**
      * Implementation is provided by the parent class. Throws by default, and
-     * cannot be overriden.
+     * cannot be overridden.
      *
      * @see #deleteDocument(String)
      */
@@ -925,7 +925,7 @@
 
     /**
      * Implementation is provided by the parent class. Throws by default, and
-     * cannot be overriden.
+     * cannot be overridden.
      */
     @Override
     public final int update(
@@ -1165,7 +1165,7 @@
     }
 
     /**
-     * Implementation is provided by the parent class. Cannot be overriden.
+     * Implementation is provided by the parent class. Cannot be overridden.
      *
      * @see #openDocument(String, String, CancellationSignal)
      */
@@ -1176,7 +1176,7 @@
     }
 
     /**
-     * Implementation is provided by the parent class. Cannot be overriden.
+     * Implementation is provided by the parent class. Cannot be overridden.
      *
      * @see #openDocument(String, String, CancellationSignal)
      */
@@ -1188,7 +1188,7 @@
     }
 
     /**
-     * Implementation is provided by the parent class. Cannot be overriden.
+     * Implementation is provided by the parent class. Cannot be overridden.
      *
      * @see #openDocument(String, String, CancellationSignal)
      */
@@ -1202,7 +1202,7 @@
     }
 
     /**
-     * Implementation is provided by the parent class. Cannot be overriden.
+     * Implementation is provided by the parent class. Cannot be overridden.
      *
      * @see #openDocument(String, String, CancellationSignal)
      */
@@ -1216,7 +1216,7 @@
     }
 
     /**
-     * Implementation is provided by the parent class. Cannot be overriden.
+     * Implementation is provided by the parent class. Cannot be overridden.
      *
      * @see #openDocumentThumbnail(String, Point, CancellationSignal)
      * @see #openTypedDocument(String, String, Bundle, CancellationSignal)
@@ -1229,7 +1229,7 @@
     }
 
     /**
-     * Implementation is provided by the parent class. Cannot be overriden.
+     * Implementation is provided by the parent class. Cannot be overridden.
      *
      * @see #openDocumentThumbnail(String, Point, CancellationSignal)
      * @see #openTypedDocument(String, String, Bundle, CancellationSignal)
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index 189b7b4..82459b1 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -717,7 +717,11 @@
             /**
              * The picasa id of the image
              * <P>Type: TEXT</P>
+             *
+             * @deprecated this value was only relevant for images hosted on
+             *             Picasa, which are no longer supported.
              */
+            @Deprecated
             public static final String PICASA_ID = "picasa_id";
 
             /**
@@ -755,7 +759,12 @@
             /**
              * The mini thumb id.
              * <P>Type: INTEGER</P>
+             *
+             * @deprecated all thumbnails should be obtained via
+             *             {@link Images.Thumbnails#getThumbnail}, as this
+             *             value is no longer supported.
              */
+            @Deprecated
             public static final String MINI_THUMB_MAGIC = "mini_thumb_magic";
 
             /**
@@ -1947,7 +1956,12 @@
             /**
              * The mini thumb id.
              * <P>Type: INTEGER</P>
+             *
+             * @deprecated all thumbnails should be obtained via
+             *             {@link Images.Thumbnails#getThumbnail}, as this
+             *             value is no longer supported.
              */
+            @Deprecated
             public static final String MINI_THUMB_MAGIC = "mini_thumb_magic";
 
             /**
diff --git a/core/java/android/provider/SearchIndexablesProvider.java b/core/java/android/provider/SearchIndexablesProvider.java
index 138e77b..02a5e6f 100644
--- a/core/java/android/provider/SearchIndexablesProvider.java
+++ b/core/java/android/provider/SearchIndexablesProvider.java
@@ -181,7 +181,7 @@
     }
 
     /**
-     * Implementation is provided by the parent class. Throws by default, and cannot be overriden.
+     * Implementation is provided by the parent class. Throws by default, and cannot be overridden.
      */
     @Override
     public final Uri insert(Uri uri, ContentValues values) {
@@ -189,7 +189,7 @@
     }
 
     /**
-     * Implementation is provided by the parent class. Throws by default, and cannot be overriden.
+     * Implementation is provided by the parent class. Throws by default, and cannot be overridden.
      */
     @Override
     public final int delete(Uri uri, String selection, String[] selectionArgs) {
@@ -197,7 +197,7 @@
     }
 
     /**
-     * Implementation is provided by the parent class. Throws by default, and cannot be overriden.
+     * Implementation is provided by the parent class. Throws by default, and cannot be overridden.
      */
     @Override
     public final int update(
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index a1cc67d..026195e 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -6508,6 +6508,25 @@
         public static final String MULTI_PRESS_TIMEOUT = "multi_press_timeout";
 
         /**
+         * Whether the user specifies a minimum ui timeout to override minimum ui timeout of
+         * accessibility service
+         *
+         * Type: int (0 for false, 1 for true)
+         * @hide
+         */
+        public static final String ACCESSIBILITY_MINIMUM_UI_TIMEOUT_ENABLED =
+                "accessibility_minimum_ui_timeout_enabled";
+
+        /**
+         * Setting that specifies ui minimum timeout in milliseconds.
+         *
+         * @see #ACCESSIBILITY_MINIMUM_UI_TIMEOUT_ENABLED
+         * @hide
+         */
+        public static final String ACCESSIBILITY_MINIMUM_UI_TIMEOUT_MS =
+                "accessibility_minimum_ui_timeout_ms";
+
+        /**
          * List of the enabled print services.
          *
          * N and beyond uses {@link #DISABLED_PRINT_SERVICES}. But this might be used in an upgrade
@@ -7256,6 +7275,14 @@
         private static final Validator DOZE_REACH_GESTURE_VALIDATOR = BOOLEAN_VALIDATOR;
 
         /**
+         * Gesture that wakes up the display, showing the ambient version of the status bar.
+         * @hide
+         */
+        public static final String DOZE_WAKE_SCREEN_GESTURE = "doze_wake_screen_gesture";
+
+        private static final Validator DOZE_WAKE_SCREEN_GESTURE_VALIDATOR = BOOLEAN_VALIDATOR;
+
+        /**
          * The current night mode that has been selected by the user.  Owned
          * and controlled by UiModeManagerService.  Constants are as per
          * UiModeManager.
@@ -8158,6 +8185,7 @@
             DOZE_PICK_UP_GESTURE,
             DOZE_DOUBLE_TAP_GESTURE,
             DOZE_REACH_GESTURE,
+            DOZE_WAKE_SCREEN_GESTURE,
             NFC_PAYMENT_DEFAULT_COMPONENT,
             AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN,
             FACE_UNLOCK_KEYGUARD_ENABLED,
@@ -8186,6 +8214,8 @@
             ZEN_SETTINGS_SUGGESTION_VIEWED,
             CHARGING_SOUNDS_ENABLED,
             CHARGING_VIBRATION_ENABLED,
+            ACCESSIBILITY_MINIMUM_UI_TIMEOUT_ENABLED,
+            ACCESSIBILITY_MINIMUM_UI_TIMEOUT_MS,
         };
 
         /**
@@ -8302,6 +8332,7 @@
             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(DOZE_WAKE_SCREEN_GESTURE, DOZE_WAKE_SCREEN_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);
@@ -8339,6 +8370,8 @@
             VALIDATORS.put(ZEN_SETTINGS_SUGGESTION_VIEWED, BOOLEAN_VALIDATOR);
             VALIDATORS.put(CHARGING_SOUNDS_ENABLED, BOOLEAN_VALIDATOR);
             VALIDATORS.put(CHARGING_VIBRATION_ENABLED, BOOLEAN_VALIDATOR);
+            VALIDATORS.put(ACCESSIBILITY_MINIMUM_UI_TIMEOUT_ENABLED, BOOLEAN_VALIDATOR);
+            VALIDATORS.put(ACCESSIBILITY_MINIMUM_UI_TIMEOUT_MS, NON_NEGATIVE_INTEGER_VALIDATOR);
         }
 
         /**
@@ -13308,6 +13341,36 @@
          * @hide
          */
         public static final String BINDER_CALLS_STATS = "binder_calls_stats";
+
+        /**
+         * Looper stats settings.
+         *
+         * The following strings are supported as keys:
+         * <pre>
+         *     enabled              (boolean)
+         *     sampling_interval    (int)
+         * </pre>
+         *
+         * @hide
+         */
+        public static final String LOOPER_STATS = "looper_stats";
+
+        /**
+         * Default user id to boot into. They map to user ids, for example, 10, 11, 12.
+         *
+         * @hide
+         */
+        public static final String DEFAULT_USER_ID_TO_BOOT_INTO = "default_boot_into_user_id";
+
+        /**
+         * Persistent user id that is last logged in to.
+         *
+         * They map to user ids, for example, 10, 11, 12.
+         *
+         * @hide
+         */
+        public static final String LAST_ACTIVE_USER_ID = "last_active_persistent_user_id";
+
     }
 
     /**
diff --git a/core/java/android/service/autofill/CharSequenceTransformation.java b/core/java/android/service/autofill/CharSequenceTransformation.java
index f52ac85..271707a 100644
--- a/core/java/android/service/autofill/CharSequenceTransformation.java
+++ b/core/java/android/service/autofill/CharSequenceTransformation.java
@@ -78,7 +78,7 @@
             int childViewId) throws Exception {
         final StringBuilder converted = new StringBuilder();
         final int size = mFields.size();
-        if (sDebug) Log.d(TAG, size + " multiple fields on id " + childViewId);
+        if (sDebug) Log.d(TAG, size + " fields on id " + childViewId);
         for (Entry<AutofillId, Pair<Pattern, String>> entry : mFields.entrySet()) {
             final AutofillId id = entry.getKey();
             final Pair<Pattern, String> field = entry.getValue();
@@ -90,7 +90,7 @@
             try {
                 final Matcher matcher = field.first.matcher(value);
                 if (!matcher.find()) {
-                    if (sDebug) Log.d(TAG, "match for " + field.first + " failed on id " + id);
+                    if (sDebug) Log.d(TAG, "Match for " + field.first + " failed on id " + id);
                     return;
                 }
                 // replaceAll throws an exception if the subst is invalid
@@ -103,6 +103,9 @@
                 throw e;
             }
         }
+        // Cannot log converted, it might have PII
+        Log.d(TAG, "Converting text on child " + childViewId + " to " + converted.length()
+                + "_chars");
         parentTemplate.setCharSequence(childViewId, "setText", converted);
     }
 
diff --git a/core/java/android/service/autofill/CustomDescription.java b/core/java/android/service/autofill/CustomDescription.java
index b1ae7a5..fdbb1c2 100644
--- a/core/java/android/service/autofill/CustomDescription.java
+++ b/core/java/android/service/autofill/CustomDescription.java
@@ -314,7 +314,8 @@
          * 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.
+         * @param action action to be performed. Must be an an implementation provided by the
+         * Android System.
          *
          * @return this builder
          *
diff --git a/core/java/android/service/autofill/OnClickAction.java b/core/java/android/service/autofill/OnClickAction.java
index 7439b00..8597a88 100644
--- a/core/java/android/service/autofill/OnClickAction.java
+++ b/core/java/android/service/autofill/OnClickAction.java
@@ -21,6 +21,9 @@
  *
  * <p>Typically used to switch the visibility of other views in a
  * {@link CustomDescription custom save UI}.
+ *
+ * <p><b>Note:</b> This interface is not meant to be implemented by app developers; only
+ * implementations provided by the Android System can be used in other Autofill APIs.
  */
 public interface OnClickAction {
 }
diff --git a/core/java/android/service/autofill/Sanitizer.java b/core/java/android/service/autofill/Sanitizer.java
index 38757ac..8a1310d 100644
--- a/core/java/android/service/autofill/Sanitizer.java
+++ b/core/java/android/service/autofill/Sanitizer.java
@@ -21,6 +21,9 @@
  * <p>Typically used to avoid displaying the save UI for values that are autofilled but reformatted
  * by the app&mdash;for example, if the autofill service sends a credit card number
  * value as "004815162342108" and the app automatically changes it to "0048 1516 2342 108".
+ *
+ * <p><b>Note:</b> This interface is not meant to be implemented by app developers; only
+ * implementations provided by the Android System can be used in other Autofill APIs.
  */
 public interface Sanitizer {
 }
diff --git a/core/java/android/service/autofill/Transformation.java b/core/java/android/service/autofill/Transformation.java
index aa8bc9b..de43955 100644
--- a/core/java/android/service/autofill/Transformation.java
+++ b/core/java/android/service/autofill/Transformation.java
@@ -20,6 +20,9 @@
  * template} at runtime, using the values of fields contained in the screen.
  *
  * <p>Typically used by {@link CustomDescription} to provide a customized autofill save UI.
+ *
+ * <p><b>Note:</b> This interface is not meant to be implemented by app developers; only
+ * implementations provided by the Android System can be used in other Autofill APIs.
  */
 public interface Transformation {
 }
diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java
index 15b2aae..38de794 100644
--- a/core/java/android/service/dreams/DreamService.java
+++ b/core/java/android/service/dreams/DreamService.java
@@ -27,6 +27,7 @@
 import android.content.Intent;
 import android.graphics.PixelFormat;
 import android.graphics.drawable.ColorDrawable;
+import android.os.Build;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.IRemoteCallback;
@@ -626,7 +627,7 @@
      * @see #startDozing
      * @hide For use by system UI components only.
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     public boolean canDoze() {
         return mCanDoze;
     }
@@ -694,7 +695,7 @@
      * @see #startDozing
      * @hide For use by system UI components only.
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     public void stopDozing() {
         if (mDozing) {
             mDozing = false;
@@ -716,7 +717,7 @@
      * @see #setDozing(boolean)
      * @hide For use by system UI components only.
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     public boolean isDozing() {
         return mDozing;
     }
diff --git a/core/java/android/service/notification/NotificationAssistantService.java b/core/java/android/service/notification/NotificationAssistantService.java
index 3b820ca..26240c5 100644
--- a/core/java/android/service/notification/NotificationAssistantService.java
+++ b/core/java/android/service/notification/NotificationAssistantService.java
@@ -52,6 +52,9 @@
  * {@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.
+ * <p>
+ *     All callbacks are called on the main thread.
+ * </p>
  *
  * @hide
  */
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index 1b588f4..d7fe15d 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -91,6 +91,10 @@
  * notification listeners running in a work profile. A
  * {@link android.app.admin.DevicePolicyManager} might block notifications originating from a work
  * profile.</p>
+ * <p>
+ *     From {@link Build.VERSION_CODES#N} onward all callbacks are called on the main thread. Prior
+ *     to N, there is no guarantee on what thread the callback will happen.
+ * </p>
  */
 public abstract class NotificationListenerService extends Service {
 
@@ -276,7 +280,7 @@
 
     private final Object mLock = new Object();
 
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private Handler mHandler;
 
     /** @hide */
@@ -985,6 +989,21 @@
     }
 
     /**
+     * Clears listener hints set via {@link #getCurrentListenerHints()}.
+     *
+     * <p>The service should wait for the {@link #onListenerConnected()} event
+     * before performing this operation.
+     */
+    public final void clearRequestedListenerHints() {
+        if (!isBound()) return;
+        try {
+            getNotificationInterface().clearRequestedListenerHints(mWrapper);
+        } catch (android.os.RemoteException ex) {
+            Log.v(TAG, "Unable to contact notification manager", ex);
+        }
+    }
+
+    /**
      * Sets the desired {@link #getCurrentListenerHints() listener hints}.
      *
      * <p>
diff --git a/core/java/android/service/notification/StatusBarNotification.java b/core/java/android/service/notification/StatusBarNotification.java
index dd97d52..84826e0 100644
--- a/core/java/android/service/notification/StatusBarNotification.java
+++ b/core/java/android/service/notification/StatusBarNotification.java
@@ -18,7 +18,7 @@
 
 import android.annotation.UnsupportedAppUsage;
 import android.app.Notification;
-import android.app.NotificationChannel;
+import android.app.NotificationManager;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
@@ -261,7 +261,7 @@
         return this.user.getIdentifier();
     }
 
-    /** The package of the app that posted the notification. */
+    /** The package that the notification belongs to. */
     public String getPackageName() {
         return pkg;
     }
@@ -277,14 +277,18 @@
         return tag;
     }
 
-    /** The notifying app's calling uid. @hide */
-    @UnsupportedAppUsage
+    /**
+     * The notifying app's ({@link #getPackageName()}'s) uid.
+     */
     public int getUid() {
         return uid;
     }
 
-    /** The package used for AppOps tracking. @hide */
-    @UnsupportedAppUsage
+    /** The package that posted the notification.
+     *<p>
+     * Might be different from {@link #getPackageName()} if the app owning the notification has
+     * a {@link NotificationManager#setNotificationDelegate(String) notification delegate}.
+     */
     public String getOpPkg() {
         return opPkg;
     }
diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java
index f90eb14..e819c96 100644
--- a/core/java/android/service/notification/ZenModeConfig.java
+++ b/core/java/android/service/notification/ZenModeConfig.java
@@ -16,6 +16,7 @@
 
 package android.service.notification;
 
+import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_REMINDERS;
 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_LIGHTS;
 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK;
@@ -763,6 +764,145 @@
         }
     };
 
+    /**
+     * @return notification policy based on manual and automatic rules
+     */
+    public Policy getConsolidatedNotificationPolicy() {
+        ZenPolicy policy = new ZenPolicy();
+
+        // assumption: manual rule always uses the default policy
+        for (ZenRule rule : automaticRules.values()) {
+            if (rule.isAutomaticActive()) {
+                if (rule.zenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) {
+                    policy.apply(rule.zenPolicy);
+                }
+            }
+        }
+
+        return toNotificationPolicy(policy);
+    }
+
+    /**
+     * Converts a zenPolicy to a notificationPolicy using this ZenModeConfig's values as its
+     * defaults for all unset values in zenPolicy
+     */
+    public Policy toNotificationPolicy(ZenPolicy zenPolicy) {
+        NotificationManager.Policy defaultPolicy = toNotificationPolicy();
+        int priorityCategories = 0;
+        int suppressedVisualEffects = 0;
+        int callSenders = defaultPolicy.priorityCallSenders;
+        int messageSenders = defaultPolicy.priorityMessageSenders;
+
+        if (zenPolicy.isCategoryAllowed(ZenPolicy.PRIORITY_CATEGORY_REMINDERS,
+                isPriorityCategoryEnabled(Policy.PRIORITY_CATEGORY_REMINDERS, defaultPolicy))) {
+            priorityCategories |= PRIORITY_CATEGORY_REMINDERS;
+        }
+
+        if (zenPolicy.isCategoryAllowed(ZenPolicy.PRIORITY_CATEGORY_EVENTS,
+                isPriorityCategoryEnabled(Policy.PRIORITY_CATEGORY_EVENTS, defaultPolicy))) {
+            priorityCategories |= Policy.PRIORITY_CATEGORY_EVENTS;
+        }
+
+        if (zenPolicy.isCategoryAllowed(ZenPolicy.PRIORITY_CATEGORY_MESSAGES,
+                isPriorityCategoryEnabled(Policy.PRIORITY_CATEGORY_MESSAGES, defaultPolicy))) {
+            priorityCategories |= Policy.PRIORITY_CATEGORY_MESSAGES;
+            messageSenders = getNotificationPolicySenders(zenPolicy.getPriorityMessageSenders());
+        }
+
+        if (zenPolicy.isCategoryAllowed(ZenPolicy.PRIORITY_CATEGORY_CALLS,
+                isPriorityCategoryEnabled(Policy.PRIORITY_CATEGORY_CALLS, defaultPolicy))) {
+            priorityCategories |= Policy.PRIORITY_CATEGORY_CALLS;
+            messageSenders = getNotificationPolicySenders(zenPolicy.getPriorityCallSenders());
+        }
+
+        if (zenPolicy.isCategoryAllowed(ZenPolicy.PRIORITY_CATEGORY_REPEAT_CALLERS,
+                isPriorityCategoryEnabled(Policy.PRIORITY_CATEGORY_REPEAT_CALLERS,
+                        defaultPolicy))) {
+            priorityCategories |= Policy.PRIORITY_CATEGORY_REPEAT_CALLERS;
+        }
+
+        if (zenPolicy.isCategoryAllowed(ZenPolicy.PRIORITY_CATEGORY_ALARMS,
+                isPriorityCategoryEnabled(Policy.PRIORITY_CATEGORY_ALARMS, defaultPolicy))) {
+            priorityCategories |= Policy.PRIORITY_CATEGORY_ALARMS;
+        }
+
+        if (zenPolicy.isCategoryAllowed(ZenPolicy.PRIORITY_CATEGORY_MEDIA,
+                isPriorityCategoryEnabled(Policy.PRIORITY_CATEGORY_MEDIA, defaultPolicy))) {
+            priorityCategories |= Policy.PRIORITY_CATEGORY_MEDIA;
+        }
+
+        if (zenPolicy.isCategoryAllowed(ZenPolicy.PRIORITY_CATEGORY_SYSTEM,
+                isPriorityCategoryEnabled(Policy.PRIORITY_CATEGORY_SYSTEM, defaultPolicy))) {
+            priorityCategories |= Policy.PRIORITY_CATEGORY_SYSTEM;
+        }
+
+        if (!zenPolicy.isVisualEffectAllowed(ZenPolicy.VISUAL_EFFECT_FULL_SCREEN_INTENT,
+                isVisualEffectAllowed(Policy.SUPPRESSED_EFFECT_FULL_SCREEN_INTENT,
+                        defaultPolicy))) {
+            suppressedVisualEffects |= Policy.SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
+        }
+
+        if (!zenPolicy.isVisualEffectAllowed(ZenPolicy.VISUAL_EFFECT_LIGHTS,
+                isVisualEffectAllowed(Policy.SUPPRESSED_EFFECT_LIGHTS,
+                        defaultPolicy))) {
+            suppressedVisualEffects |= Policy.SUPPRESSED_EFFECT_LIGHTS;
+        }
+
+        if (!zenPolicy.isVisualEffectAllowed(ZenPolicy.VISUAL_EFFECT_PEEK,
+                isVisualEffectAllowed(Policy.SUPPRESSED_EFFECT_PEEK,
+                        defaultPolicy))) {
+            suppressedVisualEffects |= Policy.SUPPRESSED_EFFECT_PEEK;
+        }
+
+        if (!zenPolicy.isVisualEffectAllowed(ZenPolicy.VISUAL_EFFECT_STATUS_BAR,
+                isVisualEffectAllowed(Policy.SUPPRESSED_EFFECT_STATUS_BAR,
+                        defaultPolicy))) {
+            suppressedVisualEffects |= Policy.SUPPRESSED_EFFECT_STATUS_BAR;
+        }
+
+        if (!zenPolicy.isVisualEffectAllowed(ZenPolicy.VISUAL_EFFECT_BADGE,
+                isVisualEffectAllowed(Policy.SUPPRESSED_EFFECT_BADGE,
+                        defaultPolicy))) {
+            suppressedVisualEffects |= Policy.SUPPRESSED_EFFECT_BADGE;
+        }
+
+        if (!zenPolicy.isVisualEffectAllowed(ZenPolicy.VISUAL_EFFECT_AMBIENT,
+                isVisualEffectAllowed(Policy.SUPPRESSED_EFFECT_AMBIENT,
+                        defaultPolicy))) {
+            suppressedVisualEffects |= Policy.SUPPRESSED_EFFECT_AMBIENT;
+        }
+
+        if (!zenPolicy.isVisualEffectAllowed(ZenPolicy.VISUAL_EFFECT_NOTIFICATION_LIST,
+                isVisualEffectAllowed(Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST,
+                        defaultPolicy))) {
+            suppressedVisualEffects |= Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST;
+        }
+
+        return new NotificationManager.Policy(priorityCategories, callSenders,
+                messageSenders, suppressedVisualEffects);
+    }
+
+    private boolean isPriorityCategoryEnabled(int categoryType, Policy policy) {
+        return (policy.priorityCategories & categoryType) != 0;
+    }
+
+    private boolean isVisualEffectAllowed(int visualEffect, Policy policy) {
+        return (policy.suppressedVisualEffects & visualEffect) == 0;
+    }
+
+    private int getNotificationPolicySenders(@ZenPolicy.PeopleType int senders) {
+        switch (senders) {
+            case ZenPolicy.PEOPLE_TYPE_ANYONE:
+                return Policy.PRIORITY_SENDERS_ANY;
+            case ZenPolicy.PEOPLE_TYPE_CONTACTS:
+                return Policy.PRIORITY_SENDERS_CONTACTS;
+            case ZenPolicy.PEOPLE_TYPE_STARRED:
+            default:
+                return Policy.PRIORITY_SENDERS_STARRED;
+        }
+
+    }
+
     public Policy toNotificationPolicy() {
         int priorityCategories = 0;
         int priorityCallSenders = Policy.PRIORITY_SENDERS_CONTACTS;
@@ -1315,6 +1455,7 @@
         @UnsupportedAppUsage
         public long creationTime;        // required for automatic
         public String enabler;          // package name, only used for manual rules.
+        public ZenPolicy zenPolicy;
 
         public ZenRule() { }
 
@@ -1335,6 +1476,7 @@
             if (source.readInt() == 1) {
                 enabler = source.readString();
             }
+            zenPolicy = source.readParcelable(null);
         }
 
         @Override
@@ -1369,6 +1511,7 @@
             } else {
                 dest.writeInt(0);
             }
+            dest.writeParcelable(zenPolicy, 0);
         }
 
         @Override
@@ -1384,6 +1527,7 @@
                     .append(",component=").append(component)
                     .append(",creationTime=").append(creationTime)
                     .append(",enabler=").append(enabler)
+                    .append(",zenPolicy=").append(zenPolicy)
                     .append(']').toString();
         }
 
@@ -1407,7 +1551,9 @@
             if (component != null) {
                 component.writeToProto(proto, ZenRuleProto.COMPONENT);
             }
-
+            if (zenPolicy != null) {
+                zenPolicy.writeToProto(proto, ZenRuleProto.ZEN_POLICY);
+            }
             proto.end(token);
         }
 
@@ -1454,9 +1600,12 @@
             if (creationTime != to.creationTime) {
                 d.addLine(item, "creationTime", creationTime, to.creationTime);
             }
-            if (enabler != to.enabler) {
+            if (!Objects.equals(enabler, to.enabler)) {
                 d.addLine(item, "enabler", enabler, to.enabler);
             }
+            if (!Objects.equals(zenPolicy, to.zenPolicy)) {
+                d.addLine(item, "zenPolicy", zenPolicy, to.zenPolicy);
+            }
         }
 
         @Override
@@ -1472,13 +1621,14 @@
                     && Objects.equals(other.condition, condition)
                     && Objects.equals(other.component, component)
                     && Objects.equals(other.id, id)
-                    && Objects.equals(other.enabler, enabler);
+                    && Objects.equals(other.enabler, enabler)
+                    && Objects.equals(other.zenPolicy, zenPolicy);
         }
 
         @Override
         public int hashCode() {
             return Objects.hash(enabled, snoozing, name, zenMode, conditionId, condition,
-                    component, id, enabler);
+                    component, id, enabler, zenPolicy);
         }
 
         public boolean isAutomaticActive() {
diff --git a/core/java/android/service/notification/ZenPolicy.java b/core/java/android/service/notification/ZenPolicy.java
new file mode 100644
index 0000000..1ccf529
--- /dev/null
+++ b/core/java/android/service/notification/ZenPolicy.java
@@ -0,0 +1,897 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.notification;
+
+import android.annotation.IntDef;
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.proto.ProtoOutputStream;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Objects;
+
+/**
+ * ZenPolicy determines whether to allow certain notifications and their corresponding sounds to
+ * play when a device is in Do Not Disturb mode.
+ * ZenPolicy also dictates the visual effects of notifications that are intercepted when
+ * a device is in Do Not Disturb mode.
+ */
+public final class ZenPolicy implements Parcelable {
+    private ArrayList<Integer> mPriorityCategories;
+    private ArrayList<Integer> mVisualEffects;
+    private @PeopleType int mPriorityMessages = PEOPLE_TYPE_UNSET;
+    private @PeopleType int mPriorityCalls = PEOPLE_TYPE_UNSET;
+
+    /** @hide */
+    @IntDef(prefix = { "PRIORITY_CATEGORY_" }, value = {
+            PRIORITY_CATEGORY_REMINDERS,
+            PRIORITY_CATEGORY_EVENTS,
+            PRIORITY_CATEGORY_MESSAGES,
+            PRIORITY_CATEGORY_CALLS,
+            PRIORITY_CATEGORY_REPEAT_CALLERS,
+            PRIORITY_CATEGORY_ALARMS,
+            PRIORITY_CATEGORY_MEDIA,
+            PRIORITY_CATEGORY_SYSTEM,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface PriorityCategory {}
+
+    /** @hide */
+    public static final int PRIORITY_CATEGORY_REMINDERS = 0;
+    /** @hide */
+    public static final int PRIORITY_CATEGORY_EVENTS = 1;
+    /** @hide */
+    public static final int PRIORITY_CATEGORY_MESSAGES = 2;
+    /** @hide */
+    public static final int PRIORITY_CATEGORY_CALLS = 3;
+    /** @hide */
+    public static final int PRIORITY_CATEGORY_REPEAT_CALLERS = 4;
+    /** @hide */
+    public static final int PRIORITY_CATEGORY_ALARMS = 5;
+    /** @hide */
+    public static final int PRIORITY_CATEGORY_MEDIA = 6;
+    /** @hide */
+    public static final int PRIORITY_CATEGORY_SYSTEM = 7;
+
+    /** @hide */
+    @IntDef(prefix = { "VISUAL_EFFECT_" }, value = {
+            VISUAL_EFFECT_FULL_SCREEN_INTENT,
+            VISUAL_EFFECT_LIGHTS,
+            VISUAL_EFFECT_PEEK,
+            VISUAL_EFFECT_STATUS_BAR,
+            VISUAL_EFFECT_BADGE,
+            VISUAL_EFFECT_AMBIENT,
+            VISUAL_EFFECT_NOTIFICATION_LIST,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface VisualEffect {}
+
+    /** @hide */
+    public static final int VISUAL_EFFECT_FULL_SCREEN_INTENT = 0;
+    /** @hide */
+    public static final int VISUAL_EFFECT_LIGHTS = 1;
+    /** @hide */
+    public static final int VISUAL_EFFECT_PEEK = 2;
+    /** @hide */
+    public static final int VISUAL_EFFECT_STATUS_BAR = 3;
+    /** @hide */
+    public static final int VISUAL_EFFECT_BADGE = 4;
+    /** @hide */
+    public static final int VISUAL_EFFECT_AMBIENT = 5;
+    /** @hide */
+    public static final int VISUAL_EFFECT_NOTIFICATION_LIST = 6;
+
+    /** @hide */
+    @IntDef(prefix = { "PEOPLE_TYPE_" }, value = {
+            PEOPLE_TYPE_UNSET,
+            PEOPLE_TYPE_ANYONE,
+            PEOPLE_TYPE_CONTACTS,
+            PEOPLE_TYPE_STARRED,
+            PEOPLE_TYPE_NONE,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface PeopleType {}
+
+    /**
+     * Used to indicate no preference for the type of people that can bypass dnd for either
+     * calls or messages.
+     */
+    public static final int PEOPLE_TYPE_UNSET = 0;
+
+    /**
+     * Used to indicate all calls or messages can bypass dnd.
+     */
+    public static final int PEOPLE_TYPE_ANYONE = 1;
+
+    /**
+     * Used to indicate calls or messages from contacts can bypass dnd.
+     */
+    public static final int PEOPLE_TYPE_CONTACTS = 2;
+
+    /**
+     * Used to indicate calls or messages from starred contacts can bypass dnd.
+     */
+    public static final int PEOPLE_TYPE_STARRED = 3;
+
+    /**
+     * Used to indicate no calls or messages can bypass dnd.
+     */
+    public static final int PEOPLE_TYPE_NONE = 4;
+
+    /** @hide */
+    @IntDef(prefix = { "STATE_" }, value = {
+            STATE_UNSET,
+            STATE_ALLOW,
+            STATE_DISALLOW,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface State {}
+
+    /**
+     * Indicates no preference for whether a type of sound or visual effect is or isn't allowed
+     * to play/show when DND is active.  Will default to the current set policy.
+     */
+    public static final int STATE_UNSET = 0;
+
+    /**
+     * Indicates a type of sound or visual effect is allowed to play/show when DND is active.
+     */
+    public static final int STATE_ALLOW = 1;
+
+    /**
+     * Indicates a type of sound or visual effect is not allowed to play/show when DND is active.
+     */
+    public static final int STATE_DISALLOW = 2;
+
+    /** @hide */
+    public ZenPolicy() {
+        mPriorityCategories = new ArrayList<>(Collections.nCopies(8, 0));
+        mVisualEffects = new ArrayList<>(Collections.nCopies(7, 0));
+    }
+
+    /**
+     * Message senders that can bypass DND.
+     * @return {@link #PEOPLE_TYPE_UNSET}, {@link #PEOPLE_TYPE_ANYONE},
+     * {@link #PEOPLE_TYPE_CONTACTS}, {@link #PEOPLE_TYPE_STARRED} or {@link #PEOPLE_TYPE_NONE}
+     */
+    public @PeopleType int getPriorityMessageSenders() {
+        return mPriorityMessages;
+    }
+
+    /**
+     * Callers that can bypass DND.
+     * @return {@link #PEOPLE_TYPE_UNSET}, {@link #PEOPLE_TYPE_ANYONE},
+     * {@link #PEOPLE_TYPE_CONTACTS}, {@link #PEOPLE_TYPE_STARRED} or {@link #PEOPLE_TYPE_NONE}
+     */
+    public @PeopleType int getPriorityCallSenders() {
+        return mPriorityCalls;
+    }
+
+    /**
+     * Whether this policy wants to allow notifications with category
+     * {@link Notification#CATEGORY_REMINDER} to play sounds and visually appear
+     * or to intercept them when DND is active.
+     * @return {@link #STATE_UNSET}, {@link #STATE_ALLOW} or {@link #STATE_DISALLOW}
+     */
+    public @State int getPriorityCategoryReminders() {
+        return mPriorityCategories.get(PRIORITY_CATEGORY_REMINDERS);
+    }
+
+    /**
+     * Whether this policy wants to allow notifications with category
+     * {@link Notification#CATEGORY_EVENT} to play sounds and visually appear
+     * or to intercept them when DND is active.
+     * @return {@link #STATE_UNSET}, {@link #STATE_ALLOW} or {@link #STATE_DISALLOW}
+     */
+    public @State int getPriorityCategoryEvents() {
+        return mPriorityCategories.get(PRIORITY_CATEGORY_EVENTS);
+    }
+
+    /**
+     * Whether this policy wants to allow notifications with category
+     * {@link Notification#CATEGORY_MESSAGE} to play sounds and visually appear
+     * or to intercept them when DND is active.  Types of message senders that are allowed
+     * are specified by {@link #getPriorityMessageSenders}.
+     * @return {@link #STATE_UNSET}, {@link #STATE_ALLOW} or {@link #STATE_DISALLOW}
+     */
+    public @State int getPriorityCategoryMessages() {
+        return mPriorityCategories.get(PRIORITY_CATEGORY_MESSAGES);
+    }
+
+    /**
+     * Whether this policy wants to allow notifications with category
+     * {@link Notification#CATEGORY_CALL} to play sounds and visually appear
+     * or to intercept them when DND is active.  Types of callers that are allowed
+     * are specified by {@link #getPriorityCallSenders()}.
+     * @return {@link #STATE_UNSET}, {@link #STATE_ALLOW} or {@link #STATE_DISALLOW}
+     */
+    public @State int getPriorityCategoryCalls() {
+        return mPriorityCategories.get(PRIORITY_CATEGORY_CALLS);
+    }
+
+    /**
+     * Whether this policy wants to allow repeat callers (notifications with category
+     * {@link Notification#CATEGORY_CALL} that have recently called) to play sounds and
+     * visually appear or to intercept them when DND is active.
+     * @return {@link #STATE_UNSET}, {@link #STATE_ALLOW} or {@link #STATE_DISALLOW}
+     */
+    public @State int getPriorityCategoryRepeatCallers() {
+        return mPriorityCategories.get(PRIORITY_CATEGORY_REPEAT_CALLERS);
+    }
+
+    /**
+     * Whether this policy wants to allow notifications with category
+     * {@link Notification#CATEGORY_ALARM} to play sounds and visually appear
+     * or to intercept them when DND is active.
+     * When alarms are {@link #STATE_DISALLOW disallowed}, the alarm stream will be muted when DND
+     * is active.
+     * @return {@link #STATE_UNSET}, {@link #STATE_ALLOW} or {@link #STATE_DISALLOW}
+     */
+    public @State int getPriorityCategoryAlarms() {
+        return mPriorityCategories.get(PRIORITY_CATEGORY_ALARMS);
+    }
+
+    /**
+     * Whether this policy wants to allow media notifications to play sounds and visually appear
+     * or to intercept them when DND is active.
+     * When media is {@link #STATE_DISALLOW disallowed}, the media stream will be muted when DND is
+     * active.
+     * @return {@link #STATE_UNSET}, {@link #STATE_ALLOW} or {@link #STATE_DISALLOW}
+     */
+    public @State int getPriorityCategoryMedia() {
+        return mPriorityCategories.get(PRIORITY_CATEGORY_MEDIA);
+    }
+
+    /**
+     * Whether this policy wants to allow system sounds when DND is active.
+     * When system is {@link #STATE_DISALLOW}, the system stream will be muted when DND is active.
+     * @return {@link #STATE_UNSET}, {@link #STATE_ALLOW} or {@link #STATE_DISALLOW}
+     */
+    public @State int getPriorityCategorySystem() {
+        return mPriorityCategories.get(PRIORITY_CATEGORY_SYSTEM);
+    }
+
+    /**
+     * Whether this policy allows {@link Notification#fullScreenIntent full screen intents} from
+     * notifications intercepted by DND.
+     */
+    public @State int getVisualEffectFullScreenIntent() {
+        return mVisualEffects.get(VISUAL_EFFECT_FULL_SCREEN_INTENT);
+    }
+
+    /**
+     * Whether this policy allows {@link NotificationChannel#shouldShowLights() notification
+     * lights} from notifications intercepted by DND.
+     */
+    public @State int getVisualEffectLights() {
+        return mVisualEffects.get(VISUAL_EFFECT_LIGHTS);
+    }
+
+    /**
+     * Whether this policy allows peeking from notifications intercepted by DND.
+     */
+    public @State int getVisualEffectPeek() {
+        return mVisualEffects.get(VISUAL_EFFECT_PEEK);
+    }
+
+    /**
+     * Whether this policy allows notifications intercepted by DND from appearing in the status bar
+     * on devices that support status bars.
+     */
+    public @State int getVisualEffectStatusBar() {
+        return mVisualEffects.get(VISUAL_EFFECT_STATUS_BAR);
+    }
+
+    /**
+     * Whether this policy allows {@link NotificationChannel#canShowBadge() badges} from
+     * notifications intercepted by DND on devices that support badging.
+     */
+    public @State int getVisualEffectBadge() {
+        return mVisualEffects.get(VISUAL_EFFECT_BADGE);
+    }
+
+    /**
+     * Whether this policy allows notifications intercepted by DND from appearing on ambient
+     * displays on devices that support ambient display.
+     */
+    public @State int getVisualEffectAmbient() {
+        return mVisualEffects.get(VISUAL_EFFECT_AMBIENT);
+    }
+
+    /**
+     * Whether this policy allows notifications intercepted by DND from appearing in notification
+     * list views like the notification shade or lockscreen on devices that support those
+     * views.
+     */
+    public @State int getVisualEffectNotificationList() {
+        return mVisualEffects.get(VISUAL_EFFECT_NOTIFICATION_LIST);
+    }
+
+    /**
+     * Builder class for {@link ZenPolicy} objects.
+     * Provides a convenient way to set the various fields of a {@link ZenPolicy}.  If a field
+     * is not set, it is (@link STATE_UNSET} and will not change the current set policy.
+     */
+    public static class Builder {
+        private ZenPolicy mZenPolicy;
+
+        public Builder() {
+            mZenPolicy = new ZenPolicy();
+        }
+
+        /**
+         * Builds the current ZenPolicy.
+         */
+        public ZenPolicy build() {
+            return mZenPolicy.copy();
+        }
+
+        /**
+         * Allows all notifications to bypass DND and unmutes all streams.
+         */
+        public Builder allowAllSounds() {
+            for (int i = 0; i < mZenPolicy.mPriorityCategories.size(); i++) {
+                mZenPolicy.mPriorityCategories.set(i, STATE_ALLOW);
+            }
+            mZenPolicy.mPriorityMessages = PEOPLE_TYPE_ANYONE;
+            mZenPolicy.mPriorityCalls = PEOPLE_TYPE_ANYONE;
+            return this;
+        }
+
+        /**
+         * Intercepts all notifications and prevents them from playing sounds
+         * when DND is active. Also mutes alarm, system and media streams.
+         * Notification channels can still play sounds only if they
+         * {@link NotificationChannel#canBypassDnd can bypass DND}. If no channels can bypass DND,
+         * the ringer stream is also muted.
+         */
+        public Builder disallowAllSounds() {
+            for (int i = 0; i < mZenPolicy.mPriorityCategories.size(); i++) {
+                mZenPolicy.mPriorityCategories.set(i, STATE_DISALLOW);
+            }
+            mZenPolicy.mPriorityMessages = PEOPLE_TYPE_NONE;
+            mZenPolicy.mPriorityCalls = PEOPLE_TYPE_NONE;
+            return this;
+        }
+
+        /**
+         * Allows notifications intercepted by DND to show on all surfaces when DND is active.
+         */
+        public Builder showAllVisualEffects() {
+            for (int i = 0; i < mZenPolicy.mVisualEffects.size(); i++) {
+                mZenPolicy.mVisualEffects.set(i, STATE_ALLOW);
+            }
+            return this;
+        }
+
+        /**
+         * Disallows notifications intercepted by DND from showing when DND is active.
+         */
+        public Builder hideAllVisualEffects() {
+            for (int i = 0; i < mZenPolicy.mVisualEffects.size(); i++) {
+                mZenPolicy.mVisualEffects.set(i, STATE_DISALLOW);
+            }
+            return this;
+        }
+
+        /**
+         * Unsets a priority category, neither allowing or disallowing. When applying this policy,
+         * unset categories will default to the current applied policy.
+         * @hide
+         */
+        public Builder unsetPriorityCategory(@PriorityCategory int category) {
+            mZenPolicy.mPriorityCategories.set(category, STATE_UNSET);
+
+            if (category == PRIORITY_CATEGORY_MESSAGES) {
+                mZenPolicy.mPriorityMessages = STATE_UNSET;
+            } else if (category == PRIORITY_CATEGORY_CALLS) {
+                mZenPolicy.mPriorityCalls = STATE_UNSET;
+            }
+
+            return this;
+        }
+
+        /**
+         * Unsets a visual effect, neither allowing or disallowing. When applying this policy,
+         * unset effects will default to the current applied policy.
+         * @hide
+         */
+        public Builder unsetVisualEffect(@VisualEffect int effect) {
+            mZenPolicy.mVisualEffects.set(effect, STATE_UNSET);
+            return this;
+        }
+
+        /**
+         * Whether to allow notifications with category {@link Notification#CATEGORY_REMINDER}
+         * to play sounds and visually appear or to intercept them when DND is active.
+         */
+        public Builder allowReminders(boolean allow) {
+            mZenPolicy.mPriorityCategories.set(PRIORITY_CATEGORY_REMINDERS,
+                    allow ? STATE_ALLOW : STATE_DISALLOW);
+            return this;
+        }
+
+        /**
+         * Whether to allow notifications with category {@link Notification#CATEGORY_EVENT}
+         * to play sounds and visually appear or to intercept them when DND is active.
+         */
+        public Builder allowEvents(boolean allow) {
+            mZenPolicy.mPriorityCategories.set(PRIORITY_CATEGORY_EVENTS,
+                    allow ? STATE_ALLOW : STATE_DISALLOW);
+            return this;
+        }
+
+        /**
+         * Whether to allow notifications with category {@link Notification#CATEGORY_MESSAGE}
+         * that match audienceType to play sounds and visually appear or to intercept
+         * them when DND is active.
+         * @param audienceType message senders that are allowed to bypass DND
+         */
+        public Builder allowMessages(@PeopleType int audienceType) {
+            if (audienceType == STATE_UNSET) {
+                return unsetPriorityCategory(PRIORITY_CATEGORY_MESSAGES);
+            }
+
+            if (audienceType == PEOPLE_TYPE_NONE) {
+                mZenPolicy.mPriorityCategories.set(PRIORITY_CATEGORY_MESSAGES, STATE_DISALLOW);
+            } else if (audienceType == PEOPLE_TYPE_ANYONE || audienceType == PEOPLE_TYPE_CONTACTS
+                    || audienceType == PEOPLE_TYPE_STARRED) {
+                mZenPolicy.mPriorityCategories.set(PRIORITY_CATEGORY_MESSAGES, STATE_ALLOW);
+            } else {
+                return this;
+            }
+
+            mZenPolicy.mPriorityMessages = audienceType;
+            return this;
+        }
+
+        /**
+         * Whether to allow notifications with category {@link Notification#CATEGORY_CALL}
+         * that match audienceType to play sounds and visually appear or to intercept
+         * them when DND is active.
+         * @param audienceType callers that are allowed to bypass DND
+         */
+        public Builder allowCalls(@PeopleType int audienceType) {
+            if (audienceType == STATE_UNSET) {
+                return unsetPriorityCategory(PRIORITY_CATEGORY_CALLS);
+            }
+
+            if (audienceType == PEOPLE_TYPE_NONE) {
+                mZenPolicy.mPriorityCategories.set(PRIORITY_CATEGORY_CALLS, STATE_DISALLOW);
+            } else if (audienceType == PEOPLE_TYPE_ANYONE || audienceType == PEOPLE_TYPE_CONTACTS
+                    || audienceType == PEOPLE_TYPE_STARRED) {
+                mZenPolicy.mPriorityCategories.set(PRIORITY_CATEGORY_CALLS, STATE_ALLOW);
+            } else {
+                return this;
+            }
+
+            mZenPolicy.mPriorityCalls = audienceType;
+            return this;
+        }
+
+        /**
+         * Whether to allow repeat callers (notifications with category
+         * {@link Notification#CATEGORY_CALL} that have recently called
+         * to play sounds and visually appear.
+         */
+        public Builder allowRepeatCallers(boolean allow) {
+            mZenPolicy.mPriorityCategories.set(PRIORITY_CATEGORY_REPEAT_CALLERS,
+                    allow ? STATE_ALLOW : STATE_DISALLOW);
+            return this;
+        }
+
+
+        /**
+         * Whether to allow notifications with category {@link Notification#CATEGORY_ALARM}
+         * to play sounds and visually appear or to intercept them when DND is active.
+         * Disallowing alarms will mute the alarm stream when DND is active.
+         */
+        public Builder allowAlarms(boolean allow) {
+            mZenPolicy.mPriorityCategories.set(PRIORITY_CATEGORY_ALARMS,
+                    allow ? STATE_ALLOW : STATE_DISALLOW);
+            return this;
+        }
+
+        /**
+         * Whether to allow media notifications to play sounds and visually
+         * appear or to intercept them when DND is active.
+         * Disallowing media will mute the media stream when DND is active.
+         */
+        public Builder allowMedia(boolean allow) {
+            mZenPolicy.mPriorityCategories.set(PRIORITY_CATEGORY_MEDIA,
+                    allow ? STATE_ALLOW : STATE_DISALLOW);
+            return this;
+        }
+
+        /**
+         * Whether to allow system sounds to play when DND is active.
+         * Disallowing system sounds will mute the system stream when DND is active.
+         */
+        public Builder allowSystem(boolean allow) {
+            mZenPolicy.mPriorityCategories.set(PRIORITY_CATEGORY_SYSTEM,
+                    allow ? STATE_ALLOW : STATE_DISALLOW);
+            return this;
+        }
+
+        /**
+         * Whether {@link Notification#fullScreenIntent full screen intents} that are intercepted
+         * by DND are shown.
+         */
+        public Builder showFullScreenIntent(boolean show) {
+            mZenPolicy.mVisualEffects.set(VISUAL_EFFECT_FULL_SCREEN_INTENT,
+                    show ? STATE_ALLOW : STATE_DISALLOW);
+            return this;
+        }
+
+        /**
+         * Whether {@link NotificationChannel#shouldShowLights() notification lights} from
+         * notifications intercepted by DND are blocked.
+         */
+        public Builder showLights(boolean show) {
+            mZenPolicy.mVisualEffects.set(VISUAL_EFFECT_LIGHTS,
+                    show ? STATE_ALLOW : STATE_DISALLOW);
+            return this;
+        }
+
+        /**
+         * Whether notifications intercepted by DND are prevented from peeking.
+         */
+        public Builder showPeeking(boolean show) {
+            mZenPolicy.mVisualEffects.set(VISUAL_EFFECT_PEEK,
+                    show ? STATE_ALLOW : STATE_DISALLOW);
+            return this;
+        }
+
+        /**
+         * Whether notifications intercepted by DND are prevented from appearing in the status bar
+         * on devices that support status bars.
+         */
+        public Builder showStatusBarIcons(boolean show) {
+            mZenPolicy.mVisualEffects.set(VISUAL_EFFECT_STATUS_BAR,
+                    show ? STATE_ALLOW : STATE_DISALLOW);
+            return this;
+        }
+
+        /**
+         * Whether {@link NotificationChannel#canShowBadge() badges} from
+         * notifications intercepted by DND are allowed on devices that support badging.
+         */
+        public Builder showBadges(boolean show) {
+            mZenPolicy.mVisualEffects.set(VISUAL_EFFECT_BADGE,
+                    show ? STATE_ALLOW : STATE_DISALLOW);
+            return this;
+        }
+
+        /**
+         * Whether notification intercepted by DND are prevented from appearing on ambient displays
+         * on devices that support ambient display.
+         */
+        public Builder showInAmbientDisplay(boolean show) {
+            mZenPolicy.mVisualEffects.set(VISUAL_EFFECT_AMBIENT,
+                    show ? STATE_ALLOW : STATE_DISALLOW);
+            return this;
+        }
+
+        /**
+         * 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.
+         */
+        public Builder showInNotificationList(boolean show) {
+            mZenPolicy.mVisualEffects.set(VISUAL_EFFECT_NOTIFICATION_LIST,
+                    show ? STATE_ALLOW : STATE_DISALLOW);
+            return this;
+        }
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeList(mPriorityCategories);
+        dest.writeList(mVisualEffects);
+        dest.writeInt(mPriorityCalls);
+        dest.writeInt(mPriorityMessages);
+    }
+
+    public static final Parcelable.Creator<ZenPolicy> CREATOR =
+            new Parcelable.Creator<ZenPolicy>() {
+        @Override
+        public ZenPolicy createFromParcel(Parcel source) {
+            ZenPolicy policy = new ZenPolicy();
+            policy.mPriorityCategories = source.readArrayList(Integer.class.getClassLoader());
+            policy.mVisualEffects = source.readArrayList(Integer.class.getClassLoader());
+            policy.mPriorityCalls = source.readInt();
+            policy.mPriorityMessages = source.readInt();
+            return policy;
+        }
+
+        @Override
+        public ZenPolicy[] newArray(int size) {
+            return new ZenPolicy[size];
+        }
+    };
+
+    @Override
+    public String toString() {
+        return new StringBuilder(ZenPolicy.class.getSimpleName())
+                .append('{')
+                .append("priorityCategories=[").append(priorityCategoriesToString())
+                .append("], visualEffects=[").append(visualEffectsToString())
+                .append(", priorityCalls=").append(stateToString(mPriorityCalls))
+                .append("], priorityMessages=").append(stateToString(mPriorityMessages))
+                .append('}')
+                .toString();
+    }
+
+
+    private String priorityCategoriesToString() {
+        StringBuilder builder = new StringBuilder();
+        for (int i = 0; i < mPriorityCategories.size(); i++) {
+            if (mPriorityCategories.get(i) != STATE_UNSET) {
+                builder.append(indexToCategory(i))
+                        .append("=")
+                        .append(stateToString(mPriorityCategories.get(i)))
+                        .append(" ");
+            }
+
+        }
+        return builder.toString();
+    }
+
+    private String visualEffectsToString() {
+        StringBuilder builder = new StringBuilder();
+        for (int i = 0; i < mVisualEffects.size(); i++) {
+            if (mVisualEffects.get(i) != STATE_UNSET) {
+                builder.append(indexToVisualEffect(i))
+                        .append("=")
+                        .append(stateToString(mVisualEffects.get(i)))
+                        .append(" ");
+            }
+
+        }
+        return builder.toString();
+    }
+
+    private String indexToVisualEffect(@VisualEffect int visualEffectIndex) {
+        switch (visualEffectIndex) {
+            case VISUAL_EFFECT_FULL_SCREEN_INTENT:
+                return "fullScreenIntent";
+            case VISUAL_EFFECT_LIGHTS:
+                return "lights";
+            case VISUAL_EFFECT_PEEK:
+                return "peek";
+            case VISUAL_EFFECT_STATUS_BAR:
+                return "statusBar";
+            case VISUAL_EFFECT_BADGE:
+                return "badge";
+            case VISUAL_EFFECT_AMBIENT:
+                return "ambient";
+            case VISUAL_EFFECT_NOTIFICATION_LIST:
+                return "notificationList";
+        }
+        return null;
+    }
+
+    private String indexToCategory(@PriorityCategory int categoryIndex) {
+        switch (categoryIndex) {
+            case PRIORITY_CATEGORY_REMINDERS:
+                return "reminders";
+            case PRIORITY_CATEGORY_EVENTS:
+                return "events";
+            case PRIORITY_CATEGORY_MESSAGES:
+                return "messages";
+            case PRIORITY_CATEGORY_CALLS:
+                return "calls";
+            case PRIORITY_CATEGORY_REPEAT_CALLERS:
+                return "repeatCallers";
+            case PRIORITY_CATEGORY_ALARMS:
+                return "alarms";
+            case PRIORITY_CATEGORY_MEDIA:
+                return "media";
+            case PRIORITY_CATEGORY_SYSTEM:
+                return "system";
+        }
+        return null;
+    }
+
+    private String stateToString(@State int state) {
+        switch (state) {
+            case STATE_UNSET:
+                return "unset";
+            case STATE_DISALLOW:
+                return "disallow";
+            case STATE_ALLOW:
+                return "allow";
+        }
+        return null;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (!(o instanceof ZenPolicy)) return false;
+        if (o == this) return true;
+        final ZenPolicy other = (ZenPolicy) o;
+
+        return Objects.equals(other.mPriorityCategories, mPriorityCategories)
+                && Objects.equals(other.mVisualEffects, mVisualEffects)
+                && other.mPriorityCalls == mPriorityCalls
+                && other.mPriorityMessages == mPriorityMessages;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mPriorityCategories, mVisualEffects, mPriorityCalls, mPriorityMessages);
+    }
+
+    private @ZenPolicy.State int getZenPolicyPriorityCategoryState(@PriorityCategory int
+            category) {
+        switch (category) {
+            case PRIORITY_CATEGORY_REMINDERS:
+                return getPriorityCategoryReminders();
+            case PRIORITY_CATEGORY_EVENTS:
+                return getPriorityCategoryEvents();
+            case PRIORITY_CATEGORY_MESSAGES:
+                return getPriorityCategoryMessages();
+            case PRIORITY_CATEGORY_CALLS:
+                return getPriorityCategoryCalls();
+            case PRIORITY_CATEGORY_REPEAT_CALLERS:
+                return getPriorityCategoryRepeatCallers();
+            case PRIORITY_CATEGORY_ALARMS:
+                return getPriorityCategoryAlarms();
+            case PRIORITY_CATEGORY_MEDIA:
+                return getPriorityCategoryMedia();
+            case PRIORITY_CATEGORY_SYSTEM:
+                return getPriorityCategorySystem();
+        }
+        return -1;
+    }
+
+    private @ZenPolicy.State int getZenPolicyVisualEffectState(@VisualEffect int effect) {
+        switch (effect) {
+            case VISUAL_EFFECT_FULL_SCREEN_INTENT:
+                return getVisualEffectFullScreenIntent();
+            case VISUAL_EFFECT_LIGHTS:
+                return getVisualEffectLights();
+            case VISUAL_EFFECT_PEEK:
+                return getVisualEffectPeek();
+            case VISUAL_EFFECT_STATUS_BAR:
+                return getVisualEffectStatusBar();
+            case VISUAL_EFFECT_BADGE:
+                return getVisualEffectBadge();
+            case VISUAL_EFFECT_AMBIENT:
+                return getVisualEffectAmbient();
+            case VISUAL_EFFECT_NOTIFICATION_LIST:
+                return getVisualEffectNotificationList();
+        }
+        return -1;
+    }
+
+    /** @hide */
+    public boolean isCategoryAllowed(@PriorityCategory int category, boolean defaultVal) {
+        switch (getZenPolicyPriorityCategoryState(category)) {
+            case ZenPolicy.STATE_ALLOW:
+                return true;
+            case ZenPolicy.STATE_DISALLOW:
+                return false;
+            default:
+                return defaultVal;
+        }
+    }
+
+    /** @hide */
+    public boolean isVisualEffectAllowed(@VisualEffect int effect, boolean defaultVal) {
+        switch (getZenPolicyVisualEffectState(effect)) {
+            case ZenPolicy.STATE_ALLOW:
+                return true;
+            case ZenPolicy.STATE_DISALLOW:
+                return false;
+            default:
+                return defaultVal;
+        }
+    }
+
+    /**
+     * Applies another policy on top of this policy
+     * @hide
+     */
+    public void apply(ZenPolicy policyToApply) {
+        // apply priority categories
+        for (int category = 0; category < mPriorityCategories.size(); category++) {
+            if (mPriorityCategories.get(category) == STATE_DISALLOW) {
+                // if a priority category is already disallowed by the policy, cannot allow
+                continue;
+            }
+
+            @State int newState = policyToApply.mPriorityCategories.get(category);
+            if (newState != STATE_UNSET) {
+                mPriorityCategories.set(category, newState);
+
+                if (category == PRIORITY_CATEGORY_MESSAGES
+                        && mPriorityMessages < policyToApply.mPriorityMessages) {
+                    mPriorityMessages = policyToApply.mPriorityMessages;
+                } else if (category == PRIORITY_CATEGORY_CALLS
+                        && mPriorityCalls < policyToApply.mPriorityCalls) {
+                    mPriorityCalls = policyToApply.mPriorityCalls;
+                }
+            }
+        }
+
+        // apply visual effects
+        for (int visualEffect = 0; visualEffect < mVisualEffects.size(); visualEffect++) {
+            if (mVisualEffects.get(visualEffect) == STATE_DISALLOW) {
+                // if a visual effect is already disallowed by the policy, cannot allow
+                continue;
+            }
+
+            if (policyToApply.mVisualEffects.get(visualEffect) != STATE_UNSET) {
+                mVisualEffects.set(visualEffect, policyToApply.mVisualEffects.get(visualEffect));
+            }
+        }
+    }
+
+    /**
+     * @hide
+     */
+    public void writeToProto(ProtoOutputStream proto, long fieldId) {
+        final long token = proto.start(fieldId);
+
+        proto.write(ZenPolicyProto.REMINDERS, getPriorityCategoryReminders());
+        proto.write(ZenPolicyProto.EVENTS, getPriorityCategoryEvents());
+        proto.write(ZenPolicyProto.MESSAGES, getPriorityCategoryMessages());
+        proto.write(ZenPolicyProto.CALLS, getPriorityCategoryCalls());
+        proto.write(ZenPolicyProto.REPEAT_CALLERS, getPriorityCategoryRepeatCallers());
+        proto.write(ZenPolicyProto.ALARMS, getPriorityCategoryAlarms());
+        proto.write(ZenPolicyProto.MEDIA, getPriorityCategoryMedia());
+        proto.write(ZenPolicyProto.SYSTEM, getPriorityCategorySystem());
+
+        proto.write(ZenPolicyProto.FULL_SCREEN_INTENT, getVisualEffectFullScreenIntent());
+        proto.write(ZenPolicyProto.LIGHTS, getVisualEffectLights());
+        proto.write(ZenPolicyProto.PEEK, getVisualEffectPeek());
+        proto.write(ZenPolicyProto.STATUS_BAR, getVisualEffectStatusBar());
+        proto.write(ZenPolicyProto.BADGE, getVisualEffectBadge());
+        proto.write(ZenPolicyProto.AMBIENT, getVisualEffectAmbient());
+        proto.write(ZenPolicyProto.NOTIFICATION_LIST, getVisualEffectNotificationList());
+
+        proto.write(ZenPolicyProto.PRIORITY_MESSAGES, getPriorityMessageSenders());
+        proto.write(ZenPolicyProto.PRIORITY_CALLS, getPriorityCallSenders());
+        proto.end(token);
+    }
+
+    /**
+     * Makes deep copy of this ZenPolicy.
+     * @hide
+     */
+    public ZenPolicy copy() {
+        final Parcel parcel = Parcel.obtain();
+        try {
+            writeToParcel(parcel, 0);
+            parcel.setDataPosition(0);
+            return CREATOR.createFromParcel(parcel);
+        } finally {
+            parcel.recycle();
+        }
+    }
+}
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index 2846730..4bd86a4 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -45,6 +45,7 @@
 import android.util.MergedConfiguration;
 import android.view.Display;
 import android.view.DisplayCutout;
+import android.view.DisplayInfo;
 import android.view.Gravity;
 import android.view.IWindowSession;
 import android.view.InputChannel;
@@ -763,9 +764,20 @@
 
                     mLayout.x = 0;
                     mLayout.y = 0;
-                    mLayout.width = myWidth;
-                    mLayout.height = myHeight;
-                    
+
+                    if (!fixedSize) {
+                        mLayout.width = myWidth;
+                        mLayout.height = myHeight;
+                    } else {
+                        // Force the wallpaper to cover the screen in both dimensions
+                        // only internal implementations like ImageWallpaper
+                        DisplayInfo displayInfo = new DisplayInfo();
+                        mDisplay.getDisplayInfo(displayInfo);
+                        mLayout.width = Math.max(displayInfo.logicalWidth, myWidth);
+                        mLayout.height = Math.max(displayInfo.logicalHeight, myHeight);
+                        mWindowFlags |= WindowManager.LayoutParams.FLAG_SCALED;
+                    }
+
                     mLayout.format = mFormat;
                     
                     mCurWindowFlags = mWindowFlags;
@@ -847,6 +859,9 @@
                         mStableInsets.bottom += padding.bottom;
                         mDisplayCutout.set(mDisplayCutout.get().inset(-padding.left, -padding.top,
                                 -padding.right, -padding.bottom));
+                    } else {
+                        w = myWidth;
+                        h = myHeight;
                     }
 
                     if (mCurWidth != w) {
diff --git a/core/java/android/text/DynamicLayout.java b/core/java/android/text/DynamicLayout.java
index c46c831..c928da1 100644
--- a/core/java/android/text/DynamicLayout.java
+++ b/core/java/android/text/DynamicLayout.java
@@ -23,6 +23,7 @@
 import android.annotation.UnsupportedAppUsage;
 import android.graphics.Paint;
 import android.graphics.Rect;
+import android.os.Build;
 import android.text.style.ReplacementSpan;
 import android.text.style.UpdateLayout;
 import android.text.style.WrapTogetherSpan;
@@ -354,7 +355,7 @@
      * @deprecated Use {@link Builder} instead.
      */
     @Deprecated
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     public DynamicLayout(@NonNull CharSequence base, @NonNull CharSequence display,
                          @NonNull TextPaint paint,
                          @IntRange(from = 0) int width,
diff --git a/core/java/android/text/FontConfig.java b/core/java/android/text/FontConfig.java
index 9e0fee33..19c55d5 100644
--- a/core/java/android/text/FontConfig.java
+++ b/core/java/android/text/FontConfig.java
@@ -181,7 +181,8 @@
     public static final class Family {
         private final @NonNull String mName;
         private final @NonNull Font[] mFonts;
-        private final @NonNull String[] mLanguages;
+        // Comma separated BCP47 complient locale strings
+        private final @NonNull String mLanguages;
 
         /** @hide */
         @Retention(SOURCE)
@@ -219,7 +220,7 @@
         // See frameworks/minikin/include/minikin/FontFamily.h
         private final @Variant int mVariant;
 
-        public Family(@NonNull String name, @NonNull Font[] fonts, @NonNull String[] languages,
+        public Family(@NonNull String name, @NonNull Font[] fonts, @NonNull String languages,
                 @Variant int variant) {
             mName = name;
             mFonts = fonts;
@@ -244,9 +245,9 @@
         }
 
         /**
-         * Returns the languages for this family. May be null.
+         * Returns the comma separated BCP47 complient languages for this family. May be null.
          */
-        public @Nullable String[] getLanguages() {
+        public @NonNull String getLanguages() {
             return mLanguages;
         }
 
diff --git a/core/java/android/text/Hyphenator.java b/core/java/android/text/Hyphenator.java
index 4f1488e..e4200ac 100644
--- a/core/java/android/text/Hyphenator.java
+++ b/core/java/android/text/Hyphenator.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2015 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,15 +16,145 @@
 
 package android.text;
 
+import android.annotation.IntDef;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
 /**
- * Hyphenator just initializes the native implementation of automatic hyphenation,
- * in essence finding valid hyphenation opportunities in a word.
+ * Provides constants and pack/unpack methods for the HyphenEdit.
  *
- * @hide
+ * Hyphenator provides constant values for start of line and end of line modification.
+ * For example, by passing {@link #END_HYPHEN_EDIT_INSERT_HYPHEN} like as follows, HYPHEN(U+2010)
+ * character is appended at the end of line.
+ *
+ * <pre>
+ * <code>
+ *   Paint paint = new Paint();
+ *   paint.setHyphenEdit(Hyphenator.packHyphenEdit(
+ *       Hyphenator.START_HYPHEN_EDIT_NO_EDIT,
+ *       Hyphenator.END_HYPHEN_EDIT_INSERT_HYPHEN));
+ *   paint.measureText("abc", 0, 3);  // Returns the width of "abc‐"
+ *   Canvas.drawText("abc", 0, 3, 0f, 0f, paint);  // Draws "abc‐"
+ * </code>
+ * </pre>
+ *
+ * @see android.graphics.Paint#setHyphenEdit(int)
  */
 public class Hyphenator {
+    private Hyphenator() {}
+
+    /** @hide */
+    @IntDef(prefix = { "START_HYPHEN_EDIT_" }, value = {
+        START_HYPHEN_EDIT_NO_EDIT,
+        START_HYPHEN_EDIT_INSERT_HYPHEN,
+        START_HYPHEN_EDIT_INSERT_ZWJ
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface StartHyphenEdit {}
+
+    /**
+     * An integer representing the starting of the line has no modification for hyphenation.
+     */
+    public static final int START_HYPHEN_EDIT_NO_EDIT = 0x00;
+
+    /**
+     * An integer representing the starting of the line has normal hyphen character (U+002D).
+     */
+    public static final int START_HYPHEN_EDIT_INSERT_HYPHEN = 0x01;
+
+    /**
+     * An integer representing the starting of the line has Zero-Width-Joiner (U+200D).
+     */
+    public static final int START_HYPHEN_EDIT_INSERT_ZWJ = 0x02;
+
+    /** @hide */
+    @IntDef(prefix = { "END_HYPHEN_EDIT_" }, value = {
+        END_HYPHEN_EDIT_NO_EDIT,
+        END_HYPHEN_EDIT_REPLACE_WITH_HYPHEN,
+        END_HYPHEN_EDIT_INSERT_HYPHEN,
+        END_HYPHEN_EDIT_INSERT_ARMENIAN_HYPHEN,
+        END_HYPHEN_EDIT_INSERT_MAQAF,
+        END_HYPHEN_EDIT_INSERT_UCAS_HYPHEN,
+        END_HYPHEN_EDIT_INSERT_ZWJ_AND_HYPHEN
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface EndHyphenEdit {}
+
+    /**
+     * An integer representing the end of the line has no modification for hyphenation.
+     */
+    public static final int END_HYPHEN_EDIT_NO_EDIT = 0x00;
+
+    /**
+     * An integer representing the character at the end of the line is replaced with hyphen
+     * character (U+002D).
+     */
+    public static final int END_HYPHEN_EDIT_REPLACE_WITH_HYPHEN = 0x01;
+
+    /**
+     * An integer representing the end of the line has normal hyphen character (U+002D).
+     */
+    public static final int END_HYPHEN_EDIT_INSERT_HYPHEN = 0x02;
+
+    /**
+     * An integer representing the end of the line has Armentian hyphen (U+058A).
+     */
+    public static final int END_HYPHEN_EDIT_INSERT_ARMENIAN_HYPHEN = 0x03;
+
+    /**
+     * An integer representing the end of the line has maqaf (Hebrew hyphen, U+05BE).
+     */
+    public static final int END_HYPHEN_EDIT_INSERT_MAQAF = 0x04;
+
+    /**
+     * An integer representing the end of the line has Canadian Syllabics hyphen (U+1400).
+     */
+    public static final int END_HYPHEN_EDIT_INSERT_UCAS_HYPHEN = 0x05;
+
+    /**
+     * An integer representing the end of the line has Zero-Width-Joiner (U+200D) followed by normal
+     * hyphen character (U+002D).
+     */
+    public static final int END_HYPHEN_EDIT_INSERT_ZWJ_AND_HYPHEN = 0x06;
+
+    // Following three constants are used for packing start hyphen edit and end hyphen edit into
+    // single integer. Following encodings must be the same as the minikin's one.
+    // See frameworks/minikin/include/Hyphenator.h for more details.
+    private static final int END_HYPHEN_EDIT_MASK = 0x07;  // 0b00111
+    private static final int START_HYPHEN_EDIT_MASK = 0x18;  // 0b11000
+    private static final int START_HYPHEN_EDIT_SHIFT = 0x03;
+
+    /**
+     * Extract start hyphen edit from packed value.
+     */
+    public static @StartHyphenEdit int unpackStartHyphenEdit(int hyphenEdit) {
+        return (hyphenEdit & START_HYPHEN_EDIT_MASK) >> START_HYPHEN_EDIT_SHIFT;
+    }
+
+    /**
+     * Extract end hyphen edit from packed value.
+     */
+    public static @EndHyphenEdit int unpackEndHyphenEdit(int hyphenEdit) {
+        return hyphenEdit & END_HYPHEN_EDIT_MASK;
+    }
+
+    /**
+     * Pack the start hyphen edit and end hyphen edit into single integer.
+     */
+    public static int packHyphenEdit(@StartHyphenEdit int startHyphenEdit,
+            @EndHyphenEdit int endHyphenEdit) {
+        return ((startHyphenEdit << START_HYPHEN_EDIT_SHIFT) & START_HYPHEN_EDIT_MASK)
+                | (endHyphenEdit & END_HYPHEN_EDIT_MASK);
+    }
+
+
+    /**
+     * @hide
+     */
     public static void init() {
         nInit();
     }
+
     private static native void nInit();
 }
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
index 128f860..e1ffef0 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -22,6 +22,7 @@
 import android.annotation.Nullable;
 import android.annotation.UnsupportedAppUsage;
 import android.graphics.Paint;
+import android.os.Build;
 import android.text.style.LeadingMarginSpan;
 import android.text.style.LeadingMarginSpan.LeadingMarginSpan2;
 import android.text.style.LineHeightSpan;
@@ -1216,11 +1217,19 @@
     }
 
     /**
+     * Returns the packed hyphen edit value for this line.
+     *
+     * You can extract start hyphen edit and end hyphen edit by using
+     * {@link Hyphenator#unpackStartHyphenEdit(int)} and
+     * {@link Hyphenator#unpackEndHyphenEdit(int)}.
+     *
+     * @param lineNumber a line number
+     * @return A packed hyphen edit value.
      * @hide
      */
     @Override
-    public int getHyphen(int line) {
-        return mLines[mColumns * line + HYPHEN] & HYPHEN_MASK;
+    public int getHyphen(int lineNumber) {
+        return mLines[mColumns * lineNumber + HYPHEN] & HYPHEN_MASK;
     }
 
     /**
@@ -1285,7 +1294,7 @@
      *
      * @hide
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     public int getHeight(boolean cap) {
         if (cap && mLineCount > mMaximumVisibleLineCount && mMaxLineHeight == -1
                 && Log.isLoggable(TAG, Log.WARN)) {
diff --git a/core/java/android/text/TextLine.java b/core/java/android/text/TextLine.java
index 9667b106..ad7a851 100644
--- a/core/java/android/text/TextLine.java
+++ b/core/java/android/text/TextLine.java
@@ -22,6 +22,7 @@
 import android.graphics.Canvas;
 import android.graphics.Paint;
 import android.graphics.Paint.FontMetricsInt;
+import android.os.Build;
 import android.text.Layout.Directions;
 import android.text.Layout.TabStops;
 import android.text.style.CharacterStyle;
@@ -61,7 +62,7 @@
     private TabStops mTabs;
     private char[] mChars;
     private boolean mCharsValid;
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private Spanned mSpanned;
     private PrecomputedText mComputed;
 
@@ -1053,13 +1054,16 @@
         return runIsRtl ? -ret : ret;
     }
 
-    private int adjustHyphenEdit(int start, int limit, int hyphenEdit) {
-        int result = hyphenEdit;
+    private int adjustHyphenEdit(int start, int limit, int packedHyphenEdit) {
+        int result = packedHyphenEdit;
         // Only draw hyphens on first or last run in line. Disable them otherwise.
         if (start > 0) { // not the first run
-            result &= ~Paint.HYPHENEDIT_MASK_START_OF_LINE;
+            result = Hyphenator.packHyphenEdit(Hyphenator.START_HYPHEN_EDIT_NO_EDIT,
+                    Hyphenator.unpackEndHyphenEdit(packedHyphenEdit));
         }
         if (limit < mLen) { // not the last run
+            result = Hyphenator.packHyphenEdit(Hyphenator.unpackStartHyphenEdit(packedHyphenEdit),
+                    Hyphenator.END_HYPHEN_EDIT_NO_EDIT);
             result &= ~Paint.HYPHENEDIT_MASK_END_OF_LINE;
         }
         return result;
diff --git a/core/java/android/text/style/LineHeightSpan.java b/core/java/android/text/style/LineHeightSpan.java
index 50ee5f3..2742ae0 100644
--- a/core/java/android/text/style/LineHeightSpan.java
+++ b/core/java/android/text/style/LineHeightSpan.java
@@ -16,11 +16,16 @@
 
 package android.text.style;
 
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.annotation.Px;
 import android.graphics.Paint;
 import android.text.TextPaint;
 
+import com.android.internal.util.Preconditions;
+
 /**
- * The classes that affect the height of the line should implement this interface.
+ * The classes that affect the line height of paragraph should implement this interface.
  */
 public interface LineHeightSpan extends ParagraphStyle, WrapTogetherSpan {
     /**
@@ -38,8 +43,8 @@
             Paint.FontMetricsInt fm);
 
     /**
-     * The classes that affect the height of the line with respect to density, should implement this
-     * interface.
+     * The classes that affect the line height of paragraph with respect to density,
+     * should implement this interface.
      */
     public interface WithDensity extends LineHeightSpan {
 
@@ -57,4 +62,38 @@
                 int spanstartv, int lineHeight,
                 Paint.FontMetricsInt fm, TextPaint paint);
     }
+
+    /**
+     * Default implementation of the {@link LineHeightSpan}, which changes the line height of the
+     * attached paragraph.
+     * <p>
+     * LineHeightSpan will change the line height of the entire paragraph, even though it
+     * covers only part of the paragraph.
+     * </p>
+     */
+    class Standard implements LineHeightSpan {
+
+        private final @Px int mHeight;
+        /**
+         * Set the line height of the paragraph to <code>height</code> physical pixels.
+         */
+        public Standard(@Px @IntRange(from = 1) int height) {
+            Preconditions.checkArgument(height > 0, "Height:" + height + "must be positive");
+            mHeight = height;
+        }
+
+        @Override
+        public void chooseHeight(@NonNull CharSequence text, int start, int end,
+                int spanstartv, int lineHeight,
+                @NonNull Paint.FontMetricsInt fm) {
+            final int originHeight = fm.descent - fm.ascent;
+            // If original height is not positive, do nothing.
+            if (originHeight <= 0) {
+                return;
+            }
+            final float ratio = mHeight * 1.0f / originHeight;
+            fm.descent = Math.round(fm.descent * ratio);
+            fm.ascent = fm.descent - mHeight;
+        }
+    }
 }
diff --git a/core/java/android/transition/Fade.java b/core/java/android/transition/Fade.java
index 38b89dc..41d80fc 100644
--- a/core/java/android/transition/Fade.java
+++ b/core/java/android/transition/Fade.java
@@ -94,7 +94,7 @@
      * @param fadingMode The behavior of this transition, a combination of
      * {@link #IN} and {@link #OUT}.
      */
-    public Fade(int fadingMode) {
+    public Fade(@VisibilityMode int fadingMode) {
         setMode(fadingMode);
     }
 
diff --git a/core/java/android/transition/Slide.java b/core/java/android/transition/Slide.java
index 9cf3210..14a513b 100644
--- a/core/java/android/transition/Slide.java
+++ b/core/java/android/transition/Slide.java
@@ -147,7 +147,7 @@
     /**
      * Constructor using the provided slide edge direction.
      */
-    public Slide(int slideEdge) {
+    public Slide(@GravityFlag int slideEdge) {
         setSlideEdge(slideEdge);
     }
 
diff --git a/core/java/android/transition/Visibility.java b/core/java/android/transition/Visibility.java
index 77c652e..319f080 100644
--- a/core/java/android/transition/Visibility.java
+++ b/core/java/android/transition/Visibility.java
@@ -52,9 +52,11 @@
 
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
-    @IntDef(flag = true, prefix = { "MODE_" }, value = {
+    @IntDef(flag = true, value = {
             MODE_IN,
-            MODE_OUT
+            MODE_OUT,
+            Fade.IN,
+            Fade.OUT
     })
     @interface VisibilityMode {}
 
diff --git a/core/java/android/util/DisplayMetrics.java b/core/java/android/util/DisplayMetrics.java
old mode 100644
new mode 100755
index b092fcf..f2747cf
--- a/core/java/android/util/DisplayMetrics.java
+++ b/core/java/android/util/DisplayMetrics.java
@@ -142,6 +142,14 @@
     public static final int DENSITY_560 = 560;
 
     /**
+     * Intermediate density for screens that sit somewhere between
+     * {@link #DENSITY_XXHIGH} (480 dpi) and {@link #DENSITY_XXXHIGH} (640 dpi).
+     * This is not a density that applications should target, instead relying
+     * on the system to scale their {@link #DENSITY_XXXHIGH} assets for them.
+     */
+    public static final int DENSITY_600 = 600;
+
+    /**
      * Standard quantized DPI for extra-extra-extra-high-density screens.  Applications
      * should not generally worry about this density; relying on XHIGH graphics
      * being scaled up to it should be sufficient for almost all cases.  A typical
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index a7f14b6..ff6e86e 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -39,12 +39,13 @@
     private static final Map<String, String> DEFAULT_FLAGS;
     static {
         DEFAULT_FLAGS = new HashMap<>();
-        DEFAULT_FLAGS.put("settings_battery_display_app_list", "false");
         DEFAULT_FLAGS.put("settings_bluetooth_while_driving", "false");
         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("settings_data_usage_v2", "false");
+        DEFAULT_FLAGS.put("settings_seamless_transfer", "false");
         DEFAULT_FLAGS.put(HEARING_AID_SETTINGS, "true");
     }
 
diff --git a/core/java/android/util/TypedValue.java b/core/java/android/util/TypedValue.java
index 2c9bb66..ea4464d 100644
--- a/core/java/android/util/TypedValue.java
+++ b/core/java/android/util/TypedValue.java
@@ -232,6 +232,18 @@
     };
 
     /**
+     * Determine if a value is a color.
+     *
+     * This works by comparing {@link #type} to {@link #TYPE_FIRST_COLOR_INT}
+     * and {@link #TYPE_LAST_COLOR_INT}.
+     *
+     * @return true if this value is a color
+     */
+    public boolean isColorType() {
+        return (type >= TYPE_FIRST_COLOR_INT && type <= TYPE_LAST_COLOR_INT);
+    }
+
+    /**
      * Retrieve the base value from a complex data integer.  This uses the 
      * {@link #COMPLEX_MANTISSA_MASK} and {@link #COMPLEX_RADIX_MASK} fields of 
      * the data to compute a floating point representation of the number they 
diff --git a/core/java/android/util/proto/ProtoInputStream.java b/core/java/android/util/proto/ProtoInputStream.java
new file mode 100644
index 0000000..209451b
--- /dev/null
+++ b/core/java/android/util/proto/ProtoInputStream.java
@@ -0,0 +1,978 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.util.proto;
+
+import android.annotation.TestApi;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+
+/**
+ * Class to read to a protobuf stream.
+ *
+ * Each read method takes an ID code from the protoc generated classes
+ * and return a value of the field. To read a nested object, call #start
+ * and then #end when you are done.
+ *
+ * The ID codes have type information embedded into them, so if you call
+ * the incorrect function you will get an IllegalArgumentException.
+ *
+ * nextField will return the field number of the next field, which can be
+ * matched to the protoc generated ID code and used to determine how to
+ * read the next field.
+ *
+ * It is STRONGLY RECOMMENDED to read from the ProtoInputStream with a switch
+ * statement wrapped in a while loop. Additionally, it is worth logging or
+ * storing unexpected fields or ones that do not match the expected wire type
+ *
+ * ex:
+ * void parseFromProto(ProtoInputStream stream) {
+ *     while(stream.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
+ *         try {
+ *             switch (stream.getFieldNumber()) {
+ *                 case (int) DummyProto.NAME:
+ *                     mName = stream.readString(DummyProto.NAME);
+ *                     break;
+ *                 case (int) DummyProto.VALUE:
+ *                     mValue = stream.readInt(DummyProto.VALUE);
+ *                     break;
+ *                 default:
+ *                     LOG(TAG, "Unhandled field in proto!\n"
+ *                              + ProtoUtils.currentFieldToString(stream));
+ *             }
+ *         } catch (WireTypeMismatchException wtme) {
+ *             LOG(TAG, "Wire Type mismatch in proto!\n" + ProtoUtils.currentFieldToString(stream));
+ *         }
+ *     }
+ * }
+ *
+ * @hide
+ */
+@TestApi
+public final class ProtoInputStream extends ProtoStream {
+
+    public static final int NO_MORE_FIELDS = -1;
+
+    /**
+     * Our stream.  If there is one.
+     */
+    private InputStream mStream;
+
+    /**
+     * The field number of the current field. Will be equal to NO_MORE_FIELDS if end of message is
+     * reached
+     */
+    private int mFieldNumber;
+
+    /**
+     * The wire type of the current field
+     */
+    private int mWireType;
+
+    private static final byte STATE_STARTED_FIELD_READ = 1 << 0;
+    private static final byte STATE_READING_PACKED = 1 << 1;
+    private static final byte STATE_FIELD_MISS = 2 << 1;
+
+    /**
+     * Tracks some boolean states for the proto input stream
+     * bit 0: Started Field Read, true - tag has been read, ready to read field data.
+     * false - field data has been read, reading to start next field.
+     * bit 1: Reading Packed Field, true - currently reading values from a packed field
+     * false - not reading from packed field.
+     */
+    private byte mState = 0;
+
+    /**
+     * Keeps track of the currently read nested Objects, for end object sanity checking and debug
+     */
+    private ArrayList<Long> mExpectedObjectTokenStack = null;
+
+    /**
+     * Current nesting depth of start calls.
+     */
+    private int mDepth = -1;
+
+    /**
+     * Buffer for the to be read data. If mStream is not null, it will be constantly refilled from
+     * the stream.
+     */
+    private byte[] mBuffer;
+
+    private static final int DEFAULT_BUFFER_SIZE = 8192;
+
+    /**
+     * Size of the buffer if reading from a stream.
+     */
+    private final int mBufferSize;
+
+    /**
+     * The number of bytes that have been skipped or dropped from the buffer.
+     */
+    private int mDiscardedBytes = 0;
+
+    /**
+     * Current offset in the buffer
+     * mOffset + mDiscardedBytes = current offset in proto binary
+     */
+    private int mOffset = 0;
+
+    /**
+     * Note the offset of the last byte in the buffer. Usually will equal the size of the buffer.
+     * mEnd + mDiscardedBytes = the last known byte offset + 1
+     */
+    private int mEnd = 0;
+
+    /**
+     * Packed repeated fields are not read in one go. mPackedEnd keeps track of where the packed
+     * field ends in the proto binary if current field is packed.
+     */
+    private int mPackedEnd = 0;
+
+    /**
+     * Construct a ProtoInputStream on top of an InputStream to read a proto. Also specify the
+     * number of bytes the ProtoInputStream will buffer from the input stream
+     *
+     * @param stream from which the proto is read
+     */
+    public ProtoInputStream(InputStream stream, int bufferSize) {
+        mStream = stream;
+        if (bufferSize > 0) {
+            mBufferSize = bufferSize;
+        } else {
+            mBufferSize = DEFAULT_BUFFER_SIZE;
+        }
+        mBuffer = new byte[mBufferSize];
+    }
+
+    /**
+     * Construct a ProtoInputStream on top of an InputStream to read a proto
+     *
+     * @param stream from which the proto is read
+     */
+    public ProtoInputStream(InputStream stream) {
+        this(stream, DEFAULT_BUFFER_SIZE);
+    }
+
+    /**
+     * Construct a ProtoInputStream to read a proto directly from a byte array
+     *
+     * @param buffer - the byte array to be parsed
+     */
+    public ProtoInputStream(byte[] buffer) {
+        mBufferSize = buffer.length;
+        mEnd = buffer.length;
+        mBuffer = buffer;
+        mStream = null;
+    }
+
+    /**
+     * Get the field number of the current field.
+     */
+    public int getFieldNumber() {
+        return mFieldNumber;
+    }
+
+    /**
+     * Get the wire type of the current field.
+     *
+     * @return an int that matches one of the ProtoStream WIRE_TYPE_ constants
+     */
+    public int getWireType() {
+        if ((mState & STATE_READING_PACKED) == STATE_READING_PACKED) {
+            // mWireType got overwritten when STATE_READING_PACKED was set. Send length delimited
+            // constant instead
+            return WIRE_TYPE_LENGTH_DELIMITED;
+        }
+        return mWireType;
+    }
+
+    /**
+     * Get the current offset in the proto binary.
+     */
+    public int getOffset() {
+        return mOffset + mDiscardedBytes;
+    }
+
+    /**
+     * Reads the tag of the next field from the stream. If previous field value was not read, its
+     * data will be skipped over.
+     *
+     * @return the field number of the next field
+     * @throws IOException if an I/O error occurs
+     */
+    public int nextField() throws IOException {
+
+        if ((mState & STATE_FIELD_MISS) == STATE_FIELD_MISS) {
+            // Data from the last nextField was not used, reuse the info
+            mState &= ~STATE_FIELD_MISS;
+            return mFieldNumber;
+        }
+        if ((mState & STATE_STARTED_FIELD_READ) == STATE_STARTED_FIELD_READ) {
+            // Field data was not read, skip to the next field
+            skip();
+            mState &= ~STATE_STARTED_FIELD_READ;
+        }
+        if ((mState & STATE_READING_PACKED) == STATE_READING_PACKED) {
+            if (getOffset() < mPackedEnd) {
+                // In the middle of a packed field, return the same tag until last packed value
+                // has been read
+                mState |= STATE_STARTED_FIELD_READ;
+                return mFieldNumber;
+            } else if (getOffset() == mPackedEnd) {
+                // Reached the end of the packed field
+                mState &= ~STATE_READING_PACKED;
+            } else {
+                throw new ProtoParseException(
+                        "Unexpectedly reached end of packed field at offset 0x"
+                                + Integer.toHexString(mPackedEnd)
+                                + dumpDebugData());
+            }
+        }
+
+        if ((mDepth >= 0) && (getOffset() == getOffsetFromToken(
+                mExpectedObjectTokenStack.get(mDepth)))) {
+            // reached end of a embedded message
+            mFieldNumber = NO_MORE_FIELDS;
+        } else {
+            readTag();
+        }
+        return mFieldNumber;
+    }
+
+    /**
+     * Attempt to guess the next field. If there is a match, the field data will be ready to read.
+     * If there is no match, nextField will need to be called to get the field number
+     *
+     * @return true if fieldId matches the next field, false if not
+     */
+    public boolean isNextField(long fieldId) throws IOException {
+        if (nextField() == (int) fieldId) {
+            return true;
+        }
+        // Note to reuse the info from the nextField call in the next call.
+        mState |= STATE_FIELD_MISS;
+        return false;
+    }
+
+    /**
+     * Read a single double.
+     * Will throw if the current wire type is not fixed64
+     *
+     * @param fieldId - must match the current field number and field type
+     */
+    public double readDouble(long fieldId) throws IOException {
+        assertFreshData();
+        assertFieldNumber(fieldId);
+        checkPacked(fieldId);
+
+        double value;
+        switch ((int) ((fieldId & FIELD_TYPE_MASK)
+                >>> FIELD_TYPE_SHIFT)) {
+            case (int) (FIELD_TYPE_DOUBLE >>> FIELD_TYPE_SHIFT):
+                assertWireType(WIRE_TYPE_FIXED64);
+                value = Double.longBitsToDouble(readFixed64());
+                break;
+            default:
+                throw new IllegalArgumentException(
+                        "Requested field id (" + getFieldIdString(fieldId)
+                                + ") cannot be read as a double"
+                                + dumpDebugData());
+        }
+        // Successfully read the field
+        mState &= ~STATE_STARTED_FIELD_READ;
+        return value;
+    }
+
+    /**
+     * Read a single float.
+     * Will throw if the current wire type is not fixed32
+     *
+     * @param fieldId - must match the current field number and field type
+     */
+    public float readFloat(long fieldId) throws IOException {
+        assertFreshData();
+        assertFieldNumber(fieldId);
+        checkPacked(fieldId);
+
+        float value;
+        switch ((int) ((fieldId & FIELD_TYPE_MASK)
+                >>> FIELD_TYPE_SHIFT)) {
+            case (int) (FIELD_TYPE_FLOAT >>> FIELD_TYPE_SHIFT):
+                assertWireType(WIRE_TYPE_FIXED32);
+                value = Float.intBitsToFloat(readFixed32());
+                break;
+            default:
+                throw new IllegalArgumentException(
+                        "Requested field id (" + getFieldIdString(fieldId) + ") is not a float"
+                                + dumpDebugData());
+        }
+        // Successfully read the field
+        mState &= ~STATE_STARTED_FIELD_READ;
+        return value;
+    }
+
+    /**
+     * Read a single 32bit or varint proto type field as an int.
+     * Will throw if the current wire type is not varint or fixed32
+     *
+     * @param fieldId - must match the current field number and field type
+     */
+    public int readInt(long fieldId) throws IOException {
+        assertFreshData();
+        assertFieldNumber(fieldId);
+        checkPacked(fieldId);
+
+        int value;
+        switch ((int) ((fieldId & FIELD_TYPE_MASK)
+                >>> FIELD_TYPE_SHIFT)) {
+            case (int) (FIELD_TYPE_FIXED32 >>> FIELD_TYPE_SHIFT):
+            case (int) (FIELD_TYPE_SFIXED32 >>> FIELD_TYPE_SHIFT):
+                assertWireType(WIRE_TYPE_FIXED32);
+                value = readFixed32();
+                break;
+            case (int) (FIELD_TYPE_SINT32 >>> FIELD_TYPE_SHIFT):
+                assertWireType(WIRE_TYPE_VARINT);
+                value = decodeZigZag32((int) readVarint());
+                break;
+            case (int) (FIELD_TYPE_INT32 >>> FIELD_TYPE_SHIFT):
+            case (int) (FIELD_TYPE_UINT32 >>> FIELD_TYPE_SHIFT):
+            case (int) (FIELD_TYPE_ENUM >>> FIELD_TYPE_SHIFT):
+                assertWireType(WIRE_TYPE_VARINT);
+                value = (int) readVarint();
+                break;
+            default:
+                throw new IllegalArgumentException(
+                        "Requested field id (" + getFieldIdString(fieldId) + ") is not an int"
+                                + dumpDebugData());
+        }
+        // Successfully read the field
+        mState &= ~STATE_STARTED_FIELD_READ;
+        return value;
+    }
+
+    /**
+     * Read a single 64bit or varint proto type field as an long.
+     *
+     * @param fieldId - must match the current field number
+     */
+    public long readLong(long fieldId) throws IOException {
+        assertFreshData();
+        assertFieldNumber(fieldId);
+        checkPacked(fieldId);
+
+        long value;
+        switch ((int) ((fieldId & FIELD_TYPE_MASK)
+                >>> FIELD_TYPE_SHIFT)) {
+            case (int) (FIELD_TYPE_FIXED64 >>> FIELD_TYPE_SHIFT):
+            case (int) (FIELD_TYPE_SFIXED64 >>> FIELD_TYPE_SHIFT):
+                assertWireType(WIRE_TYPE_FIXED64);
+                value = readFixed64();
+                break;
+            case (int) (FIELD_TYPE_SINT64 >>> FIELD_TYPE_SHIFT):
+                assertWireType(WIRE_TYPE_VARINT);
+                value = decodeZigZag64(readVarint());
+                break;
+            case (int) (FIELD_TYPE_INT64 >>> FIELD_TYPE_SHIFT):
+            case (int) (FIELD_TYPE_UINT64 >>> FIELD_TYPE_SHIFT):
+                assertWireType(WIRE_TYPE_VARINT);
+                value = readVarint();
+                break;
+            default:
+                throw new IllegalArgumentException(
+                        "Requested field id (" + getFieldIdString(fieldId) + ") is not an long"
+                                + dumpDebugData());
+        }
+        // Successfully read the field
+        mState &= ~STATE_STARTED_FIELD_READ;
+        return value;
+    }
+
+    /**
+     * Read a single 32bit or varint proto type field as an boolean.
+     *
+     * @param fieldId - must match the current field number
+     */
+    public boolean readBoolean(long fieldId) throws IOException {
+        assertFreshData();
+        assertFieldNumber(fieldId);
+        checkPacked(fieldId);
+
+        boolean value;
+        switch ((int) ((fieldId & FIELD_TYPE_MASK)
+                >>> FIELD_TYPE_SHIFT)) {
+            case (int) (FIELD_TYPE_BOOL >>> FIELD_TYPE_SHIFT):
+                assertWireType(WIRE_TYPE_VARINT);
+                value = readVarint() != 0;
+                break;
+            default:
+                throw new IllegalArgumentException(
+                        "Requested field id (" + getFieldIdString(fieldId) + ") is not an boolean"
+                                + dumpDebugData());
+        }
+        // Successfully read the field
+        mState &= ~STATE_STARTED_FIELD_READ;
+        return value;
+    }
+
+    /**
+     * Read a string field
+     *
+     * @param fieldId - must match the current field number
+     */
+    public String readString(long fieldId) throws IOException {
+        assertFreshData();
+        assertFieldNumber(fieldId);
+
+        String value;
+        switch ((int) ((fieldId & FIELD_TYPE_MASK) >>> FIELD_TYPE_SHIFT)) {
+            case (int) (FIELD_TYPE_STRING >>> FIELD_TYPE_SHIFT):
+                assertWireType(WIRE_TYPE_LENGTH_DELIMITED);
+                int len = (int) readVarint();
+                value = readRawString(len);
+                break;
+            default:
+                throw new IllegalArgumentException(
+                        "Requested field id(" + getFieldIdString(fieldId)
+                                + ") is not an string"
+                                + dumpDebugData());
+        }
+        // Successfully read the field
+        mState &= ~STATE_STARTED_FIELD_READ;
+        return value;
+    }
+
+    /**
+     * Read a bytes field
+     *
+     * @param fieldId - must match the current field number
+     */
+    public byte[] readBytes(long fieldId) throws IOException {
+        assertFreshData();
+        assertFieldNumber(fieldId);
+
+        byte[] value;
+        switch ((int) ((fieldId & FIELD_TYPE_MASK) >>> FIELD_TYPE_SHIFT)) {
+            case (int) (FIELD_TYPE_MESSAGE >>> FIELD_TYPE_SHIFT):
+            case (int) (FIELD_TYPE_BYTES >>> FIELD_TYPE_SHIFT):
+                assertWireType(WIRE_TYPE_LENGTH_DELIMITED);
+                int len = (int) readVarint();
+                value = readRawBytes(len);
+                break;
+            default:
+                throw new IllegalArgumentException(
+                        "Requested field type (" + getFieldIdString(fieldId)
+                                + ") cannot be read as raw bytes"
+                                + dumpDebugData());
+        }
+        // Successfully read the field
+        mState &= ~STATE_STARTED_FIELD_READ;
+        return value;
+    }
+
+    /**
+     * Start the read of an embedded Object
+     *
+     * @param fieldId - must match the current field number
+     * @return a token. The token must be handed back when finished reading embedded Object
+     */
+    public long start(long fieldId) throws IOException {
+        assertFreshData();
+        assertFieldNumber(fieldId);
+        assertWireType(WIRE_TYPE_LENGTH_DELIMITED);
+
+        int messageSize = (int) readVarint();
+
+        if (mExpectedObjectTokenStack == null) {
+            mExpectedObjectTokenStack = new ArrayList<>();
+        }
+        if (++mDepth == mExpectedObjectTokenStack.size()) {
+            // Create a token to keep track of nested Object and extend the object stack
+            mExpectedObjectTokenStack.add(makeToken(0,
+                    (fieldId & FIELD_COUNT_REPEATED) == FIELD_COUNT_REPEATED, mDepth,
+                    (int) fieldId, getOffset() + messageSize));
+
+        } else {
+            // Create a token to keep track of nested Object
+            mExpectedObjectTokenStack.set(mDepth, makeToken(0,
+                    (fieldId & FIELD_COUNT_REPEATED) == FIELD_COUNT_REPEATED, mDepth,
+                    (int) fieldId, getOffset() + messageSize));
+        }
+
+        // Sanity check
+        if (mDepth > 0
+                && getOffsetFromToken(mExpectedObjectTokenStack.get(mDepth))
+                > getOffsetFromToken(mExpectedObjectTokenStack.get(mDepth - 1))) {
+            throw new ProtoParseException("Embedded Object ("
+                    + token2String(mExpectedObjectTokenStack.get(mDepth))
+                    + ") ends after of parent Objects's ("
+                    + token2String(mExpectedObjectTokenStack.get(mDepth - 1))
+                    + ") end"
+                    + dumpDebugData());
+        }
+        mState &= ~STATE_STARTED_FIELD_READ;
+        return mExpectedObjectTokenStack.get(mDepth);
+    }
+
+    /**
+     * Note the end of a nested object. Must be called to continue streaming the rest of the proto.
+     * end can be called mid object parse. The offset will be moved to the next field outside the
+     * object.
+     *
+     * @param token - token
+     */
+    public void end(long token) {
+        // Sanity check to make sure user is keeping track of their embedded messages
+        if (mExpectedObjectTokenStack.get(mDepth) != token) {
+            throw new ProtoParseException(
+                    "end token " + token + " does not match current message token "
+                            + mExpectedObjectTokenStack.get(mDepth)
+                            + dumpDebugData());
+        }
+        if (getOffsetFromToken(mExpectedObjectTokenStack.get(mDepth)) > getOffset()) {
+            // Did not read all of the message, skip to the end
+            incOffset(getOffsetFromToken(mExpectedObjectTokenStack.get(mDepth)) - getOffset());
+        }
+        mDepth--;
+        mState &= ~STATE_STARTED_FIELD_READ;
+    }
+
+    /**
+     * Read the tag at the start of the next field and collect field number and wire type.
+     * Will set mFieldNumber to NO_MORE_FIELDS if end of buffer/stream reached.
+     */
+    private void readTag() throws IOException {
+        fillBuffer();
+        if (mOffset >= mEnd) {
+            // reached end of the stream
+            mFieldNumber = NO_MORE_FIELDS;
+            return;
+        }
+        int tag = (int) readVarint();
+        mFieldNumber = tag >>> FIELD_ID_SHIFT;
+        mWireType = tag & WIRE_TYPE_MASK;
+        mState |= STATE_STARTED_FIELD_READ;
+    }
+
+    /**
+     * Decode a 32 bit ZigZag encoded signed int.
+     *
+     * @param n - int to decode
+     * @return the decoded signed int
+     */
+    public int decodeZigZag32(final int n) {
+        return (n >>> 1) ^ -(n & 1);
+    }
+
+    /**
+     * Decode a 64 bit ZigZag encoded signed long.
+     *
+     * @param n - long to decode
+     * @return the decoded signed long
+     */
+    public long decodeZigZag64(final long n) {
+        return (n >>> 1) ^ -(n & 1);
+    }
+
+    /**
+     * Read a varint from the buffer
+     *
+     * @return the varint as a long
+     */
+    private long readVarint() throws IOException {
+        long value = 0;
+        int shift = 0;
+        while (true) {
+            fillBuffer();
+            // Limit how much bookkeeping is done by checking how far away the end of the buffer is
+            // and directly accessing buffer up until the end.
+            final int fragment = mEnd - mOffset;
+            for (int i = 0; i < fragment; i++) {
+                byte b = mBuffer[(mOffset + i)];
+                value |= (b & 0x7FL) << shift;
+                if ((b & 0x80) == 0) {
+                    incOffset(i + 1);
+                    return value;
+                }
+                shift += 7;
+                if (shift > 63) {
+                    throw new ProtoParseException(
+                            "Varint is too large at offset 0x"
+                                    + Integer.toHexString(getOffset() + i)
+                                    + dumpDebugData());
+                }
+            }
+            // Hit the end of the buffer, do some incrementing and checking, then continue
+            incOffset(fragment);
+        }
+    }
+
+    /**
+     * Read a fixed 32 bit int from the buffer
+     *
+     * @return the fixed32 as a int
+     */
+    private int readFixed32() throws IOException {
+        // check for fast path, which is likely with a reasonable buffer size
+        if (mOffset + 4 <= mEnd) {
+            // don't bother filling buffer since we know the end is plenty far away
+            incOffset(4);
+            return (mBuffer[mOffset - 4] & 0xFF)
+                    | ((mBuffer[mOffset - 3] & 0xFF) << 8)
+                    | ((mBuffer[mOffset - 2] & 0xFF) << 16)
+                    | ((mBuffer[mOffset - 1] & 0xFF) << 24);
+        }
+
+        // the Fixed32 crosses the edge of a chunk, read the Fixed32 in multiple fragments.
+        // There will be two fragment reads except when the chunk size is 2 or less.
+        int value = 0;
+        int shift = 0;
+        int bytesLeft = 4;
+        while (bytesLeft > 0) {
+            fillBuffer();
+            // Find the number of bytes available until the end of the chunk or Fixed32
+            int fragment = (mEnd - mOffset) < bytesLeft ? (mEnd - mOffset) : bytesLeft;
+            incOffset(fragment);
+            bytesLeft -= fragment;
+            while (fragment > 0) {
+                value |= ((mBuffer[mOffset - fragment] & 0xFF) << shift);
+                fragment--;
+                shift += 8;
+            }
+        }
+        return value;
+    }
+
+    /**
+     * Read a fixed 64 bit long from the buffer
+     *
+     * @return the fixed64 as a long
+     */
+    private long readFixed64() throws IOException {
+        // check for fast path, which is likely with a reasonable buffer size
+        if (mOffset + 8 <= mEnd) {
+            // don't bother filling buffer since we know the end is plenty far away
+            incOffset(8);
+            return (mBuffer[mOffset - 8] & 0xFFL)
+                    | ((mBuffer[mOffset - 7] & 0xFFL) << 8)
+                    | ((mBuffer[mOffset - 6] & 0xFFL) << 16)
+                    | ((mBuffer[mOffset - 5] & 0xFFL) << 24)
+                    | ((mBuffer[mOffset - 4] & 0xFFL) << 32)
+                    | ((mBuffer[mOffset - 3] & 0xFFL) << 40)
+                    | ((mBuffer[mOffset - 2] & 0xFFL) << 48)
+                    | ((mBuffer[mOffset - 1] & 0xFFL) << 56);
+        }
+
+        // the Fixed64 crosses the edge of a chunk, read the Fixed64 in multiple fragments.
+        // There will be two fragment reads except when the chunk size is 6 or less.
+        long value = 0;
+        int shift = 0;
+        int bytesLeft = 8;
+        while (bytesLeft > 0) {
+            fillBuffer();
+            // Find the number of bytes available until the end of the chunk or Fixed64
+            int fragment = (mEnd - mOffset) < bytesLeft ? (mEnd - mOffset) : bytesLeft;
+            incOffset(fragment);
+            bytesLeft -= fragment;
+            while (fragment > 0) {
+                value |= ((mBuffer[(mOffset - fragment)] & 0xFFL) << shift);
+                fragment--;
+                shift += 8;
+            }
+        }
+        return value;
+    }
+
+    /**
+     * Read raw bytes from the buffer
+     *
+     * @param n - number of bytes to read
+     * @return a byte array with raw bytes
+     */
+    private byte[] readRawBytes(int n) throws IOException {
+        byte[] buffer = new byte[n];
+        int pos = 0;
+        while (mOffset + n - pos > mEnd) {
+            int fragment = mEnd - mOffset;
+            if (fragment > 0) {
+                System.arraycopy(mBuffer, mOffset, buffer, pos, fragment);
+                incOffset(fragment);
+                pos += fragment;
+            }
+            fillBuffer();
+            if (mOffset >= mEnd) {
+                throw new ProtoParseException(
+                        "Unexpectedly reached end of the InputStream at offset 0x"
+                                + Integer.toHexString(mEnd)
+                                + dumpDebugData());
+            }
+        }
+        System.arraycopy(mBuffer, mOffset, buffer, pos, n - pos);
+        incOffset(n - pos);
+        return buffer;
+    }
+
+    /**
+     * Read raw string from the buffer
+     *
+     * @param n - number of bytes to read
+     * @return a string
+     */
+    private String readRawString(int n) throws IOException {
+        fillBuffer();
+        if (mOffset + n <= mEnd) {
+            // fast path read. String is well within the current buffer
+            String value = StringFactory.newStringFromBytes(mBuffer, mOffset, n,
+                    StandardCharsets.UTF_8);
+            incOffset(n);
+            return value;
+        } else if (n <= mBufferSize) {
+            // String extends past buffer, but can be encapsulated in a buffer. Copy the first chunk
+            // of the string to the start of the buffer and then fill the rest of the buffer from
+            // the stream.
+            final int stringHead = mEnd - mOffset;
+            System.arraycopy(mBuffer, mOffset, mBuffer, 0, stringHead);
+            mEnd = stringHead + mStream.read(mBuffer, stringHead, n - stringHead);
+
+            mDiscardedBytes += mOffset;
+            mOffset = 0;
+
+            String value = StringFactory.newStringFromBytes(mBuffer, mOffset, n,
+                    StandardCharsets.UTF_8);
+            incOffset(n);
+            return value;
+        }
+        // Otherwise, the string is too large to use the buffer. Create the string from a
+        // separate byte array.
+        return StringFactory.newStringFromBytes(readRawBytes(n), 0, n, StandardCharsets.UTF_8);
+    }
+
+    /**
+     * Fill the buffer with a chunk from the stream if need be.
+     * Will skip chunks until mOffset is reached
+     */
+    private void fillBuffer() throws IOException {
+        if (mOffset >= mEnd && mStream != null) {
+            mOffset -= mEnd;
+            mDiscardedBytes += mEnd;
+            if (mOffset >= mBufferSize) {
+                int skipped = (int) mStream.skip((mOffset / mBufferSize) * mBufferSize);
+                mDiscardedBytes += skipped;
+                mOffset -= skipped;
+            }
+            mEnd = mStream.read(mBuffer);
+        }
+    }
+
+    /**
+     * Skips the rest of current field and moves to the start of the next field. This should only be
+     * called while state is STATE_STARTED_FIELD_READ
+     */
+    public void skip() throws IOException {
+        if ((mState & STATE_READING_PACKED) == STATE_READING_PACKED) {
+            incOffset(mPackedEnd - getOffset());
+        } else {
+            switch (mWireType) {
+                case WIRE_TYPE_VARINT:
+                    byte b;
+                    do {
+                        fillBuffer();
+                        b = mBuffer[mOffset];
+                        incOffset(1);
+                    } while ((b & 0x80) != 0);
+                    break;
+                case WIRE_TYPE_FIXED64:
+                    incOffset(8);
+                    break;
+                case WIRE_TYPE_LENGTH_DELIMITED:
+                    fillBuffer();
+                    int length = (int) readVarint();
+                    incOffset(length);
+                    break;
+                /*
+            case WIRE_TYPE_START_GROUP:
+                // Not implemented
+                break;
+            case WIRE_TYPE_END_GROUP:
+                // Not implemented
+                break;
+                */
+                case WIRE_TYPE_FIXED32:
+                    incOffset(4);
+                    break;
+                default:
+                    throw new ProtoParseException(
+                            "Unexpected wire type: " + mWireType + " at offset 0x"
+                                    + Integer.toHexString(mOffset)
+                                    + dumpDebugData());
+            }
+        }
+        mState &= ~STATE_STARTED_FIELD_READ;
+    }
+
+    /**
+     * Increment the offset and handle all the relevant bookkeeping
+     * Refilling the buffer when its end is reached will be handled elsewhere (ideally just before
+     * a read, to avoid unnecessary reads from stream)
+     *
+     * @param n - number of bytes to increment
+     */
+    private void incOffset(int n) {
+        mOffset += n;
+
+        if (mDepth >= 0 && getOffset() > getOffsetFromToken(
+                mExpectedObjectTokenStack.get(mDepth))) {
+            throw new ProtoParseException("Unexpectedly reached end of embedded object.  "
+                    + token2String(mExpectedObjectTokenStack.get(mDepth))
+                    + dumpDebugData());
+        }
+    }
+
+    /**
+     * Check the current wire type to determine if current numeric field is packed. If it is packed,
+     * set up to deal with the field
+     * This should only be called for primitive numeric field types.
+     *
+     * @param fieldId - used to determine what the packed wire type is.
+     */
+    private void checkPacked(long fieldId) throws IOException {
+        if (mWireType == WIRE_TYPE_LENGTH_DELIMITED) {
+            // Primitive Field is length delimited, must be a packed field.
+            final int length = (int) readVarint();
+            mPackedEnd = getOffset() + length;
+            mState |= STATE_READING_PACKED;
+
+            // Fake the wire type, based on the field type
+            switch ((int) ((fieldId & FIELD_TYPE_MASK)
+                    >>> FIELD_TYPE_SHIFT)) {
+                case (int) (FIELD_TYPE_FLOAT >>> FIELD_TYPE_SHIFT):
+                case (int) (FIELD_TYPE_FIXED32 >>> FIELD_TYPE_SHIFT):
+                case (int) (FIELD_TYPE_SFIXED32 >>> FIELD_TYPE_SHIFT):
+                    if (length % 4 != 0) {
+                        throw new IllegalArgumentException(
+                                "Requested field id (" + getFieldIdString(fieldId)
+                                        + ") packed length " + length
+                                        + " is not aligned for fixed32"
+                                        + dumpDebugData());
+                    }
+                    mWireType = WIRE_TYPE_FIXED32;
+                    break;
+                case (int) (FIELD_TYPE_DOUBLE >>> FIELD_TYPE_SHIFT):
+                case (int) (FIELD_TYPE_FIXED64 >>> FIELD_TYPE_SHIFT):
+                case (int) (FIELD_TYPE_SFIXED64 >>> FIELD_TYPE_SHIFT):
+                    if (length % 8 != 0) {
+                        throw new IllegalArgumentException(
+                                "Requested field id (" + getFieldIdString(fieldId)
+                                        + ") packed length " + length
+                                        + " is not aligned for fixed64"
+                                        + dumpDebugData());
+                    }
+                    mWireType = WIRE_TYPE_FIXED64;
+                    break;
+                case (int) (FIELD_TYPE_SINT32 >>> FIELD_TYPE_SHIFT):
+                case (int) (FIELD_TYPE_INT32 >>> FIELD_TYPE_SHIFT):
+                case (int) (FIELD_TYPE_UINT32 >>> FIELD_TYPE_SHIFT):
+                case (int) (FIELD_TYPE_SINT64 >>> FIELD_TYPE_SHIFT):
+                case (int) (FIELD_TYPE_INT64 >>> FIELD_TYPE_SHIFT):
+                case (int) (FIELD_TYPE_UINT64 >>> FIELD_TYPE_SHIFT):
+                case (int) (FIELD_TYPE_ENUM >>> FIELD_TYPE_SHIFT):
+                case (int) (FIELD_TYPE_BOOL >>> FIELD_TYPE_SHIFT):
+                    mWireType = WIRE_TYPE_VARINT;
+                    break;
+                default:
+                    throw new IllegalArgumentException(
+                            "Requested field id (" + getFieldIdString(fieldId)
+                                    + ") is not a packable field"
+                                    + dumpDebugData());
+            }
+        }
+    }
+
+
+    /**
+     * Check a field id constant against current field number
+     *
+     * @param fieldId - throws if fieldId does not match mFieldNumber
+     */
+    private void assertFieldNumber(long fieldId) {
+        if ((int) fieldId != mFieldNumber) {
+            throw new IllegalArgumentException("Requested field id (" + getFieldIdString(fieldId)
+                    + ") does not match current field number (0x" + Integer.toHexString(
+                    mFieldNumber)
+                    + ") at offset 0x" + Integer.toHexString(getOffset())
+                    + dumpDebugData());
+        }
+    }
+
+
+    /**
+     * Check a wire type against current wire type.
+     *
+     * @param wireType - throws if wireType does not match mWireType.
+     */
+    private void assertWireType(int wireType) {
+        if (wireType != mWireType) {
+            throw new WireTypeMismatchException(
+                    "Current wire type " + getWireTypeString(mWireType)
+                            + " does not match expected wire type " + getWireTypeString(wireType)
+                            + " at offset 0x" + Integer.toHexString(getOffset())
+                            + dumpDebugData());
+        }
+    }
+
+    /**
+     * Check if there is data ready to be read.
+     */
+    private void assertFreshData() {
+        if ((mState & STATE_STARTED_FIELD_READ) != STATE_STARTED_FIELD_READ) {
+            throw new ProtoParseException(
+                    "Attempting to read already read field at offset 0x" + Integer.toHexString(
+                            getOffset()) + dumpDebugData());
+        }
+    }
+
+    /**
+     * Dump debugging data about the buffer.
+     */
+    public String dumpDebugData() {
+        StringBuilder sb = new StringBuilder();
+
+        sb.append("\nmFieldNumber : 0x" + Integer.toHexString(mFieldNumber));
+        sb.append("\nmWireType : 0x" + Integer.toHexString(mWireType));
+        sb.append("\nmState : 0x" + Integer.toHexString(mState));
+        sb.append("\nmDiscardedBytes : 0x" + Integer.toHexString(mDiscardedBytes));
+        sb.append("\nmOffset : 0x" + Integer.toHexString(mOffset));
+        sb.append("\nmExpectedObjectTokenStack : ");
+        if (mExpectedObjectTokenStack == null) {
+            sb.append("null");
+        } else {
+            sb.append(mExpectedObjectTokenStack);
+        }
+        sb.append("\nmDepth : 0x" + Integer.toHexString(mDepth));
+        sb.append("\nmBuffer : ");
+        if (mBuffer == null) {
+            sb.append("null");
+        } else {
+            sb.append(mBuffer);
+        }
+        sb.append("\nmBufferSize : 0x" + Integer.toHexString(mBufferSize));
+        sb.append("\nmEnd : 0x" + Integer.toHexString(mEnd));
+
+        return sb.toString();
+    }
+}
diff --git a/core/java/android/util/proto/ProtoOutputStream.java b/core/java/android/util/proto/ProtoOutputStream.java
index a94806a..a1ee61c 100644
--- a/core/java/android/util/proto/ProtoOutputStream.java
+++ b/core/java/android/util/proto/ProtoOutputStream.java
@@ -100,88 +100,12 @@
  * errors if they are not matched.
  */
 @TestApi
-public final class ProtoOutputStream {
+public final class ProtoOutputStream extends ProtoStream {
+    /**
+     * @hide
+     */
     public static final String TAG = "ProtoOutputStream";
 
-    public static final int FIELD_ID_SHIFT = 3;
-    public static final int WIRE_TYPE_MASK = (1<<FIELD_ID_SHIFT)-1;
-    public static final int FIELD_ID_MASK = ~WIRE_TYPE_MASK;
-
-    public static final int WIRE_TYPE_VARINT = 0;
-    public static final int WIRE_TYPE_FIXED64 = 1;
-    public static final int WIRE_TYPE_LENGTH_DELIMITED = 2;
-    public static final int WIRE_TYPE_START_GROUP = 3;
-    public static final int WIRE_TYPE_END_GROUP = 4;
-    public static final int WIRE_TYPE_FIXED32 = 5;
-
-    /**
-     * Position of the field type in a (long) fieldId.
-     */
-    public static final int FIELD_TYPE_SHIFT = 32;
-
-    /**
-     * Mask for the field types stored in a fieldId.  Leaves a whole
-     * byte for future expansion, even though there are currently only 17 types.
-     */
-    public static final long FIELD_TYPE_MASK = 0x0ffL << FIELD_TYPE_SHIFT;
-
-    public static final long FIELD_TYPE_UNKNOWN = 0;
-
-    /**
-     * The types are copied from external/protobuf/src/google/protobuf/descriptor.h directly,
-     * so no extra mapping needs to be maintained in this case.
-     */
-    public static final long FIELD_TYPE_DOUBLE = 1L << FIELD_TYPE_SHIFT;
-    public static final long FIELD_TYPE_FLOAT = 2L << FIELD_TYPE_SHIFT;
-    public static final long FIELD_TYPE_INT64 = 3L << FIELD_TYPE_SHIFT;
-    public static final long FIELD_TYPE_UINT64 = 4L << FIELD_TYPE_SHIFT;
-    public static final long FIELD_TYPE_INT32 = 5L << FIELD_TYPE_SHIFT;
-    public static final long FIELD_TYPE_FIXED64 = 6L << FIELD_TYPE_SHIFT;
-    public static final long FIELD_TYPE_FIXED32 = 7L << FIELD_TYPE_SHIFT;
-    public static final long FIELD_TYPE_BOOL = 8L << FIELD_TYPE_SHIFT;
-    public static final long FIELD_TYPE_STRING = 9L << FIELD_TYPE_SHIFT;
-//  public static final long FIELD_TYPE_GROUP = 10L << FIELD_TYPE_SHIFT; // Deprecated.
-    public static final long FIELD_TYPE_MESSAGE = 11L << FIELD_TYPE_SHIFT;
-    public static final long FIELD_TYPE_BYTES = 12L << FIELD_TYPE_SHIFT;
-    public static final long FIELD_TYPE_UINT32 = 13L << FIELD_TYPE_SHIFT;
-    public static final long FIELD_TYPE_ENUM = 14L << FIELD_TYPE_SHIFT;
-    public static final long FIELD_TYPE_SFIXED32 = 15L << FIELD_TYPE_SHIFT;
-    public static final long FIELD_TYPE_SFIXED64 = 16L << FIELD_TYPE_SHIFT;
-    public static final long FIELD_TYPE_SINT32 = 17L << FIELD_TYPE_SHIFT;
-    public static final long FIELD_TYPE_SINT64 = 18L << FIELD_TYPE_SHIFT;
-
-    private static final String[] FIELD_TYPE_NAMES = new String[] {
-        "Double",
-        "Float",
-        "Int64",
-        "UInt64",
-        "Int32",
-        "Fixed64",
-        "Fixed32",
-        "Bool",
-        "String",
-        "Group",  // This field is deprecated but reserved here for indexing.
-        "Message",
-        "Bytes",
-        "UInt32",
-        "Enum",
-        "SFixed32",
-        "SFixed64",
-        "SInt32",
-        "SInt64",
-    };
-
-    //
-    // FieldId flags for whether the field is single, repeated or packed.
-    //
-    public static final int FIELD_COUNT_SHIFT = 40;
-    public static final long FIELD_COUNT_MASK = 0x0fL << FIELD_COUNT_SHIFT;
-
-    public static final long FIELD_COUNT_UNKNOWN = 0;
-    public static final long FIELD_COUNT_SINGLE = 1L << FIELD_COUNT_SHIFT;
-    public static final long FIELD_COUNT_REPEATED = 2L << FIELD_COUNT_SHIFT;
-    public static final long FIELD_COUNT_PACKED = 5L << FIELD_COUNT_SHIFT;
-
     /**
      * Our buffer.
      */
@@ -1997,94 +1921,6 @@
         }
     }
 
-    //
-    // Child objects
-    //
-
-    /**
-     * Make a token.
-     *  Bits 61-63 - tag size (So we can go backwards later if the object had not data)
-     *                - 3 bits, max value 7, max value needed 5
-     *  Bit  60    - true if the object is repeated (lets us require endObject or endRepeatedObject)
-     *  Bits 59-51 - depth (For error checking)
-     *                - 9 bits, max value 512, when checking, value is masked (if we really
-     *                  are more than 512 levels deep)
-     *  Bits 32-50 - objectId (For error checking)
-     *                - 19 bits, max value 524,288. that's a lot of objects. IDs will wrap
-     *                  because of the overflow, and only the tokens are compared.
-     *  Bits  0-31 - offset of the first size field in the buffer.
-     */
-    // VisibleForTesting
-    public static long makeToken(int tagSize, boolean repeated, int depth, int objectId,
-            int sizePos) {
-        return ((0x07L & (long)tagSize) << 61)
-                | (repeated ? (1L << 60) : 0)
-                | (0x01ffL & (long)depth) << 51
-                | (0x07ffffL & (long)objectId) << 32
-                | (0x0ffffffffL & (long)sizePos);
-    }
-
-    /**
-     * Get the encoded tag size from the token.
-     */
-    public static int getTagSizeFromToken(long token) {
-        return (int)(0x7 & (token >> 61));
-    }
-
-    /**
-     * Get whether this is a call to startObject (false) or startRepeatedObject (true).
-     */
-    public static boolean getRepeatedFromToken(long token) {
-        return (0x1 & (token >> 60)) != 0;
-    }
-
-    /**
-     * Get the nesting depth of startObject calls from the token.
-     */
-    public static int getDepthFromToken(long token) {
-        return (int)(0x01ff & (token >> 51));
-    }
-
-    /**
-     * Get the object ID from the token. The object ID is a serial number for the
-     * startObject calls that have happened on this object.  The values are truncated
-     * to 9 bits, but that is sufficient for error checking.
-     */
-    public static int getObjectIdFromToken(long token) {
-        return (int)(0x07ffff & (token >> 32));
-    }
-
-    /**
-     * Get the location of the childRawSize (the first 32 bit size field) in this object.
-     */
-    public static int getSizePosFromToken(long token) {
-        return (int)token;
-    }
-
-    /**
-     * Convert the object ID to the ordinal value -- the n-th call to startObject.
-     * The object IDs start at -1 and count backwards, so that the value is unlikely
-     * to alias with an actual size field that had been written.
-     */
-    public static int convertObjectIdToOrdinal(int objectId) {
-        return (-1 & 0x07ffff) - objectId;
-    }
-
-    /**
-     * Return a debugging string of a token.
-     */
-    public static String token2String(long token) {
-        if (token == 0L) {
-            return "Token(0)";
-        } else {
-            return "Token(val=0x" + Long.toHexString(token)
-                    + " depth=" + getDepthFromToken(token)
-                    + " object=" + convertObjectIdToOrdinal(getObjectIdFromToken(token))
-                    + " tagSize=" + getTagSizeFromToken(token)
-                    + " sizePos=" + getSizePosFromToken(token)
-                    + ')';
-        }
-    }
 
     /**
      * Start a child object.
@@ -2175,7 +2011,7 @@
         // at which to write the size.
         final int depth = getDepthFromToken(token);
         final boolean expectedRepeated = getRepeatedFromToken(token);
-        final int sizePos = getSizePosFromToken(token);
+        final int sizePos = getOffsetFromToken(token);
         final int childRawSize = mBuffer.getWritePos() - sizePos - 8;
 
         if (repeated != expectedRepeated) {
@@ -2346,56 +2182,6 @@
     }
 
     /**
-     * Get the developer-usable name of a field type.
-     */
-    private static String getFieldTypeString(long fieldType) {
-        int index = ((int)((fieldType & FIELD_TYPE_MASK) >>> FIELD_TYPE_SHIFT)) - 1;
-        if (index >= 0 && index < FIELD_TYPE_NAMES.length) {
-            return FIELD_TYPE_NAMES[index];
-        } else {
-            return null;
-        }
-    }
-
-    /**
-     * Get the developer-usable name of a field count.
-     */
-    private static String getFieldCountString(long fieldCount) {
-        if (fieldCount == FIELD_COUNT_SINGLE) {
-            return "";
-        } else if (fieldCount == FIELD_COUNT_REPEATED) {
-            return "Repeated";
-        } else if (fieldCount == FIELD_COUNT_PACKED) {
-            return "Packed";
-        } else {
-            return null;
-        }
-    }
-
-    /**
-     * Get a debug string for a fieldId.
-     */
-    private String getFieldIdString(long fieldId) {
-        final long fieldCount = fieldId & FIELD_COUNT_MASK;
-        String countString = getFieldCountString(fieldCount);
-        if (countString == null) {
-            countString = "fieldCount=" + fieldCount;
-        }
-        if (countString.length() > 0) {
-            countString += " ";
-        }
-
-        final long fieldType = fieldId & FIELD_TYPE_MASK;
-        String typeString = getFieldTypeString(fieldType);
-        if (typeString == null) {
-            typeString = "fieldType=" + fieldType;
-        }
-
-        return countString + typeString + " tag=" + ((int) fieldId)
-                + " fieldId=0x" + Long.toHexString(fieldId);
-    }
-
-    /**
      * Return how many bytes an encoded field tag will require.
      */
     private static int getTagSize(int id) {
diff --git a/core/java/android/util/proto/ProtoStream.java b/core/java/android/util/proto/ProtoStream.java
new file mode 100644
index 0000000..9e2e95a
--- /dev/null
+++ b/core/java/android/util/proto/ProtoStream.java
@@ -0,0 +1,280 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.util.proto;
+
+import android.annotation.TestApi;
+
+/**
+ * Abstract base class for both protobuf streams.
+ *
+ * Contains a set of useful constants and methods used by both
+ * ProtoOutputStream and ProtoInputStream
+ *
+ * @hide
+ */
+@TestApi
+public abstract class ProtoStream {
+
+    public static final int FIELD_ID_SHIFT = 3;
+    public static final int WIRE_TYPE_MASK = (1 << FIELD_ID_SHIFT) - 1;
+    public static final int FIELD_ID_MASK = ~WIRE_TYPE_MASK;
+
+    public static final int WIRE_TYPE_VARINT = 0;
+    public static final int WIRE_TYPE_FIXED64 = 1;
+    public static final int WIRE_TYPE_LENGTH_DELIMITED = 2;
+    public static final int WIRE_TYPE_START_GROUP = 3;
+    public static final int WIRE_TYPE_END_GROUP = 4;
+    public static final int WIRE_TYPE_FIXED32 = 5;
+
+    /**
+     * Position of the field type in a (long) fieldId.
+     */
+    public static final int FIELD_TYPE_SHIFT = 32;
+
+    /**
+     * Mask for the field types stored in a fieldId.  Leaves a whole
+     * byte for future expansion, even though there are currently only 17 types.
+     */
+    public static final long FIELD_TYPE_MASK = 0x0ffL << FIELD_TYPE_SHIFT;
+
+    public static final long FIELD_TYPE_UNKNOWN = 0;
+
+    /**
+     * The types are copied from external/protobuf/src/google/protobuf/descriptor.h directly,
+     * so no extra mapping needs to be maintained in this case.
+     */
+    public static final long FIELD_TYPE_DOUBLE = 1L << FIELD_TYPE_SHIFT;
+    public static final long FIELD_TYPE_FLOAT = 2L << FIELD_TYPE_SHIFT;
+    public static final long FIELD_TYPE_INT64 = 3L << FIELD_TYPE_SHIFT;
+    public static final long FIELD_TYPE_UINT64 = 4L << FIELD_TYPE_SHIFT;
+    public static final long FIELD_TYPE_INT32 = 5L << FIELD_TYPE_SHIFT;
+    public static final long FIELD_TYPE_FIXED64 = 6L << FIELD_TYPE_SHIFT;
+    public static final long FIELD_TYPE_FIXED32 = 7L << FIELD_TYPE_SHIFT;
+    public static final long FIELD_TYPE_BOOL = 8L << FIELD_TYPE_SHIFT;
+    public static final long FIELD_TYPE_STRING = 9L << FIELD_TYPE_SHIFT;
+    //  public static final long FIELD_TYPE_GROUP = 10L << FIELD_TYPE_SHIFT; // Deprecated.
+    public static final long FIELD_TYPE_MESSAGE = 11L << FIELD_TYPE_SHIFT;
+    public static final long FIELD_TYPE_BYTES = 12L << FIELD_TYPE_SHIFT;
+    public static final long FIELD_TYPE_UINT32 = 13L << FIELD_TYPE_SHIFT;
+    public static final long FIELD_TYPE_ENUM = 14L << FIELD_TYPE_SHIFT;
+    public static final long FIELD_TYPE_SFIXED32 = 15L << FIELD_TYPE_SHIFT;
+    public static final long FIELD_TYPE_SFIXED64 = 16L << FIELD_TYPE_SHIFT;
+    public static final long FIELD_TYPE_SINT32 = 17L << FIELD_TYPE_SHIFT;
+    public static final long FIELD_TYPE_SINT64 = 18L << FIELD_TYPE_SHIFT;
+
+    protected static final String[] FIELD_TYPE_NAMES = new String[]{
+            "Double",
+            "Float",
+            "Int64",
+            "UInt64",
+            "Int32",
+            "Fixed64",
+            "Fixed32",
+            "Bool",
+            "String",
+            "Group",  // This field is deprecated but reserved here for indexing.
+            "Message",
+            "Bytes",
+            "UInt32",
+            "Enum",
+            "SFixed32",
+            "SFixed64",
+            "SInt32",
+            "SInt64",
+    };
+
+    //
+    // FieldId flags for whether the field is single, repeated or packed.
+    //
+    public static final int FIELD_COUNT_SHIFT = 40;
+    public static final long FIELD_COUNT_MASK = 0x0fL << FIELD_COUNT_SHIFT;
+
+    public static final long FIELD_COUNT_UNKNOWN = 0;
+    public static final long FIELD_COUNT_SINGLE = 1L << FIELD_COUNT_SHIFT;
+    public static final long FIELD_COUNT_REPEATED = 2L << FIELD_COUNT_SHIFT;
+    public static final long FIELD_COUNT_PACKED = 5L << FIELD_COUNT_SHIFT;
+
+
+    /**
+     * Get the developer-usable name of a field type.
+     */
+    public static String getFieldTypeString(long fieldType) {
+        int index = ((int) ((fieldType & FIELD_TYPE_MASK) >>> FIELD_TYPE_SHIFT)) - 1;
+        if (index >= 0 && index < FIELD_TYPE_NAMES.length) {
+            return FIELD_TYPE_NAMES[index];
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Get the developer-usable name of a field count.
+     */
+    public static String getFieldCountString(long fieldCount) {
+        if (fieldCount == FIELD_COUNT_SINGLE) {
+            return "";
+        } else if (fieldCount == FIELD_COUNT_REPEATED) {
+            return "Repeated";
+        } else if (fieldCount == FIELD_COUNT_PACKED) {
+            return "Packed";
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Get the developer-usable name of a wire type.
+     */
+    public static String getWireTypeString(int wireType) {
+        switch (wireType) {
+            case WIRE_TYPE_VARINT:
+                return "Varint";
+            case WIRE_TYPE_FIXED64:
+                return "Fixed64";
+            case WIRE_TYPE_LENGTH_DELIMITED:
+                return "Length Delimited";
+            case WIRE_TYPE_START_GROUP:
+                return "Start Group";
+            case WIRE_TYPE_END_GROUP:
+                return "End Group";
+            case WIRE_TYPE_FIXED32:
+                return "Fixed32";
+            default:
+                return null;
+        }
+    }
+
+    /**
+     * Get a debug string for a fieldId.
+     */
+    public static String getFieldIdString(long fieldId) {
+        final long fieldCount = fieldId & FIELD_COUNT_MASK;
+        String countString = getFieldCountString(fieldCount);
+        if (countString == null) {
+            countString = "fieldCount=" + fieldCount;
+        }
+        if (countString.length() > 0) {
+            countString += " ";
+        }
+
+        final long fieldType = fieldId & FIELD_TYPE_MASK;
+        String typeString = getFieldTypeString(fieldType);
+        if (typeString == null) {
+            typeString = "fieldType=" + fieldType;
+        }
+
+        return countString + typeString + " tag=" + ((int) fieldId)
+                + " fieldId=0x" + Long.toHexString(fieldId);
+    }
+
+    /**
+     * Combine a fieldId (the field keys in the proto file) and the field flags.
+     * Mostly useful for testing because the generated code contains the fieldId
+     * constants.
+     */
+    public static long makeFieldId(int id, long fieldFlags) {
+        return fieldFlags | (((long) id) & 0x0ffffffffL);
+    }
+
+    //
+    // Child objects
+    //
+
+    /**
+     * Make a token.
+     * Bits 61-63 - tag size (So we can go backwards later if the object had not data)
+     *            - 3 bits, max value 7, max value needed 5
+     * Bit  60    - true if the object is repeated (lets us require endObject or endRepeatedObject)
+     * Bits 59-51 - depth (For error checking)
+     *            - 9 bits, max value 512, when checking, value is masked (if we really
+     *              are more than 512 levels deep)
+     * Bits 32-50 - objectId (For error checking)
+     *            - 19 bits, max value 524,288. that's a lot of objects. IDs will wrap
+     *              because of the overflow, and only the tokens are compared.
+     * Bits  0-31 - offset of interest for the object.
+     */
+    public static long makeToken(int tagSize, boolean repeated, int depth, int objectId,
+            int offset) {
+        return ((0x07L & (long) tagSize) << 61)
+                | (repeated ? (1L << 60) : 0)
+                | (0x01ffL & (long) depth) << 51
+                | (0x07ffffL & (long) objectId) << 32
+                | (0x0ffffffffL & (long) offset);
+    }
+
+    /**
+     * Get the encoded tag size from the token.
+     */
+    public static int getTagSizeFromToken(long token) {
+        return (int) (0x7 & (token >> 61));
+    }
+
+    /**
+     * Get whether this is a call to startObject (false) or startRepeatedObject (true).
+     */
+    public static boolean getRepeatedFromToken(long token) {
+        return (0x1 & (token >> 60)) != 0;
+    }
+
+    /**
+     * Get the nesting depth of startObject calls from the token.
+     */
+    public static int getDepthFromToken(long token) {
+        return (int) (0x01ff & (token >> 51));
+    }
+
+    /**
+     * Get the object ID from the token. The object ID is a serial number for the
+     * startObject calls that have happened on this object.  The values are truncated
+     * to 9 bits, but that is sufficient for error checking.
+     */
+    public static int getObjectIdFromToken(long token) {
+        return (int) (0x07ffff & (token >> 32));
+    }
+
+    /**
+     * Get the location of the offset recorded in the token.
+     */
+    public static int getOffsetFromToken(long token) {
+        return (int) token;
+    }
+
+    /**
+     * Convert the object ID to the ordinal value -- the n-th call to startObject.
+     * The object IDs start at -1 and count backwards, so that the value is unlikely
+     * to alias with an actual size field that had been written.
+     */
+    public static int convertObjectIdToOrdinal(int objectId) {
+        return (-1 & 0x07ffff) - objectId;
+    }
+
+    /**
+     * Return a debugging string of a token.
+     */
+    public static String token2String(long token) {
+        if (token == 0L) {
+            return "Token(0)";
+        } else {
+            return "Token(val=0x" + Long.toHexString(token)
+                    + " depth=" + getDepthFromToken(token)
+                    + " object=" + convertObjectIdToOrdinal(getObjectIdFromToken(token))
+                    + " tagSize=" + getTagSizeFromToken(token)
+                    + " offset=" + getOffsetFromToken(token)
+                    + ')';
+        }
+    }
+}
diff --git a/core/java/android/util/proto/ProtoUtils.java b/core/java/android/util/proto/ProtoUtils.java
index c7bbb9f..03bf590 100644
--- a/core/java/android/util/proto/ProtoUtils.java
+++ b/core/java/android/util/proto/ProtoUtils.java
@@ -19,6 +19,8 @@
 import android.util.AggStats;
 import android.util.Duration;
 
+import java.io.IOException;
+
 /**
  * This class contains a list of helper functions to write common proto in
  * //frameworks/base/core/proto/android/base directory
@@ -70,4 +72,54 @@
             }
         }
     }
+
+    /**
+     * Provide debug data about the current field as a string
+     */
+    public static String currentFieldToString(ProtoInputStream proto) throws IOException {
+        StringBuilder sb = new StringBuilder();
+
+        final int fieldNumber = proto.getFieldNumber();
+        final int wireType = proto.getWireType();
+        long fieldConstant;
+
+        sb.append("Offset : 0x" + Integer.toHexString(proto.getOffset()));
+        sb.append("\nField Number : 0x" + Integer.toHexString(proto.getFieldNumber()));
+        sb.append("\nWire Type : ");
+        switch (wireType) {
+            case ProtoStream.WIRE_TYPE_VARINT:
+                sb.append("varint");
+                fieldConstant = ProtoStream.makeFieldId(fieldNumber,
+                        ProtoStream.FIELD_COUNT_SINGLE | ProtoStream.FIELD_TYPE_INT64);
+                sb.append("\nField Value : 0x" + Long.toHexString(proto.readLong(fieldConstant)));
+                break;
+            case ProtoStream.WIRE_TYPE_FIXED64:
+                sb.append("fixed64");
+                fieldConstant = ProtoStream.makeFieldId(fieldNumber,
+                        ProtoStream.FIELD_COUNT_SINGLE | ProtoStream.FIELD_TYPE_FIXED64);
+                sb.append("\nField Value : 0x" + Long.toHexString(proto.readLong(fieldConstant)));
+                break;
+            case ProtoStream.WIRE_TYPE_LENGTH_DELIMITED:
+                sb.append("length delimited");
+                fieldConstant = ProtoStream.makeFieldId(fieldNumber,
+                        ProtoStream.FIELD_COUNT_SINGLE | ProtoStream.FIELD_TYPE_BYTES);
+                sb.append("\nField Bytes : " + proto.readBytes(fieldConstant));
+                break;
+            case ProtoStream.WIRE_TYPE_START_GROUP:
+                sb.append("start group");
+                break;
+            case ProtoStream.WIRE_TYPE_END_GROUP:
+                sb.append("end group");
+                break;
+            case ProtoStream.WIRE_TYPE_FIXED32:
+                sb.append("fixed32");
+                fieldConstant = ProtoStream.makeFieldId(fieldNumber,
+                        ProtoStream.FIELD_COUNT_SINGLE | ProtoStream.FIELD_TYPE_FIXED32);
+                sb.append("\nField Value : 0x" + Integer.toHexString(proto.readInt(fieldConstant)));
+                break;
+            default:
+                sb.append("unknown(" + proto.getWireType() + ")");
+        }
+        return sb.toString();
+    }
 }
diff --git a/core/java/android/util/proto/WireTypeMismatchException.java b/core/java/android/util/proto/WireTypeMismatchException.java
new file mode 100644
index 0000000..d90b4f8
--- /dev/null
+++ b/core/java/android/util/proto/WireTypeMismatchException.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.util.proto;
+
+import android.annotation.TestApi;
+
+/**
+ * Thrown when there is an error parsing protobuf data.
+ *
+ * @hide
+ */
+@TestApi
+public class WireTypeMismatchException extends ProtoParseException {
+
+    /**
+     * Construct a WireTypeMismatchException.
+     *
+     * @param msg The message.
+     */
+    public WireTypeMismatchException(String msg) {
+        super(msg);
+    }
+}
+
diff --git a/core/java/android/view/AccessibilityInteractionController.java b/core/java/android/view/AccessibilityInteractionController.java
index 45fa561..eb41e07 100644
--- a/core/java/android/view/AccessibilityInteractionController.java
+++ b/core/java/android/view/AccessibilityInteractionController.java
@@ -32,6 +32,7 @@
 import android.os.Parcelable;
 import android.os.Process;
 import android.os.RemoteException;
+import android.os.SystemClock;
 import android.text.style.AccessibilityClickableSpan;
 import android.text.style.ClickableSpan;
 import android.util.LongSparseArray;
@@ -702,6 +703,14 @@
                     // Handle this hidden action separately
                     succeeded = handleClickableSpanActionUiThread(
                             target, virtualDescendantId, arguments);
+                } else if (action == R.id.accessibilityActionOutsideTouch) {
+                    // trigger ACTION_OUTSIDE to notify windows
+                    final long now = SystemClock.uptimeMillis();
+                    MotionEvent event = MotionEvent.obtain(now, now, MotionEvent.ACTION_OUTSIDE,
+                            0, 0, 0);
+                    event.setSource(InputDevice.SOURCE_TOUCHSCREEN);
+                    mViewRootImpl.dispatchInputEvent(event);
+                    succeeded = true;
                 } else {
                     AccessibilityNodeProvider provider = target.getAccessibilityNodeProvider();
                     if (provider != null) {
diff --git a/core/java/android/view/Choreographer.java b/core/java/android/view/Choreographer.java
index ce16ffc..a872776 100644
--- a/core/java/android/view/Choreographer.java
+++ b/core/java/android/view/Choreographer.java
@@ -22,6 +22,7 @@
 import android.annotation.TestApi;
 import android.annotation.UnsupportedAppUsage;
 import android.hardware.display.DisplayManagerGlobal;
+import android.os.Build;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
@@ -153,7 +154,7 @@
         public String toString() { return "FRAME_CALLBACK_TOKEN"; }
     };
 
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private final Object mLock = new Object();
 
     private final Looper mLooper;
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 0398b8f..bfe1e95 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -73,7 +73,6 @@
 
     IWindowSession openSession(in IWindowSessionCallback callback, in IInputMethodClient client,
             in IInputContext inputContext);
-    boolean inputMethodClientHasFocus(IInputMethodClient client);
 
     void getInitialDisplaySize(int displayId, out Point size);
     void getBaseDisplaySize(int displayId, out Point size);
@@ -392,15 +391,16 @@
     void registerShortcutKey(in long shortcutCode, IShortcutService keySubscriber);
 
     /**
-     * Create an input consumer by name.
+     * Create an input consumer by name and display id.
      */
-    void createInputConsumer(IBinder token, String name, out InputChannel inputChannel);
+    void createInputConsumer(IBinder token, String name, int displayId,
+        out InputChannel inputChannel);
 
     /**
-     * Destroy an input consumer by name.  This method will also dispose the input channels
-     * associated with that InputConsumer.
+     * Destroy an input consumer by name and display id.
+     * This method will also dispose the input channels associated with that InputConsumer.
      */
-    boolean destroyInputConsumer(String name);
+    boolean destroyInputConsumer(String name, int displayId);
 
     /**
      * Return the touch region for the current IME window, or an empty region if there is none.
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index 8641d7f..c38fcf3 100644
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -21,6 +21,7 @@
 import android.annotation.NonNull;
 import android.annotation.TestApi;
 import android.annotation.UnsupportedAppUsage;
+import android.os.Build;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.text.method.MetaKeyKeyListener;
@@ -1256,7 +1257,7 @@
 
     @UnsupportedAppUsage
     private int mDeviceId;
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private int mSource;
     private int mDisplayId;
     @UnsupportedAppUsage
@@ -1658,7 +1659,7 @@
      * @hide
      */
     @Override
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     public final void recycle() {
         super.recycle();
         mCharacters = null;
diff --git a/core/java/android/view/LayoutInflater.java b/core/java/android/view/LayoutInflater.java
index c520a99..9aab419 100644
--- a/core/java/android/view/LayoutInflater.java
+++ b/core/java/android/view/LayoutInflater.java
@@ -17,6 +17,7 @@
 package android.view;
 
 import android.annotation.LayoutRes;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemService;
 import android.annotation.UnsupportedAppUsage;
@@ -154,7 +155,9 @@
          * @return View Newly created view. Return null for the default
          *         behavior.
          */
-        public View onCreateView(String name, Context context, AttributeSet attrs);
+        @Nullable
+        View onCreateView(@NonNull String name, @NonNull Context context,
+                @NonNull AttributeSet attrs);
     }
 
     public interface Factory2 extends Factory {
@@ -172,7 +175,9 @@
          * @return View Newly created view. Return null for the default
          *         behavior.
          */
-        public View onCreateView(View parent, String name, Context context, AttributeSet attrs);
+        @Nullable
+        View onCreateView(@Nullable View parent, @NonNull String name,
+                @NonNull Context context, @NonNull AttributeSet attrs);
     }
 
     private static class FactoryMerger implements Factory2 {
@@ -186,13 +191,17 @@
             mF22 = f22;
         }
 
-        public View onCreateView(String name, Context context, AttributeSet attrs) {
+        @Nullable
+        public View onCreateView(@NonNull String name, @NonNull Context context,
+                @NonNull AttributeSet attrs) {
             View v = mF1.onCreateView(name, context, attrs);
             if (v != null) return v;
             return mF2.onCreateView(name, context, attrs);
         }
 
-        public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {
+        @Nullable
+        public View onCreateView(@Nullable View parent, @NonNull String name,
+                @NonNull Context context, @NonNull AttributeSet attrs) {
             View v = mF12 != null ? mF12.onCreateView(parent, name, context, attrs)
                     : mF1.onCreateView(name, context, attrs);
             if (v != null) return v;
diff --git a/core/java/android/view/PointerIcon.java b/core/java/android/view/PointerIcon.java
index dc097a1..cf11fd0 100644
--- a/core/java/android/view/PointerIcon.java
+++ b/core/java/android/view/PointerIcon.java
@@ -31,6 +31,7 @@
 import android.graphics.drawable.AnimationDrawable;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
+import android.os.Build;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.Log;
@@ -146,7 +147,7 @@
     private static final SparseArray<PointerIcon> gSystemIcons = new SparseArray<PointerIcon>();
     private static boolean sUseLargeIcons = false;
 
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private final int mType;
     private int mSystemIconResourceId;
     @UnsupportedAppUsage
@@ -319,7 +320,7 @@
      * @throws IllegalArgumentException if context is null.
      * @hide
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     public PointerIcon load(@NonNull Context context) {
         if (context == null) {
             throw new IllegalArgumentException("context must not be null");
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 274dd2f..514a11e 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -545,7 +545,8 @@
                 mScreenRect.offset(surfaceInsets.left, surfaceInsets.top);
 
                 if (creating) {
-                    mSurfaceSession = new SurfaceSession(viewRoot.mSurface);
+                    viewRoot.createBoundsSurface(mSubLayer);
+                    mSurfaceSession = new SurfaceSession(viewRoot.mBoundsSurface);
                     mDeferredDestroySurfaceControl = mSurfaceControl;
 
                     updateOpaqueFlag();
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 9bc53ed..c29fbbb 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -4582,7 +4582,7 @@
     /**
      * Object that handles automatic animation of view properties.
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private ViewPropertyAnimator mAnimator = null;
 
     /**
@@ -6876,7 +6876,7 @@
      * @param requestCode The request code to use.
      * @hide
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     public void startActivityForResult(Intent intent, int requestCode) {
         mStartActivityRequestWho = "@android:view:" + System.identityHashCode(this);
         getContext().startActivityForResult(mStartActivityRequestWho, intent, requestCode, null);
@@ -18406,7 +18406,7 @@
      * communicate with the window manager.
      * @return the session object to communicate with the window manager
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     /*package*/ IWindowSession getWindowSession() {
         return mAttachInfo != null ? mAttachInfo.mSession : null;
     }
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 0119d2e..1b3e62d 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -8116,7 +8116,7 @@
         /**
          * Sets the margins, in pixels. A call to {@link android.view.View#requestLayout()} needs
          * to be done so that the new margins are taken into account. Left and right margins may be
-         * overriden by {@link android.view.View#requestLayout()} depending on layout direction.
+         * overridden by {@link android.view.View#requestLayout()} depending on layout direction.
          * Margin values should be positive.
          *
          * @param left the left margin size
@@ -8146,8 +8146,8 @@
         /**
          * Sets the relative margins, in pixels. A call to {@link android.view.View#requestLayout()}
          * needs to be done so that the new relative margins are taken into account. Left and right
-         * margins may be overriden by {@link android.view.View#requestLayout()} depending on layout
-         * direction. Margin values should be positive.
+         * margins may be overridden by {@link android.view.View#requestLayout()} depending on
+         * layout direction. Margin values should be positive.
          *
          * @param start the start margin size
          * @param top the top margin size
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 1351f6f1..16d202b 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -81,6 +81,7 @@
 import android.util.TimeUtils;
 import android.util.TypedValue;
 import android.view.Surface.OutOfResourcesException;
+import android.view.SurfaceControl.Transaction;
 import android.view.ThreadedRenderer.FrameDrawingCallback;
 import android.view.View.AttachInfo;
 import android.view.View.FocusDirection;
@@ -342,6 +343,7 @@
 
     final Rect mTempRect; // used in the transaction to not thrash the heap.
     final Rect mVisRect; // used to retrieve visible rect of focused view.
+    private final Rect mTempBoundsRect = new Rect(); // used to set the size of the bounds surface.
 
     // This is used to reduce the race between window focus changes being dispatched from
     // the window manager and input events coming through the input system.
@@ -404,6 +406,18 @@
     @UnsupportedAppUsage
     public final Surface mSurface = new Surface();
 
+    /**
+     * Child surface of {@code mSurface} with the same bounds as its parent, and crop bounds
+     * are set to the parent's bounds adjusted for surface insets. This surface is created when
+     * {@link ViewRootImpl#createBoundsSurface(int)} is called.
+     * By parenting to this bounds surface, child surfaces can ensure they do not draw into the
+     * surface inset regions set by the parent window.
+     */
+    public final Surface mBoundsSurface = new Surface();
+    private SurfaceSession mSurfaceSession;
+    private SurfaceControl mBoundsSurfaceControl;
+    private final Transaction mTransaction = new Transaction();
+
     @UnsupportedAppUsage
     boolean mAdded;
     boolean mAddedTouchMode;
@@ -1390,12 +1404,79 @@
             }
 
             if (mStopped) {
-                mSurface.release();
+                destroySurface();
             }
         }
     }
 
     /**
+     * Creates a surface as a child of {@code mSurface} with the same bounds as its parent and
+     * crop bounds set to the parent's bounds adjusted for surface insets.
+     *
+     * @param zOrderLayer Z order relative to the parent surface.
+     */
+    public void createBoundsSurface(int zOrderLayer) {
+        if (mSurfaceSession == null) {
+            mSurfaceSession = new SurfaceSession(mSurface);
+        }
+        if (mBoundsSurfaceControl != null && mBoundsSurface.isValid()) {
+            return; // surface control for bounds surface already exists.
+        }
+
+        mBoundsSurfaceControl = new SurfaceControl.Builder(mSurfaceSession)
+                .setName("Bounds for - " + getTitle().toString())
+                .setSize(mWidth, mHeight)
+                .build();
+
+        setBoundsSurfaceSizeAndCrop();
+        mTransaction.setLayer(mBoundsSurfaceControl, zOrderLayer)
+                    .show(mBoundsSurfaceControl)
+                    .apply();
+        mBoundsSurface.copyFrom(mBoundsSurfaceControl);
+    }
+
+    private void setBoundsSurfaceSizeAndCrop() {
+        // mWinFrame is already adjusted for surface insets. So offset it and use it as
+        // the cropping bounds.
+        mTempBoundsRect.set(mWinFrame);
+        mTempBoundsRect.offsetTo(mWindowAttributes.surfaceInsets.left,
+                mWindowAttributes.surfaceInsets.top);
+        mTransaction.setWindowCrop(mBoundsSurfaceControl, mTempBoundsRect);
+
+        // Expand the bounds by the surface insets to get the size of surface.
+        mTempBoundsRect.inset(-mWindowAttributes.surfaceInsets.left,
+                -mWindowAttributes.surfaceInsets.top,
+                -mWindowAttributes.surfaceInsets.right,
+                -mWindowAttributes.surfaceInsets.bottom);
+        mTransaction.setSize(mBoundsSurfaceControl, mTempBoundsRect.width(),
+                mTempBoundsRect.height());
+    }
+
+    /**
+     * Called after window layout to update the bounds surface. If the surface insets have
+     * changed or the surface has resized, update the bounds surface.
+     */
+    private void updateBoundsSurface() {
+        if (mBoundsSurfaceControl != null && mSurface.isValid()) {
+            setBoundsSurfaceSizeAndCrop();
+            mTransaction.deferTransactionUntilSurface(mBoundsSurfaceControl,
+                    mSurface, mSurface.getNextFrameNumber())
+                    .apply();
+        }
+    }
+
+    private void destroySurface() {
+        mSurface.release();
+        mSurfaceSession = null;
+
+        if (mBoundsSurfaceControl != null) {
+            mBoundsSurfaceControl.destroy();
+            mBoundsSurface.release();
+            mBoundsSurfaceControl = null;
+        }
+    }
+
+    /**
      * Block the input events during an Activity Transition. The KEYCODE_BACK event is allowed
      * through to allow quick reversal of the Activity Transition.
      *
@@ -2350,6 +2431,10 @@
             maybeHandleWindowMove(frame);
         }
 
+        if (surfaceChanged) {
+            updateBoundsSurface();
+        }
+
         final boolean didLayout = layoutRequested && (!mStopped || mReportNextDraw);
         boolean triggerGlobalLayoutListener = didLayout
                 || mAttachInfo.mRecomputeGlobalAttributes;
@@ -3860,7 +3945,7 @@
         mView = null;
         mAttachInfo.mRootView = null;
 
-        mSurface.release();
+        destroySurface();
 
         if (mInputQueueCallback != null && mInputQueue != null) {
             mInputQueueCallback.onInputQueueDestroyed(mInputQueue);
@@ -6809,7 +6894,7 @@
                         }
                     }
 
-                    mSurface.release();
+                    destroySurface();
                 }
             }
 
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index f436962..a7ec6df 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -422,7 +422,7 @@
          * @return boolean You must return true for the panel to be displayed;
          *         if you return false it will not be shown.
          */
-        public boolean onCreatePanelMenu(int featureId, Menu menu);
+        boolean onCreatePanelMenu(int featureId, @NonNull Menu menu);
 
         /**
          * Prepare a panel to be displayed.  This is called right before the
@@ -438,7 +438,7 @@
          *
          * @see #onCreatePanelView
          */
-        public boolean onPreparePanel(int featureId, View view, Menu menu);
+        boolean onPreparePanel(int featureId, @Nullable View view, @NonNull Menu menu);
 
         /**
          * Called when a panel's menu is opened by the user. This may also be
@@ -450,7 +450,7 @@
          * @return Return true to allow the menu to open, or false to prevent
          *         the menu from opening.
          */
-        public boolean onMenuOpened(int featureId, Menu menu);
+        boolean onMenuOpened(int featureId, @NonNull Menu menu);
 
         /**
          * Called when a panel's menu item has been selected by the user.
@@ -462,7 +462,7 @@
          *         false to perform the normal menu handling (calling its
          *         Runnable or sending a Message to its target Handler).
          */
-        public boolean onMenuItemSelected(int featureId, MenuItem item);
+        boolean onMenuItemSelected(int featureId, @NonNull MenuItem item);
 
         /**
          * This is called whenever the current window attributes change.
@@ -512,7 +512,7 @@
          * @param menu If onCreatePanelView() returned null, this is the Menu
          *            being displayed in the panel.
          */
-        public void onPanelClosed(int featureId, Menu menu);
+        void onPanelClosed(int featureId, @NonNull Menu menu);
 
         /**
          * Called when the user signals the desire to start a search.
diff --git a/core/java/android/view/WindowInfo.java b/core/java/android/view/WindowInfo.java
index 7bae28a..82e9a5c 100644
--- a/core/java/android/view/WindowInfo.java
+++ b/core/java/android/view/WindowInfo.java
@@ -49,6 +49,7 @@
     public CharSequence title;
     public long accessibilityIdOfAnchor = AccessibilityNodeInfo.UNDEFINED_NODE_ID;
     public boolean inPictureInPicture;
+    public boolean hasFlagWatchOutsideTouch;
 
     private WindowInfo() {
         /* do nothing - hide constructor */
@@ -74,6 +75,7 @@
         window.title = other.title;
         window.accessibilityIdOfAnchor = other.accessibilityIdOfAnchor;
         window.inPictureInPicture = other.inPictureInPicture;
+        window.hasFlagWatchOutsideTouch = other.hasFlagWatchOutsideTouch;
 
         if (other.childTokens != null && !other.childTokens.isEmpty()) {
             if (window.childTokens == null) {
@@ -108,6 +110,7 @@
         parcel.writeCharSequence(title);
         parcel.writeLong(accessibilityIdOfAnchor);
         parcel.writeInt(inPictureInPicture ? 1 : 0);
+        parcel.writeInt(hasFlagWatchOutsideTouch ? 1 : 0);
 
         if (childTokens != null && !childTokens.isEmpty()) {
             parcel.writeInt(1);
@@ -130,6 +133,8 @@
         builder.append(", focused=").append(focused);
         builder.append(", children=").append(childTokens);
         builder.append(", accessibility anchor=").append(accessibilityIdOfAnchor);
+        builder.append(", pictureInPicture=").append(inPictureInPicture);
+        builder.append(", watchOutsideTouch=").append(hasFlagWatchOutsideTouch);
         builder.append(']');
         return builder.toString();
     }
@@ -145,6 +150,7 @@
         title = parcel.readCharSequence();
         accessibilityIdOfAnchor = parcel.readLong();
         inPictureInPicture = (parcel.readInt() == 1);
+        hasFlagWatchOutsideTouch = (parcel.readInt() == 1);
 
         final boolean hasChildren = (parcel.readInt() == 1);
         if (hasChildren) {
@@ -167,6 +173,7 @@
             childTokens.clear();
         }
         inPictureInPicture = false;
+        hasFlagWatchOutsideTouch = false;
     }
 
     public static final Parcelable.Creator<WindowInfo> CREATOR =
diff --git a/core/java/android/view/WindowManagerGlobal.java b/core/java/android/view/WindowManagerGlobal.java
index d810067..4ca9a14 100644
--- a/core/java/android/view/WindowManagerGlobal.java
+++ b/core/java/android/view/WindowManagerGlobal.java
@@ -23,6 +23,7 @@
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.res.Configuration;
+import android.os.Build;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -213,7 +214,7 @@
         }
     }
 
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     public static IWindowSession peekWindowSession() {
         synchronized (WindowManagerGlobal.class) {
             return sWindowSession;
diff --git a/core/java/android/view/accessibility/AccessibilityEvent.java b/core/java/android/view/accessibility/AccessibilityEvent.java
index 3eca854..dccf9d4 100644
--- a/core/java/android/view/accessibility/AccessibilityEvent.java
+++ b/core/java/android/view/accessibility/AccessibilityEvent.java
@@ -18,6 +18,7 @@
 
 import android.annotation.IntDef;
 import android.annotation.UnsupportedAppUsage;
+import android.os.Build;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.text.TextUtils;
@@ -761,7 +762,7 @@
     private CharSequence mPackageName;
     private long mEventTime;
     int mMovementGranularity;
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     int mAction;
     int mContentChangeTypes;
     int mWindowChangeTypes;
diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java
index c59c491..e88682e 100644
--- a/core/java/android/view/accessibility/AccessibilityManager.java
+++ b/core/java/android/view/accessibility/AccessibilityManager.java
@@ -139,6 +139,8 @@
 
     int mRelevantEventTypes = AccessibilityEvent.TYPES_ALL_MASK;
 
+    int mMinimumUiTimeout;
+
     boolean mIsTouchExplorationEnabled;
 
     @UnsupportedAppUsage
@@ -320,6 +322,11 @@
         public void setRelevantEventTypes(int eventTypes) {
             mRelevantEventTypes = eventTypes;
         }
+
+        @Override
+        public void setMinimumUiTimeout(int uiTimeout) {
+            mMinimumUiTimeout = uiTimeout;
+        }
     };
 
     /**
@@ -827,6 +834,19 @@
     }
 
     /**
+     * Get the minimum timeout for changes to the UI needed by this user. Controls should remain
+     * on the screen for at least this long to give users time to react. Some users may need
+     * extra time to review the controls, or to reach them, or to activate assistive technology
+     * to activate the controls automatically.
+     *
+     * @return The minimum ui timeout for the current user in milliseconds.
+     * {@link Integer#MAX_VALUE} if timeout is infinite.
+     */
+    public int getMinimumUiTimeoutMillis() {
+        return mMinimumUiTimeout;
+    }
+
+    /**
      * Get the preparers that are registered for an accessibility ID
      *
      * @param id The ID of interest
@@ -1139,6 +1159,7 @@
             final long userStateAndRelevantEvents = service.addClient(mClient, mUserId);
             setStateLocked(IntPair.first(userStateAndRelevantEvents));
             mRelevantEventTypes = IntPair.second(userStateAndRelevantEvents);
+            mMinimumUiTimeout = service.getMinimumUiTimeout();
             mService = service;
         } catch (RemoteException re) {
             Log.e(LOG_TAG, "AccessibilityManagerService is dead", re);
diff --git a/core/java/android/view/accessibility/IAccessibilityManager.aidl b/core/java/android/view/accessibility/IAccessibilityManager.aidl
index c93e2c1..3e2ef18 100644
--- a/core/java/android/view/accessibility/IAccessibilityManager.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityManager.aidl
@@ -72,4 +72,6 @@
 
     // System process only
     boolean sendFingerprintGesture(int gestureKeyCode);
+
+    int getMinimumUiTimeout();
 }
diff --git a/core/java/android/view/accessibility/IAccessibilityManagerClient.aidl b/core/java/android/view/accessibility/IAccessibilityManagerClient.aidl
index 9cc0315..d2ddca3 100644
--- a/core/java/android/view/accessibility/IAccessibilityManagerClient.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityManagerClient.aidl
@@ -29,4 +29,6 @@
     void notifyServicesStateChanged();
 
     void setRelevantEventTypes(int eventTypes);
+
+    void setMinimumUiTimeout(int uiTimeout);
 }
diff --git a/core/java/android/view/accessibility/TEST_MAPPING b/core/java/android/view/accessibility/TEST_MAPPING
new file mode 100644
index 0000000..d2bd6ea
--- /dev/null
+++ b/core/java/android/view/accessibility/TEST_MAPPING
@@ -0,0 +1,53 @@
+{
+  "presubmit": [
+    {
+      "name": "CtsAccessibilityServiceTestCases",
+      "options": [
+        {
+          "include-annotation": "android.platform.test.annotations.Presubmit"
+        },
+        {
+          "exclude-annotation": "android.support.test.filters.FlakyTest"
+        }
+      ]
+    },
+    {
+      "name": "CtsUiAutomationTestCases",
+      "options": [
+        {
+          "include-annotation": "android.platform.test.annotations.Presubmit"
+        },
+        {
+          "exclude-annotation": "android.support.test.filters.FlakyTest"
+        }
+      ]
+    },
+    {
+      "name": "FrameworksCoreTests",
+      "options": [
+        {
+          "include-filter": "android.view.accessibility"
+        },
+        {
+          "exclude-annotation": "androidx.test.filters.FlakyTest"
+        }
+      ]
+    }
+  ],
+  "postsubmit": [
+    {
+      "name": "CtsAccessibilityServiceTestCases"
+    },
+    {
+      "name": "CtsUiAutomationTestCases"
+    },
+    {
+      "name": "FrameworksCoreTests",
+      "options": [
+        {
+          "include-filter": "android.view.accessibility"
+        }
+      ]
+    }
+  ]
+}
diff --git a/core/java/android/view/inputmethod/InputContentInfo.java b/core/java/android/view/inputmethod/InputContentInfo.java
index 7104a28..0d0fea6 100644
--- a/core/java/android/view/inputmethod/InputContentInfo.java
+++ b/core/java/android/view/inputmethod/InputContentInfo.java
@@ -183,7 +183,15 @@
     @Nullable
     public Uri getLinkUri() { return mLinkUri; }
 
-    void setUriToken(IInputContentUriToken token) {
+    /**
+     * Update the internal state of this object to be associated with the given token.
+     *
+     * <p>TODO(yukawa): Come up with an idea to make {@link InputContentInfo} immutable.</p>
+     *
+     * @param token special URI token obtained from the system.
+     * @hide
+     */
+    public void setUriToken(IInputContentUriToken token) {
         if (mUriToken != null) {
             throw new IllegalStateException("URI token is already set");
         }
diff --git a/core/java/android/view/inputmethod/InputMethod.java b/core/java/android/view/inputmethod/InputMethod.java
index ab8886b..e1600c4 100644
--- a/core/java/android/view/inputmethod/InputMethod.java
+++ b/core/java/android/view/inputmethod/InputMethod.java
@@ -25,6 +25,8 @@
 import android.os.IBinder;
 import android.os.ResultReceiver;
 
+import com.android.internal.inputmethod.IInputMethodPrivilegedOperations;
+
 /**
  * The InputMethod interface represents an input method which can generate key
  * events and text, such as digital, email addresses, CJK characters, other
@@ -79,22 +81,52 @@
     public interface SessionCallback {
         public void sessionCreated(InputMethodSession session);
     }
-    
+
+    /**
+     * Called first thing after an input method is created, this supplies a
+     * unique token for the session it has with the system service as well as
+     * IPC endpoint to do some other privileged operations.
+     *
+     * @param token special token for the system to identify
+     *              {@link InputMethodService}
+     * @param displayId The id of the display that current IME shown.
+     *                  Used for {{@link #updateInputMethodDisplay(int)}}
+     * @param privilegedOperations IPC endpoint to do some privileged
+     *                             operations that are allowed only to the
+     *                             current IME.
+     * @hide
+     */
+    @MainThread
+    default void initializeInternal(IBinder token, int displayId,
+            IInputMethodPrivilegedOperations privilegedOperations) {
+        updateInputMethodDisplay(displayId);
+        attachToken(token);
+    }
+
     /**
      * Called first thing after an input method is created, this supplies a
      * unique token for the session it has with the system service.  It is
      * needed to identify itself with the service to validate its operations.
      * This token <strong>must not</strong> be passed to applications, since
      * it grants special priviledges that should not be given to applications.
-     * 
-     * <p>Note: to protect yourself from malicious clients, you should only
-     * accept the first token given to you.  Any after that may come from the
-     * client.
+     *
+     * <p>The system guarantees that this method is called back between
+     * {@link InputMethodService#onCreate()} and {@link InputMethodService#onDestroy()}
+     * at most once.
      */
     @MainThread
     public void attachToken(IBinder token);
 
     /**
+     * Update context display according to given displayId.
+     *
+     * @param displayId The id of the display that need to update for context.
+     * @hide
+     */
+    @MainThread
+    public void updateInputMethodDisplay(int displayId);
+
+    /**
      * Bind a new application environment in to the input method, so that it
      * can later start and stop input processing.
      * Typically this method is called when this input method is enabled in an
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index d3fd0cf..508509a 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -18,6 +18,7 @@
 
 import static android.Manifest.permission.WRITE_SECURE_SETTINGS;
 
+import android.annotation.DrawableRes;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresFeature;
@@ -29,7 +30,7 @@
 import android.content.pm.PackageManager;
 import android.graphics.Rect;
 import android.inputmethodservice.InputMethodService;
-import android.net.Uri;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
@@ -56,7 +57,8 @@
 import android.view.WindowManager.LayoutParams.SoftInputModeFlags;
 import android.view.autofill.AutofillManager;
 
-import com.android.internal.inputmethod.IInputContentUriToken;
+import com.android.internal.inputmethod.InputMethodPrivilegedOperations;
+import com.android.internal.inputmethod.InputMethodPrivilegedOperationsRegistry;
 import com.android.internal.os.SomeArgs;
 import com.android.internal.view.IInputConnectionWrapper;
 import com.android.internal.view.IInputContext;
@@ -334,7 +336,7 @@
     /**
      * The InputConnection that was last retrieved from the served view.
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     ControlledInputConnectionWrapper mServedInputConnectionWrapper;
     /**
      * The completions that were last provided by the served view.
@@ -352,28 +354,6 @@
     int mCursorCandEnd;
 
     /**
-     * Represents an invalid action notification sequence number.
-     * {@link com.android.server.InputMethodManagerService} always issues a positive integer for
-     * action notification sequence numbers. Thus {@code -1} is guaranteed to be different from any
-     * valid sequence number.
-     */
-    private static final int NOT_AN_ACTION_NOTIFICATION_SEQUENCE_NUMBER = -1;
-    /**
-     * The next sequence number that is to be sent to
-     * {@link com.android.server.InputMethodManagerService} via
-     * {@link IInputMethodManager#notifyUserAction(int)} at once when a user action is observed.
-     */
-    private int mNextUserActionNotificationSequenceNumber =
-            NOT_AN_ACTION_NOTIFICATION_SEQUENCE_NUMBER;
-
-    /**
-     * The last sequence number that is already sent to
-     * {@link com.android.server.InputMethodManagerService}.
-     */
-    private int mLastSentUserActionNotificationSequenceNumber =
-            NOT_AN_ACTION_NOTIFICATION_SEQUENCE_NUMBER;
-
-    /**
      * The instance that has previously been sent to the input method.
      */
     private CursorAnchorInfo mCursorAnchorInfo = null;
@@ -407,6 +387,9 @@
     final Pool<PendingEvent> mPendingEventPool = new SimplePool<>(20);
     final SparseArray<PendingEvent> mPendingEvents = new SparseArray<>(20);
 
+    private final InputMethodPrivilegedOperationsRegistry mPrivOpsRegistry =
+            new InputMethodPrivilegedOperationsRegistry();
+
     // -----------------------------------------------------------
 
     static final int MSG_DUMP = 1;
@@ -416,7 +399,6 @@
     static final int MSG_SEND_INPUT_EVENT = 5;
     static final int MSG_TIMEOUT_INPUT_EVENT = 6;
     static final int MSG_FLUSH_INPUT_EVENT = 7;
-    static final int MSG_SET_USER_ACTION_NOTIFICATION_SEQUENCE_NUMBER = 9;
     static final int MSG_REPORT_FULLSCREEN_MODE = 10;
 
     private static boolean isAutofillUIShowing(View servedView) {
@@ -553,12 +535,6 @@
                     finishedInputEvent(msg.arg1, false, false);
                     return;
                 }
-                case MSG_SET_USER_ACTION_NOTIFICATION_SEQUENCE_NUMBER: {
-                    synchronized (mH) {
-                        mNextUserActionNotificationSequenceNumber = msg.arg1;
-                    }
-                    return;
-                }
                 case MSG_REPORT_FULLSCREEN_MODE: {
                     final boolean fullscreen = msg.arg1 != 0;
                     InputConnection ic = null;
@@ -601,11 +577,6 @@
         }
 
         @Override
-        protected void onUserAction() {
-            mParentInputMethodManager.notifyUserAction();
-        }
-
-        @Override
         public String toString() {
             return "ControlledInputConnectionWrapper{"
                     + "connection=" + getInputConnection()
@@ -652,12 +623,6 @@
         }
 
         @Override
-        public void setUserActionNotificationSequenceNumber(int sequenceNumber) {
-            mH.obtainMessage(MSG_SET_USER_ACTION_NOTIFICATION_SEQUENCE_NUMBER, sequenceNumber, 0)
-                    .sendToTarget();
-        }
-
-        @Override
         public void reportFullscreenMode(boolean fullscreen) {
             mH.obtainMessage(MSG_REPORT_FULLSCREEN_MODE, fullscreen ? 1 : 0, 0)
                     .sendToTarget();
@@ -773,19 +738,8 @@
      * class are intended for app developers interacting with the IME.
      */
     @Deprecated
-    public void showStatusIcon(IBinder imeToken, String packageName, int iconId) {
-        showStatusIconInternal(imeToken, packageName, iconId);
-    }
-
-    /**
-     * @hide
-     */
-    public void showStatusIconInternal(IBinder imeToken, String packageName, int iconId) {
-        try {
-            mService.updateStatusIcon(imeToken, packageName, iconId);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
+    public void showStatusIcon(IBinder imeToken, String packageName, @DrawableRes int iconId) {
+        mPrivOpsRegistry.get(imeToken).updateStatusIcon(packageName, iconId);
     }
 
     /**
@@ -795,36 +749,7 @@
      */
     @Deprecated
     public void hideStatusIcon(IBinder imeToken) {
-        hideStatusIconInternal(imeToken);
-    }
-
-    /**
-     * @hide
-     */
-    public void hideStatusIconInternal(IBinder imeToken) {
-        try {
-            mService.updateStatusIcon(imeToken, null, 0);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /** @hide */
-    public void setImeWindowStatus(IBinder imeToken, int vis, int backDisposition) {
-        try {
-            mService.setImeWindowStatus(imeToken, vis, backDisposition);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /** @hide */
-    public void reportStartInput(IBinder imeToken, IBinder startInputToken) {
-        try {
-            mService.reportStartInput(imeToken, startInputToken);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
+        mPrivOpsRegistry.get(imeToken).updateStatusIcon(null, 0);
     }
 
     /** @hide */
@@ -859,17 +784,6 @@
     }
 
     /**
-     * @hide
-     */
-    public void reportFullscreenMode(IBinder token, boolean fullscreen) {
-        try {
-            mService.reportFullscreenMode(token, fullscreen);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
      * Return true if the given view is the currently active view for the
      * input method.
      */
@@ -1401,8 +1315,6 @@
                     mBindSequence = res.sequence;
                     mCurMethod = res.method;
                     mCurId = res.id;
-                    mNextUserActionNotificationSequenceNumber =
-                            res.userActionNotificationSequenceNumber;
                 } else if (res.channel != null && res.channel != mCurChannel) {
                     res.channel.dispose();
                 }
@@ -1876,18 +1788,18 @@
      */
     @Deprecated
     public void setInputMethod(IBinder token, String id) {
-        setInputMethodInternal(token, id);
-    }
-
-    /**
-     * @hide
-     */
-    public void setInputMethodInternal(IBinder token, String id) {
-        try {
-            mService.setInputMethod(token, id);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
+        if (token == null) {
+            // Note: null token is allowed for callers that have WRITE_SECURE_SETTINGS permission.
+            // Thus we cannot always rely on mPrivOpsRegistry unfortunately.
+            // TODO(Bug 114488811): Consider deprecating null token rule.
+            try {
+                mService.setInputMethod(token, id);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+            return;
         }
+        mPrivOpsRegistry.get(token).setInputMethod(id);
     }
 
     /**
@@ -1905,19 +1817,18 @@
      */
     @Deprecated
     public void setInputMethodAndSubtype(IBinder token, String id, InputMethodSubtype subtype) {
-        setInputMethodAndSubtypeInternal(token, id, subtype);
-    }
-
-    /**
-     * @hide
-     */
-    public void setInputMethodAndSubtypeInternal(
-            IBinder token, String id, InputMethodSubtype subtype) {
-        try {
-            mService.setInputMethodAndSubtype(token, id, subtype);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
+        if (token == null) {
+            // Note: null token is allowed for callers that have WRITE_SECURE_SETTINGS permission.
+            // Thus we cannot always rely on mPrivOpsRegistry unfortunately.
+            // TODO(Bug 114488811): Consider deprecating null token rule.
+            try {
+                mService.setInputMethodAndSubtype(token, id, subtype);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+            return;
         }
+        mPrivOpsRegistry.get(token).setInputMethodAndSubtype(id, subtype);
     }
 
     /**
@@ -1937,18 +1848,7 @@
      */
     @Deprecated
     public void hideSoftInputFromInputMethod(IBinder token, int flags) {
-        hideSoftInputFromInputMethodInternal(token, flags);
-    }
-
-    /**
-     * @hide
-     */
-    public void hideSoftInputFromInputMethodInternal(IBinder token, int flags) {
-        try {
-            mService.hideMySoftInput(token, flags);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
+        mPrivOpsRegistry.get(token).hideMySoftInput(flags);
     }
 
     /**
@@ -1969,18 +1869,7 @@
      */
     @Deprecated
     public void showSoftInputFromInputMethod(IBinder token, int flags) {
-        showSoftInputFromInputMethodInternal(token, flags);
-    }
-
-    /**
-     * @hide
-     */
-    public void showSoftInputFromInputMethodInternal(IBinder token, int flags) {
-        try {
-            mService.showMySoftInput(token, flags);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
+        mPrivOpsRegistry.get(token).showMySoftInput(flags);
     }
 
     /**
@@ -2178,15 +2067,13 @@
      * @hide
      */
     public void showInputMethodPicker(boolean showAuxiliarySubtypes) {
-        synchronized (mH) {
-            try {
-                final int mode = showAuxiliarySubtypes ?
-                        SHOW_IM_PICKER_MODE_INCLUDE_AUXILIARY_SUBTYPES:
-                        SHOW_IM_PICKER_MODE_EXCLUDE_AUXILIARY_SUBTYPES;
-                mService.showInputMethodPickerFromClient(mClient, mode);
-            } catch (RemoteException e) {
-                throw e.rethrowFromSystemServer();
-            }
+        final int mode = showAuxiliarySubtypes
+                ? SHOW_IM_PICKER_MODE_INCLUDE_AUXILIARY_SUBTYPES
+                : SHOW_IM_PICKER_MODE_EXCLUDE_AUXILIARY_SUBTYPES;
+        try {
+            mService.showInputMethodPickerFromClient(mClient, mode);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2224,12 +2111,10 @@
      * subtypes of all input methods will be shown.
      */
     public void showInputMethodAndSubtypeEnabler(String imiId) {
-        synchronized (mH) {
-            try {
-                mService.showInputMethodAndSubtypeEnablerFromClient(mClient, imiId);
-            } catch (RemoteException e) {
-                throw e.rethrowFromSystemServer();
-            }
+        try {
+            mService.showInputMethodAndSubtypeEnablerFromClient(mClient, imiId);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2254,48 +2139,25 @@
      */
     @RequiresPermission(WRITE_SECURE_SETTINGS)
     public boolean setCurrentInputMethodSubtype(InputMethodSubtype subtype) {
-        synchronized (mH) {
-            try {
-                return mService.setCurrentInputMethodSubtype(subtype);
-            } catch (RemoteException e) {
-                throw e.rethrowFromSystemServer();
-            }
+        try {
+            return mService.setCurrentInputMethodSubtype(subtype);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
     /**
      * Notify that a user took some action with this input method.
+     *
+     * @deprecated Just kept to avoid possible app compat issue.
      * @hide
      */
-    @UnsupportedAppUsage
+    @Deprecated
+    @UnsupportedAppUsage(trackingBug = 114740982, maxTargetSdk = Build.VERSION_CODES.P)
     public void notifyUserAction() {
-        synchronized (mH) {
-            if (mLastSentUserActionNotificationSequenceNumber ==
-                    mNextUserActionNotificationSequenceNumber) {
-                if (DEBUG) {
-                    Log.w(TAG, "Ignoring notifyUserAction as it has already been sent."
-                            + " mLastSentUserActionNotificationSequenceNumber: "
-                            + mLastSentUserActionNotificationSequenceNumber
-                            + " mNextUserActionNotificationSequenceNumber: "
-                            + mNextUserActionNotificationSequenceNumber);
-                }
-                return;
-            }
-            try {
-                if (DEBUG) {
-                    Log.w(TAG, "notifyUserAction: "
-                            + " mLastSentUserActionNotificationSequenceNumber: "
-                            + mLastSentUserActionNotificationSequenceNumber
-                            + " mNextUserActionNotificationSequenceNumber: "
-                            + mNextUserActionNotificationSequenceNumber);
-                }
-                mService.notifyUserAction(mNextUserActionNotificationSequenceNumber);
-                mLastSentUserActionNotificationSequenceNumber =
-                        mNextUserActionNotificationSequenceNumber;
-            } catch (RemoteException e) {
-                throw e.rethrowFromSystemServer();
-            }
-        }
+        Log.w(TAG, "notifyUserAction() is a hidden method, which is now just a stub method"
+                + " that does nothing.  Leave comments in b.android.com/114740982 if your "
+                + " application still depends on the previous behavior of this method.");
     }
 
     /**
@@ -2333,39 +2195,21 @@
     }
 
     /**
-     * @return The current height of the input method window.
+     * This is kept due to {@link android.annotation.UnsupportedAppUsage}.
+     *
+     * <p>TODO(Bug 113914148): Check if we can remove this.  We have accidentally exposed
+     * WindowManagerInternal#getInputMethodWindowVisibleHeight to app developers and some of them
+     * started relying on it.</p>
+     *
+     * @return Something that is not well-defined.
      * @hide
      */
     @UnsupportedAppUsage
     public int getInputMethodWindowVisibleHeight() {
-        synchronized (mH) {
-            try {
-                return mService.getInputMethodWindowVisibleHeight();
-            } catch (RemoteException e) {
-                throw e.rethrowFromSystemServer();
-            }
-        }
-    }
-
-    /**
-     * Tells the system that the IME decided to not show a window and the system no longer needs to
-     * use the previous IME's inset.
-     *
-     * <p>Caveat: {@link android.inputmethodservice.InputMethodService#clearInsetOfPreviousIme()}
-     * is the only expected caller of this method.  Do not depend on this anywhere else.</p>
-     *
-     * <p>TODO: We probably need to reconsider how IME should be handled.</p>
-     * @hide
-     * @param token Supplies the identifying token given to an input method when it was started,
-     * which allows it to perform this operation on itself.
-     */
-    public void clearLastInputMethodWindowForTransition(final IBinder token) {
-        synchronized (mH) {
-            try {
-                mService.clearLastInputMethodWindowForTransition(token);
-            } catch (RemoteException e) {
-                throw e.rethrowFromSystemServer();
-            }
+        try {
+            return mService.getInputMethodWindowVisibleHeight();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2383,20 +2227,17 @@
      */
     @Deprecated
     public boolean switchToLastInputMethod(IBinder imeToken) {
-        return switchToPreviousInputMethodInternal(imeToken);
-    }
-
-    /**
-     * @hide
-     */
-    public boolean switchToPreviousInputMethodInternal(IBinder imeToken) {
-        synchronized (mH) {
+        if (imeToken == null) {
+            // Note: null token is allowed for callers that have WRITE_SECURE_SETTINGS permission.
+            // Thus we cannot always rely on mPrivOpsRegistry unfortunately.
+            // TODO(Bug 114488811): Consider deprecating null token rule.
             try {
                 return mService.switchToPreviousInputMethod(imeToken);
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
         }
+        return mPrivOpsRegistry.get(imeToken).switchToPreviousInputMethod();
     }
 
     /**
@@ -2414,20 +2255,17 @@
      */
     @Deprecated
     public boolean switchToNextInputMethod(IBinder imeToken, boolean onlyCurrentIme) {
-        return switchToNextInputMethodInternal(imeToken, onlyCurrentIme);
-    }
-
-    /**
-     * @hide
-     */
-    public boolean switchToNextInputMethodInternal(IBinder imeToken, boolean onlyCurrentIme) {
-        synchronized (mH) {
+        if (imeToken == null) {
+            // Note: null token is allowed for callers that have WRITE_SECURE_SETTINGS permission.
+            // Thus we cannot always rely on mPrivOpsRegistry unfortunately.
+            // TODO(Bug 114488811): Consider deprecating null token rule.
             try {
                 return mService.switchToNextInputMethod(imeToken, onlyCurrentIme);
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
         }
+        return mPrivOpsRegistry.get(imeToken).switchToNextInputMethod(onlyCurrentIme);
     }
 
     /**
@@ -2446,20 +2284,7 @@
      */
     @Deprecated
     public boolean shouldOfferSwitchingToNextInputMethod(IBinder imeToken) {
-        return shouldOfferSwitchingToNextInputMethodInternal(imeToken);
-    }
-
-    /**
-     * @hide
-     */
-    public boolean shouldOfferSwitchingToNextInputMethodInternal(IBinder imeToken) {
-        synchronized (mH) {
-            try {
-                return mService.shouldOfferSwitchingToNextInputMethod(imeToken);
-            } catch (RemoteException e) {
-                throw e.rethrowFromSystemServer();
-            }
-        }
+        return mPrivOpsRegistry.get(imeToken).shouldOfferSwitchingToNextInputMethod();
     }
 
     /**
@@ -2488,57 +2313,19 @@
      * @param subtypes subtypes will be added as additional subtypes of the current input method.
      */
     public void setAdditionalInputMethodSubtypes(String imiId, InputMethodSubtype[] subtypes) {
-        synchronized (mH) {
-            try {
-                mService.setAdditionalInputMethodSubtypes(imiId, subtypes);
-            } catch (RemoteException e) {
-                throw e.rethrowFromSystemServer();
-            }
+        try {
+            mService.setAdditionalInputMethodSubtypes(imiId, subtypes);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
     public InputMethodSubtype getLastInputMethodSubtype() {
-        synchronized (mH) {
-            try {
-                return mService.getLastInputMethodSubtype();
-            } catch (RemoteException e) {
-                throw e.rethrowFromSystemServer();
-            }
-        }
-    }
-
-    /**
-     * Allow the receiver of {@link InputContentInfo} to obtain a temporary read-only access
-     * permission to the content.
-     *
-     * <p>See {@link android.inputmethodservice.InputMethodService#exposeContent(InputContentInfo,
-     * InputConnection)} for details.</p>
-     *
-     * @param token Supplies the identifying token given to an input method when it was started,
-     * which allows it to perform this operation on itself.
-     * @param inputContentInfo Content to be temporarily exposed from the input method to the
-     * application.
-     * This cannot be {@code null}.
-     * @param editorInfo The editor that receives {@link InputContentInfo}.
-     * @hide
-     */
-    public void exposeContent(@NonNull IBinder token, @NonNull InputContentInfo inputContentInfo,
-            @NonNull EditorInfo editorInfo) {
-        final IInputContentUriToken uriToken;
-        final Uri contentUri = inputContentInfo.getContentUri();
         try {
-            uriToken = mService.createInputContentUriToken(token, contentUri,
-                    editorInfo.packageName);
-            if (uriToken == null) {
-                return;
-            }
+            return mService.getLastInputMethodSubtype();
         } catch (RemoteException e) {
-            Log.e(TAG, "createInputContentAccessToken failed. contentUri=" + contentUri.toString()
-                    + " packageName=" + editorInfo.packageName, e);
-            return;
+            throw e.rethrowFromSystemServer();
         }
-        inputContentInfo.setUriToken(uriToken);
-        return;
     }
 
     void doDump(FileDescriptor fd, PrintWriter fout, String[] args) {
@@ -2571,10 +2358,6 @@
                 + " mCursorSelEnd=" + mCursorSelEnd
                 + " mCursorCandStart=" + mCursorCandStart
                 + " mCursorCandEnd=" + mCursorCandEnd);
-        p.println("  mNextUserActionNotificationSequenceNumber="
-                + mNextUserActionNotificationSequenceNumber
-                + " mLastSentUserActionNotificationSequenceNumber="
-                + mLastSentUserActionNotificationSequenceNumber);
     }
 
     /**
@@ -2637,4 +2420,34 @@
         sb.append(",temporaryDetach=" + view.isTemporarilyDetached());
         return sb.toString();
     }
+
+    /**
+     * Called by {@link InputMethodService} so that API calls to deprecated ones defined in this
+     * class can be forwarded to {@link InputMethodPrivilegedOperations}.
+     *
+     * <p>Note: this method does not hold strong references to {@code token} and {@code ops}. The
+     * registry entry will be automatically cleared after {@code token} is garbage collected.</p>
+     *
+     * @param token IME token that is associated with {@code ops}
+     * @param ops {@link InputMethodPrivilegedOperations} that is associated with {@code token}
+     * @hide
+     */
+    public void registerInputMethodPrivOps(IBinder token, InputMethodPrivilegedOperations ops) {
+        mPrivOpsRegistry.put(token, ops);
+    }
+
+    /**
+     * Called from {@link InputMethodService#onDestroy()} to make sure that deprecated IME APIs
+     * defined in this class can no longer access to {@link InputMethodPrivilegedOperations}.
+     *
+     * <p>Note: Calling this method is optional, but at least gives more explict error message in
+     * logcat when IME developers are doing something unsupported (e.g. trying to call IME APIs
+     * after {@link InputMethodService#onDestroy()}).</p>
+     *
+     * @param token IME token to be removed.
+     * @hide
+     */
+    public void unregisterInputMethodPrivOps(IBinder token) {
+        mPrivOpsRegistry.remove(token);
+    }
 }
diff --git a/core/java/android/webkit/SafeBrowsingResponse.java b/core/java/android/webkit/SafeBrowsingResponse.java
index 1d3a617..7839a00 100644
--- a/core/java/android/webkit/SafeBrowsingResponse.java
+++ b/core/java/android/webkit/SafeBrowsingResponse.java
@@ -36,14 +36,14 @@
     public abstract void showInterstitial(boolean allowReporting);
 
     /**
-     * Act as if the user clicked "visit this unsafe site."
+     * Act as if the user clicked the "visit this unsafe site" button.
      *
      * @param report {@code true} to enable Safe Browsing reporting.
      */
     public abstract void proceed(boolean report);
 
     /**
-     * Act as if the user clicked "back to safety."
+     * Act as if the user clicked the "back to safety" button.
      *
      * @param report {@code true} to enable Safe Browsing reporting.
      */
diff --git a/core/java/android/webkit/WebViewFactory.java b/core/java/android/webkit/WebViewFactory.java
index e9a9e8f..46b1f6e 100644
--- a/core/java/android/webkit/WebViewFactory.java
+++ b/core/java/android/webkit/WebViewFactory.java
@@ -51,9 +51,6 @@
 
     private static final String CHROMIUM_WEBVIEW_FACTORY_METHOD = "create";
 
-    public static final String CHROMIUM_WEBVIEW_VMSIZE_SIZE_PROPERTY =
-            "persist.sys.webview.vmsize";
-
     private static final String LOGTAG = "WebViewFactory";
 
     private static final boolean DEBUG = false;
diff --git a/core/java/android/webkit/WebViewLibraryLoader.java b/core/java/android/webkit/WebViewLibraryLoader.java
index cabba06..5a6aeba 100644
--- a/core/java/android/webkit/WebViewLibraryLoader.java
+++ b/core/java/android/webkit/WebViewLibraryLoader.java
@@ -17,15 +17,14 @@
 package android.webkit;
 
 import android.annotation.NonNull;
-import android.annotation.Nullable;
 import android.app.ActivityManagerInternal;
-import android.content.pm.ApplicationInfo;
+import android.app.ActivityThread;
+import android.app.LoadedApk;
+import android.content.Context;
 import android.content.pm.PackageInfo;
 import android.os.Build;
 import android.os.Process;
 import android.os.RemoteException;
-import android.os.SystemProperties;
-import android.text.TextUtils;
 import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -33,11 +32,7 @@
 
 import dalvik.system.VMRuntime;
 
-import java.io.File;
-import java.io.IOException;
 import java.util.Arrays;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipFile;
 
 /**
  * @hide
@@ -50,7 +45,6 @@
             "/data/misc/shared_relro/libwebviewchromium32.relro";
     private static final String CHROMIUM_WEBVIEW_NATIVE_RELRO_64 =
             "/data/misc/shared_relro/libwebviewchromium64.relro";
-    private static final long CHROMIUM_WEBVIEW_DEFAULT_VMSIZE_BYTES = 100 * 1024 * 1024;
 
     private static final boolean DEBUG = false;
 
@@ -69,18 +63,26 @@
             boolean result = false;
             boolean is64Bit = VMRuntime.getRuntime().is64Bit();
             try {
-                if (args.length != 1 || args[0] == null) {
+                if (args.length != 2 || args[0] == null || args[1] == null) {
                     Log.e(LOGTAG, "Invalid RelroFileCreator args: " + Arrays.toString(args));
                     return;
                 }
-                Log.v(LOGTAG, "RelroFileCreator (64bit = " + is64Bit + "), lib: " + args[0]);
+                String packageName = args[0];
+                String libraryFileName = args[1];
+                Log.v(LOGTAG, "RelroFileCreator (64bit = " + is64Bit + "), package: "
+                        + packageName + " library: " + libraryFileName);
                 if (!sAddressSpaceReserved) {
                     Log.e(LOGTAG, "can't create relro file; address space not reserved");
                     return;
                 }
-                result = nativeCreateRelroFile(args[0] /* path */,
+                LoadedApk apk = ActivityThread.currentActivityThread().getPackageInfo(
+                        packageName,
+                        null,
+                        Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY);
+                result = nativeCreateRelroFile(libraryFileName,
                                                is64Bit ? CHROMIUM_WEBVIEW_NATIVE_RELRO_64 :
-                                                         CHROMIUM_WEBVIEW_NATIVE_RELRO_32);
+                                                         CHROMIUM_WEBVIEW_NATIVE_RELRO_32,
+                                               apk.getClassLoader());
                 if (result && DEBUG) Log.v(LOGTAG, "created relro file");
             } finally {
                 // We must do our best to always notify the update service, even if something fails.
@@ -101,7 +103,8 @@
     /**
      * Create a single relro file by invoking an isolated process that to do the actual work.
      */
-    static void createRelroFile(final boolean is64Bit, @NonNull WebViewNativeLibrary nativeLib) {
+    static void createRelroFile(final boolean is64Bit, @NonNull String packageName,
+            @NonNull String libraryFileName) {
         final String abi =
                 is64Bit ? Build.SUPPORTED_64_BIT_ABIS[0] : Build.SUPPORTED_32_BIT_ABIS[0];
 
@@ -119,13 +122,10 @@
         };
 
         try {
-            if (nativeLib == null || nativeLib.path == null) {
-                throw new IllegalArgumentException(
-                        "Native library paths to the WebView RelRo process must not be null!");
-            }
             boolean success = LocalServices.getService(ActivityManagerInternal.class)
                     .startIsolatedProcess(
-                            RelroFileCreator.class.getName(), new String[] { nativeLib.path },
+                            RelroFileCreator.class.getName(),
+                            new String[] { packageName, libraryFileName },
                             "WebViewLoader-" + abi, abi, Process.SHARED_RELRO_UID, crashHandler);
             if (!success) throw new Exception("Failed to start the relro file creator process");
         } catch (Throwable t) {
@@ -140,83 +140,50 @@
      * be called whenever we change WebView provider.
      * @return the number of relro processes started.
      */
-    static int prepareNativeLibraries(PackageInfo webviewPackageInfo)
-            throws WebViewFactory.MissingWebViewPackageException {
-        WebViewNativeLibrary nativeLib32bit =
-                getWebViewNativeLibrary(webviewPackageInfo, false /* is64bit */);
-        WebViewNativeLibrary nativeLib64bit =
-                getWebViewNativeLibrary(webviewPackageInfo, true /* is64bit */);
-        updateWebViewZygoteVmSize(nativeLib32bit, nativeLib64bit);
-
-        return createRelros(nativeLib32bit, nativeLib64bit);
+    static int prepareNativeLibraries(@NonNull PackageInfo webViewPackageInfo) {
+        // TODO(torne): new way of calculating VM size
+        // updateWebViewZygoteVmSize(nativeLib32bit, nativeLib64bit);
+        String libraryFileName = WebViewFactory.getWebViewLibrary(
+                webViewPackageInfo.applicationInfo);
+        if (libraryFileName == null) {
+            // Can't do anything with no filename, don't spawn any processes.
+            return 0;
+        }
+        return createRelros(webViewPackageInfo.packageName, libraryFileName);
     }
 
     /**
      * @return the number of relro processes started.
      */
-    private static int createRelros(@Nullable WebViewNativeLibrary nativeLib32bit,
-            @Nullable WebViewNativeLibrary nativeLib64bit) {
+    private static int createRelros(@NonNull String packageName, @NonNull String libraryFileName) {
         if (DEBUG) Log.v(LOGTAG, "creating relro files");
         int numRelros = 0;
 
         if (Build.SUPPORTED_32_BIT_ABIS.length > 0) {
-            if (nativeLib32bit == null) {
-                Log.e(LOGTAG, "No 32-bit WebView library path, skipping relro creation.");
-            } else {
-                if (DEBUG) Log.v(LOGTAG, "Create 32 bit relro");
-                createRelroFile(false /* is64Bit */, nativeLib32bit);
-                numRelros++;
-            }
+            if (DEBUG) Log.v(LOGTAG, "Create 32 bit relro");
+            createRelroFile(false /* is64Bit */, packageName, libraryFileName);
+            numRelros++;
         }
 
         if (Build.SUPPORTED_64_BIT_ABIS.length > 0) {
-            if (nativeLib64bit == null) {
-                Log.e(LOGTAG, "No 64-bit WebView library path, skipping relro creation.");
-            } else {
-                if (DEBUG) Log.v(LOGTAG, "Create 64 bit relro");
-                createRelroFile(true /* is64Bit */, nativeLib64bit);
-                numRelros++;
-            }
+            if (DEBUG) Log.v(LOGTAG, "Create 64 bit relro");
+            createRelroFile(true /* is64Bit */, packageName, libraryFileName);
+            numRelros++;
         }
         return numRelros;
     }
 
     /**
-     *
-     * @return the native WebView libraries in the new WebView APK.
-     */
-    private static void updateWebViewZygoteVmSize(
-            @Nullable WebViewNativeLibrary nativeLib32bit,
-            @Nullable WebViewNativeLibrary nativeLib64bit)
-            throws WebViewFactory.MissingWebViewPackageException {
-        // Find the native libraries of the new WebView package, to change the size of the
-        // memory region in the Zygote reserved for the library.
-        long newVmSize = 0L;
-
-        if (nativeLib32bit != null) newVmSize = Math.max(newVmSize, nativeLib32bit.size);
-        if (nativeLib64bit != null) newVmSize = Math.max(newVmSize, nativeLib64bit.size);
-
-        if (DEBUG) {
-            Log.v(LOGTAG, "Based on library size, need " + newVmSize
-                    + " bytes of address space.");
-        }
-        // The required memory can be larger than the file on disk (due to .bss), and an
-        // upgraded version of the library will likely be larger, so always attempt to
-        // reserve twice as much as we think to allow for the library to grow during this
-        // boot cycle.
-        newVmSize = Math.max(2 * newVmSize, CHROMIUM_WEBVIEW_DEFAULT_VMSIZE_BYTES);
-        Log.d(LOGTAG, "Setting new address space to " + newVmSize);
-        setWebViewZygoteVmSize(newVmSize);
-    }
-
-    /**
      * Reserve space for the native library to be loaded into.
      */
     static void reserveAddressSpaceInZygote() {
         System.loadLibrary("webviewchromium_loader");
-        long addressSpaceToReserve =
-                SystemProperties.getLong(WebViewFactory.CHROMIUM_WEBVIEW_VMSIZE_SIZE_PROPERTY,
-                CHROMIUM_WEBVIEW_DEFAULT_VMSIZE_BYTES);
+        boolean is64Bit = VMRuntime.getRuntime().is64Bit();
+        // On 64-bit address space is really cheap and we can reserve 1GB which is plenty.
+        // On 32-bit it's fairly scarce and we should keep it to a realistic number that
+        // permits some future growth but doesn't hog space: we use 100MB which is more than 2x
+        // the current requirement.
+        long addressSpaceToReserve = is64Bit ? 1 * 1024 * 1024 * 1024 : 100 * 1024 * 1024;
         sAddressSpaceReserved = nativeReserveAddressSpace(addressSpaceToReserve);
 
         if (sAddressSpaceReserved) {
@@ -253,106 +220,7 @@
         return result;
     }
 
-    /**
-     * Fetch WebView's native library paths from {@param packageInfo}.
-     * @hide
-     */
-    @Nullable
-    @VisibleForTesting
-    public static WebViewNativeLibrary getWebViewNativeLibrary(PackageInfo packageInfo,
-            boolean is64bit) throws WebViewFactory.MissingWebViewPackageException {
-        ApplicationInfo ai = packageInfo.applicationInfo;
-        final String nativeLibFileName = WebViewFactory.getWebViewLibrary(ai);
-
-        String dir = getWebViewNativeLibraryDirectory(ai, is64bit /* 64bit */);
-
-        WebViewNativeLibrary lib = findNativeLibrary(ai, nativeLibFileName,
-                is64bit ? Build.SUPPORTED_64_BIT_ABIS : Build.SUPPORTED_32_BIT_ABIS, dir);
-
-        if (DEBUG) {
-            Log.v(LOGTAG, String.format("Native %d-bit lib: %s", is64bit ? 64 : 32, lib.path));
-        }
-        return lib;
-    }
-
-    /**
-     * @return the directory of the native WebView library with bitness {@param is64bit}.
-     * @hide
-     */
-    @VisibleForTesting
-    public static String getWebViewNativeLibraryDirectory(ApplicationInfo ai, boolean is64bit) {
-        // Primary arch has the same bitness as the library we are looking for.
-        if (is64bit == VMRuntime.is64BitAbi(ai.primaryCpuAbi)) return ai.nativeLibraryDir;
-
-        // Secondary arch has the same bitness as the library we are looking for.
-        if (!TextUtils.isEmpty(ai.secondaryCpuAbi)) {
-            return ai.secondaryNativeLibraryDir;
-        }
-
-        return "";
-    }
-
-    /**
-     * @return an object describing a native WebView library given the directory path of that
-     * library, or null if the library couldn't be found.
-     */
-    @Nullable
-    private static WebViewNativeLibrary findNativeLibrary(ApplicationInfo ai,
-            String nativeLibFileName, String[] abiList, String libDirectory)
-            throws WebViewFactory.MissingWebViewPackageException {
-        if (TextUtils.isEmpty(libDirectory)) return null;
-        String libPath = libDirectory + "/" + nativeLibFileName;
-        File f = new File(libPath);
-        if (f.exists()) {
-            return new WebViewNativeLibrary(libPath, f.length());
-        } else {
-            return getLoadFromApkPath(ai.sourceDir, abiList, nativeLibFileName);
-        }
-    }
-
-    /**
-     * @hide
-     */
-    @VisibleForTesting
-    public static class WebViewNativeLibrary {
-        public final String path;
-        public final long size;
-
-        WebViewNativeLibrary(String path, long size) {
-            this.path = path;
-            this.size = size;
-        }
-    }
-
-    private static WebViewNativeLibrary getLoadFromApkPath(String apkPath,
-                                                           String[] abiList,
-                                                           String nativeLibFileName)
-            throws WebViewFactory.MissingWebViewPackageException {
-        // Search the APK for a native library conforming to a listed ABI.
-        try (ZipFile z = new ZipFile(apkPath)) {
-            for (String abi : abiList) {
-                final String entry = "lib/" + abi + "/" + nativeLibFileName;
-                ZipEntry e = z.getEntry(entry);
-                if (e != null && e.getMethod() == ZipEntry.STORED) {
-                    // Return a path formatted for dlopen() load from APK.
-                    return new WebViewNativeLibrary(apkPath + "!/" + entry, e.getSize());
-                }
-            }
-        } catch (IOException e) {
-            throw new WebViewFactory.MissingWebViewPackageException(e);
-        }
-        return null;
-    }
-
-    /**
-     * Sets the size of the memory area in which to store the relro section.
-     */
-    private static void setWebViewZygoteVmSize(long vmSize) {
-        SystemProperties.set(WebViewFactory.CHROMIUM_WEBVIEW_VMSIZE_SIZE_PROPERTY,
-                Long.toString(vmSize));
-    }
-
     static native boolean nativeReserveAddressSpace(long addressSpaceToReserve);
-    static native boolean nativeCreateRelroFile(String lib, String relro);
+    static native boolean nativeCreateRelroFile(String lib, String relro, ClassLoader clazzLoader);
     static native int nativeLoadWithRelroFile(String lib, String relro, ClassLoader clazzLoader);
 }
diff --git a/core/java/android/widget/AdapterView.java b/core/java/android/widget/AdapterView.java
index dd6c923..f3fe16e 100644
--- a/core/java/android/widget/AdapterView.java
+++ b/core/java/android/widget/AdapterView.java
@@ -682,7 +682,7 @@
 
     /**
      * Sets the currently selected item. To support accessibility subclasses that
-     * override this method must invoke the overriden super method first.
+     * override this method must invoke the overridden super method first.
      *
      * @param position Index (starting at 0) of the data item to be selected.
      */
diff --git a/core/java/android/widget/AutoCompleteTextView.java b/core/java/android/widget/AutoCompleteTextView.java
index 71d13a9..cbd624e 100644
--- a/core/java/android/widget/AutoCompleteTextView.java
+++ b/core/java/android/widget/AutoCompleteTextView.java
@@ -24,6 +24,7 @@
 import android.database.DataSetObserver;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
+import android.os.Build;
 import android.text.Editable;
 import android.text.Selection;
 import android.text.TextUtils;
@@ -533,7 +534,7 @@
      *
      * @hide Pending API council approval
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     public void setDropDownAnimationStyle(int animationStyle) {
         mPopup.setAnimationStyle(animationStyle);
     }
diff --git a/core/java/android/widget/LinearLayout.java b/core/java/android/widget/LinearLayout.java
index 452e903..f2e478d 100644
--- a/core/java/android/widget/LinearLayout.java
+++ b/core/java/android/widget/LinearLayout.java
@@ -653,7 +653,7 @@
     }
 
     /**
-     * <p>Returns the view at the specified index. This method can be overriden
+     * <p>Returns the view at the specified index. This method can be overridden
      * to take into account virtual children. Refer to
      * {@link android.widget.TableLayout} and {@link android.widget.TableRow}
      * for an example.</p>
@@ -1527,7 +1527,7 @@
 
     /**
      * <p>Measure the child according to the parent's measure specs. This
-     * method should be overriden by subclasses to force the sizing of
+     * method should be overridden by subclasses to force the sizing of
      * children. This method is called by {@link #measureVertical(int, int)} and
      * {@link #measureHorizontal(int, int)}.</p>
      *
diff --git a/core/java/android/widget/Magnifier.java b/core/java/android/widget/Magnifier.java
index f82b17f..8e2786d 100644
--- a/core/java/android/widget/Magnifier.java
+++ b/core/java/android/widget/Magnifier.java
@@ -77,11 +77,13 @@
     // The height of the window containing the magnifier.
     private final int mWindowHeight;
     // The zoom applied to the view region copied to the magnifier view.
-    private final float mZoom;
+    private float mZoom;
     // The width of the content that will be copied to the magnifier.
-    private final int mSourceWidth;
+    private int mSourceWidth;
     // The height of the content that will be copied to the magnifier.
-    private final int mSourceHeight;
+    private int mSourceHeight;
+    // Whether the zoom of the magnifier has changed since last content copy.
+    private boolean mDirtyZoom;
     // The elevation of the window containing the magnifier.
     private final float mWindowElevation;
     // The corner radius of the window containing the magnifier.
@@ -196,7 +198,8 @@
 
         final int startX = mClampedCenterZoomCoords.x - mSourceWidth / 2;
         final int startY = mClampedCenterZoomCoords.y - mSourceHeight / 2;
-        if (sourceCenterX != mPrevShowSourceCoords.x || sourceCenterY != mPrevShowSourceCoords.y) {
+        if (sourceCenterX != mPrevShowSourceCoords.x || sourceCenterY != mPrevShowSourceCoords.y
+                || mDirtyZoom) {
             if (mWindow == null) {
                 synchronized (mLock) {
                     mWindow = new InternalPopupWindow(mView.getContext(), mView.getDisplay(),
@@ -212,11 +215,11 @@
             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) {
+                    if (mWindow != currentWindowInstance) {
+                        // The magnifier was dismissed (and maybe shown again) in the meantime.
+                        return;
+                    }
                     mWindow.setContentPositionForNextDraw(windowCoords.x, windowCoords.y);
                 }
             });
@@ -253,9 +256,16 @@
     public void update() {
         if (mWindow != null) {
             obtainSurfaces();
-            // Update the content shown in the magnifier.
-            performPixelCopy(mPrevStartCoordsInSurface.x, mPrevStartCoordsInSurface.y,
-                    false /* update window position */);
+            if (!mDirtyZoom) {
+                // Update the content shown in the magnifier.
+                performPixelCopy(mPrevStartCoordsInSurface.x, mPrevStartCoordsInSurface.y,
+                        false /* update window position */);
+            } else {
+                // If the zoom has changed, we cannot use the same top left coordinates
+                // as before, so just #show again to have them recomputed.
+                show(mPrevShowSourceCoords.x, mPrevShowSourceCoords.y,
+                        mPrevShowWindowCoords.x, mPrevShowWindowCoords.y);
+            }
         }
     }
 
@@ -298,6 +308,18 @@
     }
 
     /**
+     * Sets the zoom to be applied to the chosen content before being copied to the magnifier popup.
+     * @param zoom the zoom to be set
+     */
+    public void setZoom(@FloatRange(from = 0f) float zoom) {
+        Preconditions.checkArgumentPositive(zoom, "Zoom should be positive");
+        mZoom = zoom;
+        mSourceWidth = Math.round(mWindowWidth / mZoom);
+        mSourceHeight = Math.round(mWindowHeight / mZoom);
+        mDirtyZoom = true;
+    }
+
+    /**
      * Returns the zoom to be applied to the magnified view region copied to the magnifier.
      * If the zoom is x and the magnifier window size is (width, height), the original size
      * of the content being magnified will be (width / x, height / x).
@@ -534,6 +556,7 @@
                 sPixelCopyHandlerThread.getThreadHandler());
         mPrevStartCoordsInSurface.x = startXInSurface;
         mPrevStartCoordsInSurface.y = startYInSurface;
+        mDirtyZoom = false;
     }
 
     /**
@@ -1020,6 +1043,21 @@
     }
 
     /**
+     * @return the content to be magnified, as bitmap
+     *
+     * @hide
+     */
+    @TestApi
+    public @Nullable Bitmap getOriginalContent() {
+        if (mWindow == null) {
+            return null;
+        }
+        synchronized (mWindow.mLock) {
+            return Bitmap.createBitmap(mWindow.mBitmap);
+        }
+    }
+
+    /**
      * @return the size of the magnifier window in dp
      *
      * @hide
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index 0da47fd..1883809 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -545,7 +545,7 @@
             StateListDrawable stateList = (StateListDrawable) mBackground;
 
             // Find the above-anchor view - this one's easy, it should be labeled as such.
-            int aboveAnchorStateIndex = stateList.getStateDrawableIndex(ABOVE_ANCHOR_STATE_SET);
+            int aboveAnchorStateIndex = stateList.findStateDrawableIndex(ABOVE_ANCHOR_STATE_SET);
 
             // Now, for the below-anchor view, look for any other drawable specified in the
             // StateListDrawable which is not for the above-anchor state and use that.
diff --git a/core/java/android/widget/SearchView.java b/core/java/android/widget/SearchView.java
index 5b5950d..10e1dfb 100644
--- a/core/java/android/widget/SearchView.java
+++ b/core/java/android/widget/SearchView.java
@@ -36,6 +36,7 @@
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -1292,7 +1293,7 @@
         mSearchSrcTextView.dismissDropDown();
     }
 
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private void onCloseClicked() {
         CharSequence text = mSearchSrcTextView.getText();
         if (TextUtils.isEmpty(text)) {
@@ -1590,7 +1591,7 @@
     /**
      * Sets the text in the query box, without updating the suggestions.
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private void setQuery(CharSequence query) {
         mSearchSrcTextView.setText(query, true);
         // Move the cursor to the end
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 31b1d99..a86e6f8 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -63,6 +63,7 @@
 import android.graphics.RectF;
 import android.graphics.Typeface;
 import android.graphics.drawable.Drawable;
+import android.graphics.fonts.Font;
 import android.graphics.fonts.FontVariationAxis;
 import android.icu.text.DecimalFormatSymbols;
 import android.os.AsyncTask;
@@ -312,6 +313,7 @@
  * @attr ref android.R.styleable#TextView_fallbackLineSpacing
  * @attr ref android.R.styleable#TextView_letterSpacing
  * @attr ref android.R.styleable#TextView_fontFeatureSettings
+ * @attr ref android.R.styleable#TextView_fontVariationSettings
  * @attr ref android.R.styleable#TextView_breakStrategy
  * @attr ref android.R.styleable#TextView_hyphenationFrequency
  * @attr ref android.R.styleable#TextView_autoSizeTextType
@@ -2068,7 +2070,7 @@
      */
     private void setTypefaceFromAttrs(@Nullable Typeface typeface, @Nullable String familyName,
             @XMLTypefaceAttr int typefaceIndex, @Typeface.Style int style,
-            @IntRange(from = -1, to = Typeface.MAX_WEIGHT) int weight) {
+            @IntRange(from = -1, to = Font.FONT_WEIGHT_MAX) int weight) {
         if (typeface == null && familyName != null) {
             // Lookup normal Typeface from system font map.
             final Typeface normalTypeface = Typeface.create(familyName, Typeface.NORMAL);
@@ -2095,9 +2097,9 @@
     }
 
     private void resolveStyleAndSetTypeface(@NonNull Typeface typeface, @Typeface.Style int style,
-            @IntRange(from = -1, to = Typeface.MAX_WEIGHT) int weight) {
+            @IntRange(from = -1, to = Font.FONT_WEIGHT_MAX) int weight) {
         if (weight >= 0) {
-            weight = Math.min(Typeface.MAX_WEIGHT, weight);
+            weight = Math.min(Font.FONT_WEIGHT_MAX, weight);
             final boolean italic = (style & Typeface.ITALIC) != 0;
             setTypeface(Typeface.create(typeface, weight, italic));
         } else {
@@ -3528,6 +3530,7 @@
         boolean mHasLetterSpacing = false;
         float mLetterSpacing = 0;
         String mFontFeatureSettings = null;
+        String mFontVariationSettings = null;
 
         @Override
         public String toString() {
@@ -3555,6 +3558,7 @@
                     + "    mHasLetterSpacing:" + mHasLetterSpacing + "\n"
                     + "    mLetterSpacing:" + mLetterSpacing + "\n"
                     + "    mFontFeatureSettings:" + mFontFeatureSettings + "\n"
+                    + "    mFontVariationSettings:" + mFontVariationSettings + "\n"
                     + "}";
         }
     }
@@ -3598,12 +3602,14 @@
                 com.android.internal.R.styleable.TextAppearance_letterSpacing);
         sAppearanceValues.put(com.android.internal.R.styleable.TextView_fontFeatureSettings,
                 com.android.internal.R.styleable.TextAppearance_fontFeatureSettings);
+        sAppearanceValues.put(com.android.internal.R.styleable.TextView_fontVariationSettings,
+                com.android.internal.R.styleable.TextAppearance_fontVariationSettings);
     }
 
     /**
      * Read the Text Appearance attributes from a given TypedArray and set its values to the given
      * set. If the TypedArray contains a value that was already set in the given attributes, that
-     * will be overriden.
+     * will be overridden.
      *
      * @param context The Context to be used
      * @param appearance The TypedArray to read properties from
@@ -3700,6 +3706,9 @@
                 case com.android.internal.R.styleable.TextAppearance_fontFeatureSettings:
                     attributes.mFontFeatureSettings = appearance.getString(attr);
                     break;
+                case com.android.internal.R.styleable.TextAppearance_fontVariationSettings:
+                    attributes.mFontVariationSettings = appearance.getString(attr);
+                    break;
                 default:
             }
         }
@@ -3756,6 +3765,10 @@
         if (attributes.mFontFeatureSettings != null) {
             setFontFeatureSettings(attributes.mFontFeatureSettings);
         }
+
+        if (attributes.mFontVariationSettings != null) {
+            setFontVariationSettings(attributes.mFontVariationSettings);
+        }
     }
 
     /**
@@ -4370,6 +4383,8 @@
      *
      * @see #getFontVariationSettings()
      * @see FontVariationAxis
+     *
+     * @attr ref android.R.styleable#TextView_fontVariationSettings
      */
     public boolean setFontVariationSettings(@Nullable String fontVariationSettings) {
         final String existingSettings = mTextPaint.getFontVariationSettings();
diff --git a/core/java/android/widget/Toast.java b/core/java/android/widget/Toast.java
index 3fbc819..10cf702 100644
--- a/core/java/android/widget/Toast.java
+++ b/core/java/android/widget/Toast.java
@@ -27,6 +27,7 @@
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.graphics.PixelFormat;
+import android.os.Build;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
@@ -443,7 +444,7 @@
          * schedule handleShow into the right thread
          */
         @Override
-        @UnsupportedAppUsage
+        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
         public void show(IBinder windowToken) {
             if (localLOGV) Log.v(TAG, "SHOW: " + this);
             mHandler.obtainMessage(SHOW, windowToken).sendToTarget();
diff --git a/core/java/android/widget/Toolbar.java b/core/java/android/widget/Toolbar.java
index 1bbd7e8..adb7f2f 100644
--- a/core/java/android/widget/Toolbar.java
+++ b/core/java/android/widget/Toolbar.java
@@ -29,6 +29,7 @@
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.graphics.drawable.Drawable;
+import android.os.Build;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.text.Layout;
@@ -137,7 +138,7 @@
     @UnsupportedAppUsage
     private TextView mTitleTextView;
     private TextView mSubtitleTextView;
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private ImageButton mNavButtonView;
     private ImageView mLogoView;
 
diff --git a/core/java/android/widget/VideoView.java b/core/java/android/widget/VideoView.java
index 14881eb..8b45d99 100644
--- a/core/java/android/widget/VideoView.java
+++ b/core/java/android/widget/VideoView.java
@@ -38,6 +38,7 @@
 import android.media.TtmlRenderer;
 import android.media.WebVttRenderer;
 import android.net.Uri;
+import android.os.Build;
 import android.os.Looper;
 import android.util.AttributeSet;
 import android.util.Log;
@@ -85,7 +86,7 @@
 
     // all possible internal states
     private static final int STATE_ERROR = -1;
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private static final int STATE_IDLE = 0;
     private static final int STATE_PREPARING = 1;
     private static final int STATE_PREPARED = 2;
diff --git a/core/java/com/android/internal/app/ColorDisplayController.java b/core/java/com/android/internal/app/ColorDisplayController.java
index ba6cf26..7515180 100644
--- a/core/java/com/android/internal/app/ColorDisplayController.java
+++ b/core/java/com/android/internal/app/ColorDisplayController.java
@@ -112,8 +112,8 @@
 
     private final Context mContext;
     private final int mUserId;
-    private final ContentObserver mContentObserver;
 
+    private ContentObserver mContentObserver;
     private Callback mCallback;
     private MetricsLogger mMetricsLogger;
 
@@ -124,18 +124,6 @@
     public ColorDisplayController(@NonNull Context context, int userId) {
         mContext = context.getApplicationContext();
         mUserId = userId;
-
-        mContentObserver = new ContentObserver(new Handler(Looper.getMainLooper())) {
-            @Override
-            public void onChange(boolean selfChange, Uri uri) {
-                super.onChange(selfChange, uri);
-
-                final String setting = uri == null ? null : uri.getLastPathSegment();
-                if (setting != null) {
-                    onSettingChanged(setting);
-                }
-            }
-        };
     }
 
     /**
@@ -522,6 +510,20 @@
         if (oldCallback != callback) {
             mCallback = callback;
 
+            if (mContentObserver == null) {
+                mContentObserver = new ContentObserver(new Handler(Looper.getMainLooper())) {
+                    @Override
+                    public void onChange(boolean selfChange, Uri uri) {
+                        super.onChange(selfChange, uri);
+
+                        final String setting = uri == null ? null : uri.getLastPathSegment();
+                        if (setting != null) {
+                            onSettingChanged(setting);
+                        }
+                    }
+                };
+            }
+
             if (callback == null) {
                 // Stop listening for changes now that there IS NOT a listener.
                 mContext.getContentResolver().unregisterContentObserver(mContentObserver);
diff --git a/core/java/com/android/internal/app/procstats/AssociationState.java b/core/java/com/android/internal/app/procstats/AssociationState.java
index 115ba18..3842f66 100644
--- a/core/java/com/android/internal/app/procstats/AssociationState.java
+++ b/core/java/com/android/internal/app/procstats/AssociationState.java
@@ -20,8 +20,8 @@
 import android.os.Parcel;
 import android.os.SystemClock;
 import android.os.UserHandle;
-import android.service.procstats.ProcessStatsAssociationStateProto;
-import android.service.procstats.ProcessStatsStateProto;
+import android.service.procstats.PackageAssociationProcessStatsProto;
+import android.service.procstats.PackageAssociationSourceProcessStatsProto;
 import android.util.ArrayMap;
 import android.util.Slog;
 import android.util.TimeUtils;
@@ -662,22 +662,23 @@
     public void writeToProto(ProtoOutputStream proto, long fieldId, long now) {
         final long token = proto.start(fieldId);
 
-        proto.write(ProcessStatsAssociationStateProto.COMPONENT_NAME, mName);
+        proto.write(PackageAssociationProcessStatsProto.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);
+            final long sourceToken = proto.start(PackageAssociationProcessStatsProto.SOURCES);
+            proto.write(PackageAssociationSourceProcessStatsProto.PROCESS_NAME, key.mProcess);
+            proto.write(PackageAssociationSourceProcessStatsProto.PROCESS_UID, key.mUid);
+            proto.write(PackageAssociationSourceProcessStatsProto.TOTAL_COUNT, src.mCount);
             long duration = src.mDuration;
             if (src.mNesting > 0) {
                 duration += now - src.mStartUptime;
             }
-            proto.write(ProcessStatsAssociationStateProto.Source.TOTAL_DURATION_MS, duration);
+            proto.write(PackageAssociationSourceProcessStatsProto.TOTAL_DURATION_MS, duration);
             if (src.mActiveCount != 0) {
-                proto.write(ProcessStatsAssociationStateProto.Source.ACTIVE_COUNT,
+                proto.write(PackageAssociationSourceProcessStatsProto.ACTIVE_COUNT,
                         src.mActiveCount);
             }
             final long timeNow = src.mActiveStartUptime != 0 ? (now-src.mActiveStartUptime) : 0;
@@ -690,16 +691,26 @@
                         duration += timeNow;
                     }
                     final int procState = SparseMappingTable.getIdFromKey(dkey);
-                    DumpUtils.printProcStateDurationProto(proto,
-                            ProcessStatsAssociationStateProto.Source.ACTIVE_STATES,
-                            procState, duration);
+                    final long stateToken = proto.start(
+                            PackageAssociationSourceProcessStatsProto.ACTIVE_STATE_STATS);
+                    DumpUtils.printProto(proto,
+                            PackageAssociationSourceProcessStatsProto.StateStats.PROCESS_STATE,
+                            DumpUtils.STATE_PROTO_ENUMS, procState, 1);
+                    proto.write(PackageAssociationSourceProcessStatsProto.StateStats.DURATION_MS,
+                            duration);
+                    proto.end(stateToken);
                 }
             } else {
                 duration = src.mActiveDuration + timeNow;
                 if (duration != 0) {
-                    DumpUtils.printProcStateDurationProto(proto,
-                            ProcessStatsAssociationStateProto.Source.ACTIVE_STATES,
-                            src.mActiveProcState, duration);
+                    final long stateToken = proto.start(
+                            PackageAssociationSourceProcessStatsProto.ACTIVE_STATE_STATS);
+                    DumpUtils.printProto(proto,
+                            PackageAssociationSourceProcessStatsProto.StateStats.PROCESS_STATE,
+                            DumpUtils.STATE_PROTO_ENUMS, src.mActiveProcState, 1);
+                    proto.write(PackageAssociationSourceProcessStatsProto.StateStats.DURATION_MS,
+                            duration);
+                    proto.end(stateToken);
                 }
             }
             proto.end(sourceToken);
diff --git a/core/java/com/android/internal/app/procstats/DumpUtils.java b/core/java/com/android/internal/app/procstats/DumpUtils.java
index 701391d..eda04a6 100644
--- a/core/java/com/android/internal/app/procstats/DumpUtils.java
+++ b/core/java/com/android/internal/app/procstats/DumpUtils.java
@@ -17,6 +17,7 @@
 package com.android.internal.app.procstats;
 
 import android.os.UserHandle;
+import android.service.procstats.ProcessStatsEnums;
 import android.service.procstats.ProcessStatsStateProto;
 import android.util.TimeUtils;
 import android.util.proto.ProtoOutputStream;
@@ -107,20 +108,24 @@
         STATE_TAGS[STATE_CACHED_EMPTY]              = "e";
 
         STATE_PROTO_ENUMS = new int[STATE_COUNT];
-        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;
+        STATE_PROTO_ENUMS[STATE_PERSISTENT] = ProcessStatsEnums.PROCESS_STATE_PERSISTENT;
+        STATE_PROTO_ENUMS[STATE_TOP] = ProcessStatsEnums.PROCESS_STATE_TOP;
+        STATE_PROTO_ENUMS[STATE_IMPORTANT_FOREGROUND] =
+                ProcessStatsEnums.PROCESS_STATE_IMPORTANT_FOREGROUND;
+        STATE_PROTO_ENUMS[STATE_IMPORTANT_BACKGROUND] =
+                ProcessStatsEnums.PROCESS_STATE_IMPORTANT_BACKGROUND;
+        STATE_PROTO_ENUMS[STATE_BACKUP] = ProcessStatsEnums.PROCESS_STATE_BACKUP;
+        STATE_PROTO_ENUMS[STATE_SERVICE] = ProcessStatsEnums.PROCESS_STATE_SERVICE;
+        STATE_PROTO_ENUMS[STATE_SERVICE_RESTARTING] =
+                ProcessStatsEnums.PROCESS_STATE_SERVICE_RESTARTING;
+        STATE_PROTO_ENUMS[STATE_RECEIVER] = ProcessStatsEnums.PROCESS_STATE_RECEIVER;
+        STATE_PROTO_ENUMS[STATE_HEAVY_WEIGHT] = ProcessStatsEnums.PROCESS_STATE_HEAVY_WEIGHT;
+        STATE_PROTO_ENUMS[STATE_HOME] = ProcessStatsEnums.PROCESS_STATE_HOME;
+        STATE_PROTO_ENUMS[STATE_LAST_ACTIVITY] = ProcessStatsEnums.PROCESS_STATE_LAST_ACTIVITY;
+        STATE_PROTO_ENUMS[STATE_CACHED_ACTIVITY] = ProcessStatsEnums.PROCESS_STATE_CACHED_ACTIVITY;
+        STATE_PROTO_ENUMS[STATE_CACHED_ACTIVITY_CLIENT] =
+                ProcessStatsEnums.PROCESS_STATE_CACHED_ACTIVITY_CLIENT;
+        STATE_PROTO_ENUMS[STATE_CACHED_EMPTY] = ProcessStatsEnums.PROCESS_STATE_CACHED_EMPTY;
     }
 
     public static final String[] ADJ_SCREEN_NAMES_CSV = new String[] {
@@ -138,8 +143,8 @@
     };
 
     static final int[] ADJ_SCREEN_PROTO_ENUMS = new int[] {
-            ProcessStatsStateProto.OFF,
-            ProcessStatsStateProto.ON
+            ProcessStatsEnums.SCREEN_STATE_OFF,
+            ProcessStatsEnums.SCREEN_STATE_ON
     };
 
     static final String[] ADJ_MEM_TAGS = new String[] {
@@ -147,10 +152,10 @@
     };
 
     static final int[] ADJ_MEM_PROTO_ENUMS = new int[] {
-            ProcessStatsStateProto.NORMAL,
-            ProcessStatsStateProto.MODERATE,
-            ProcessStatsStateProto.LOW,
-            ProcessStatsStateProto.CRITICAL
+            ProcessStatsEnums.MEMORY_STATE_NORMAL,
+            ProcessStatsEnums.MEMORY_STATE_MODERATE,
+            ProcessStatsEnums.MEMORY_STATE_LOW,
+            ProcessStatsEnums.MEMORY_STATE_CRITICAL
     };
 
     static final String CSV_SEP = "\t";
@@ -278,7 +283,6 @@
                 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) {
diff --git a/core/java/com/android/internal/app/procstats/ProcessState.java b/core/java/com/android/internal/app/procstats/ProcessState.java
index d7f4736..4071c82 100644
--- a/core/java/com/android/internal/app/procstats/ProcessState.java
+++ b/core/java/com/android/internal/app/procstats/ProcessState.java
@@ -31,36 +31,38 @@
 import android.util.proto.ProtoOutputStream;
 import android.util.proto.ProtoUtils;
 
-import com.android.internal.app.procstats.ProcessStats.PackageState;
-import com.android.internal.app.procstats.ProcessStats.ProcessStateHolder;
-import com.android.internal.app.procstats.ProcessStats.TotalMemoryUseCollection;
-import static com.android.internal.app.procstats.ProcessStats.PSS_SAMPLE_COUNT;
-import static com.android.internal.app.procstats.ProcessStats.PSS_MINIMUM;
+
 import static com.android.internal.app.procstats.ProcessStats.PSS_AVERAGE;
+import static com.android.internal.app.procstats.ProcessStats.PSS_COUNT;
 import static com.android.internal.app.procstats.ProcessStats.PSS_MAXIMUM;
-import static com.android.internal.app.procstats.ProcessStats.PSS_RSS_MINIMUM;
+import static com.android.internal.app.procstats.ProcessStats.PSS_MINIMUM;
 import static com.android.internal.app.procstats.ProcessStats.PSS_RSS_AVERAGE;
 import static com.android.internal.app.procstats.ProcessStats.PSS_RSS_MAXIMUM;
-import static com.android.internal.app.procstats.ProcessStats.PSS_USS_MINIMUM;
+import static com.android.internal.app.procstats.ProcessStats.PSS_RSS_MINIMUM;
+import static com.android.internal.app.procstats.ProcessStats.PSS_SAMPLE_COUNT;
 import static com.android.internal.app.procstats.ProcessStats.PSS_USS_AVERAGE;
 import static com.android.internal.app.procstats.ProcessStats.PSS_USS_MAXIMUM;
-import static com.android.internal.app.procstats.ProcessStats.PSS_COUNT;
-import static com.android.internal.app.procstats.ProcessStats.STATE_NOTHING;
-import static com.android.internal.app.procstats.ProcessStats.STATE_PERSISTENT;
-import static com.android.internal.app.procstats.ProcessStats.STATE_TOP;
-import static com.android.internal.app.procstats.ProcessStats.STATE_IMPORTANT_FOREGROUND;
-import static com.android.internal.app.procstats.ProcessStats.STATE_IMPORTANT_BACKGROUND;
+import static com.android.internal.app.procstats.ProcessStats.PSS_USS_MINIMUM;
 import static com.android.internal.app.procstats.ProcessStats.STATE_BACKUP;
-import static com.android.internal.app.procstats.ProcessStats.STATE_HEAVY_WEIGHT;
-import static com.android.internal.app.procstats.ProcessStats.STATE_SERVICE;
-import static com.android.internal.app.procstats.ProcessStats.STATE_SERVICE_RESTARTING;
-import static com.android.internal.app.procstats.ProcessStats.STATE_RECEIVER;
-import static com.android.internal.app.procstats.ProcessStats.STATE_HOME;
-import static com.android.internal.app.procstats.ProcessStats.STATE_LAST_ACTIVITY;
 import static com.android.internal.app.procstats.ProcessStats.STATE_CACHED_ACTIVITY;
 import static com.android.internal.app.procstats.ProcessStats.STATE_CACHED_ACTIVITY_CLIENT;
 import static com.android.internal.app.procstats.ProcessStats.STATE_CACHED_EMPTY;
 import static com.android.internal.app.procstats.ProcessStats.STATE_COUNT;
+import static com.android.internal.app.procstats.ProcessStats.STATE_HEAVY_WEIGHT;
+import static com.android.internal.app.procstats.ProcessStats.STATE_HOME;
+import static com.android.internal.app.procstats.ProcessStats.STATE_IMPORTANT_BACKGROUND;
+import static com.android.internal.app.procstats.ProcessStats.STATE_IMPORTANT_FOREGROUND;
+import static com.android.internal.app.procstats.ProcessStats.STATE_LAST_ACTIVITY;
+import static com.android.internal.app.procstats.ProcessStats.STATE_NOTHING;
+import static com.android.internal.app.procstats.ProcessStats.STATE_PERSISTENT;
+import static com.android.internal.app.procstats.ProcessStats.STATE_RECEIVER;
+import static com.android.internal.app.procstats.ProcessStats.STATE_SERVICE;
+import static com.android.internal.app.procstats.ProcessStats.STATE_SERVICE_RESTARTING;
+import static com.android.internal.app.procstats.ProcessStats.STATE_TOP;
+
+import com.android.internal.app.procstats.ProcessStats.PackageState;
+import com.android.internal.app.procstats.ProcessStats.ProcessStateHolder;
+import com.android.internal.app.procstats.ProcessStats.TotalMemoryUseCollection;
 
 import java.io.PrintWriter;
 import java.util.Comparator;
diff --git a/core/java/com/android/internal/app/procstats/ProcessStats.java b/core/java/com/android/internal/app/procstats/ProcessStats.java
index b6624a2..f6e99ba 100644
--- a/core/java/com/android/internal/app/procstats/ProcessStats.java
+++ b/core/java/com/android/internal/app/procstats/ProcessStats.java
@@ -2126,12 +2126,14 @@
 
             for (int is = 0; is < mServices.size(); is++) {
                 final ServiceState serviceState = mServices.valueAt(is);
-                serviceState.writeToProto(proto, ProcessStatsPackageProto.PROCESS_STATS, now);
+                serviceState.writeToProto(proto, ProcessStatsPackageProto.SERVICE_STATS,
+                        now);
             }
 
             for (int ia=0; ia<mAssociations.size(); ia++) {
                 final AssociationState ascState = mAssociations.valueAt(ia);
-                ascState.writeToProto(proto, ProcessStatsPackageProto.ASSOCIATION_STATS, now);
+                ascState.writeToProto(proto, ProcessStatsPackageProto.ASSOCIATION_STATS,
+                        now);
             }
 
             proto.end(token);
diff --git a/core/java/com/android/internal/app/procstats/ServiceState.java b/core/java/com/android/internal/app/procstats/ServiceState.java
index 16975a4..72077c4 100644
--- a/core/java/com/android/internal/app/procstats/ServiceState.java
+++ b/core/java/com/android/internal/app/procstats/ServiceState.java
@@ -19,16 +19,13 @@
 
 import android.os.Parcel;
 import android.os.SystemClock;
-import android.service.procstats.ProcessStatsProto;
-import android.service.procstats.ProcessStatsServiceStateProto;
-import android.service.procstats.ProcessStatsStateProto;
+import android.service.procstats.PackageServiceOperationStatsProto;
+import android.service.procstats.PackageServiceStatsProto;
+import android.service.procstats.ProcessStatsEnums;
 import android.util.Slog;
-import android.util.SparseLongArray;
 import android.util.TimeUtils;
 import android.util.proto.ProtoOutputStream;
-import android.util.proto.ProtoUtils;
 
-import static com.android.internal.app.procstats.ProcessStats.PSS_SAMPLE_COUNT;
 import static com.android.internal.app.procstats.ProcessStats.STATE_NOTHING;
 
 import java.io.PrintWriter;
@@ -559,29 +556,45 @@
 
     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,
+        proto.write(PackageServiceStatsProto.SERVICE_NAME, mName);
+
+        writeTypeToProto(proto, PackageServiceStatsProto.OPERATION_STATS,
+                ProcessStatsEnums.SERVICE_OPERATION_STATE_RUNNING,
                 ServiceState.SERVICE_RUN, mRunCount, mRunState, mRunStartTime, now);
-        writeTypeToProto(proto, ProcessStatsServiceStateProto.STARTED_OP,
+
+        writeTypeToProto(proto, PackageServiceStatsProto.OPERATION_STATS,
+                ProcessStatsEnums.SERVICE_OPERATION_STATE_STARTED,
                 ServiceState.SERVICE_STARTED, mStartedCount, mStartedState, mStartedStartTime, now);
-        writeTypeToProto(proto, ProcessStatsServiceStateProto.FOREGROUND_OP,
+
+        writeTypeToProto(proto, PackageServiceStatsProto.OPERATION_STATS,
+                ProcessStatsEnums.SERVICE_OPERATION_STATE_FOREGROUND,
                 ServiceState.SERVICE_FOREGROUND, mForegroundCount, mForegroundState,
                 mForegroundStartTime, now);
-        writeTypeToProto(proto, ProcessStatsServiceStateProto.BOUND_OP,
+
+        writeTypeToProto(proto, PackageServiceStatsProto.OPERATION_STATS,
+                ProcessStatsEnums.SERVICE_OPERATION_STATE_BOUND,
                 ServiceState.SERVICE_BOUND, mBoundCount, mBoundState, mBoundStartTime, now);
-        writeTypeToProto(proto, ProcessStatsServiceStateProto.EXECUTING_OP,
+
+        writeTypeToProto(proto, PackageServiceStatsProto.OPERATION_STATS,
+                ProcessStatsEnums.SERVICE_OPERATION_STATE_EXECUTING,
                 ServiceState.SERVICE_EXEC, mExecCount, mExecState, mExecStartTime, now);
+
         proto.end(token);
     }
 
-    public void writeTypeToProto(ProtoOutputStream proto, long fieldId, int serviceType,
+    /**
+     * write the metrics to proto for each operation type.
+     */
+    public void writeTypeToProto(ProtoOutputStream proto, long fieldId, int opType, 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);
+        proto.write(PackageServiceOperationStatsProto.OPERATION, opType);
+        proto.write(PackageServiceOperationStatsProto.COUNT, opCount);
+
         boolean didCurState = false;
         final int N = mDurations.getKeyCount();
         for (int i=0; i<N; i++) {
@@ -597,21 +610,22 @@
                 didCurState = true;
                 time += now - curStartTime;
             }
-            final long stateToken = proto.start(ProcessStatsServiceStateProto.OperationInfo.STATES);
+            final long stateToken = proto.start(PackageServiceOperationStatsProto.STATE_STATS);
             DumpUtils.printProcStateAdjTagProto(proto,
-                    ProcessStatsStateProto.SCREEN_STATE,
-                    ProcessStatsStateProto.MEMORY_STATE,
+                    PackageServiceOperationStatsProto.StateStats.SCREEN_STATE,
+                    PackageServiceOperationStatsProto.StateStats.MEMORY_STATE,
                     type);
-            proto.write(ProcessStatsStateProto.DURATION_MS, time);
+            proto.write(PackageServiceOperationStatsProto.StateStats.DURATION_MS, time);
             proto.end(stateToken);
         }
         if (!didCurState && curState != STATE_NOTHING) {
-            final long stateToken = proto.start(ProcessStatsServiceStateProto.OperationInfo.STATES);
+            final long stateToken = proto.start(PackageServiceOperationStatsProto.STATE_STATS);
             DumpUtils.printProcStateAdjTagProto(proto,
-                    ProcessStatsStateProto.SCREEN_STATE,
-                    ProcessStatsStateProto.MEMORY_STATE,
+                    PackageServiceOperationStatsProto.StateStats.SCREEN_STATE,
+                    PackageServiceOperationStatsProto.StateStats.MEMORY_STATE,
                     curState);
-            proto.write(ProcessStatsStateProto.DURATION_MS, now - curStartTime);
+            proto.write(PackageServiceOperationStatsProto.StateStats.DURATION_MS,
+                    now - curStartTime);
             proto.end(stateToken);
         }
 
diff --git a/core/java/com/android/internal/colorextraction/types/Tonal.java b/core/java/com/android/internal/colorextraction/types/Tonal.java
index 7b25a06..3fd88db 100644
--- a/core/java/com/android/internal/colorextraction/types/Tonal.java
+++ b/core/java/com/android/internal/colorextraction/types/Tonal.java
@@ -51,10 +51,8 @@
 
     private static final boolean DEBUG = true;
 
-    public static final int THRESHOLD_COLOR_LIGHT = 0xffe0e0e0;
     public static final int MAIN_COLOR_LIGHT = 0xffe0e0e0;
-    public static final int THRESHOLD_COLOR_DARK = 0xff212121;
-    public static final int MAIN_COLOR_DARK = 0xff000000;
+    public static final int MAIN_COLOR_DARK = 0xff212121;
 
     private final TonalPalette mGreyPalette;
     private final ArrayList<TonalPalette> mTonalPalettes;
@@ -197,12 +195,12 @@
         // light fallback or darker than our dark fallback.
         ColorUtils.colorToHSL(mainColor, mTmpHSL);
         final float mainLuminosity = mTmpHSL[2];
-        ColorUtils.colorToHSL(THRESHOLD_COLOR_LIGHT, mTmpHSL);
+        ColorUtils.colorToHSL(MAIN_COLOR_LIGHT, mTmpHSL);
         final float lightLuminosity = mTmpHSL[2];
         if (mainLuminosity > lightLuminosity) {
             return false;
         }
-        ColorUtils.colorToHSL(THRESHOLD_COLOR_DARK, mTmpHSL);
+        ColorUtils.colorToHSL(MAIN_COLOR_DARK, mTmpHSL);
         final float darkLuminosity = mTmpHSL[2];
         if (mainLuminosity < darkLuminosity) {
             return false;
diff --git a/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java b/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java
index 8728367..cb282b6 100644
--- a/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java
+++ b/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java
@@ -75,6 +75,15 @@
         return !TextUtils.isEmpty(reachSensorType());
     }
 
+    public boolean wakeScreenGestureEnabled(int user) {
+        return boolSettingDefaultOn(Settings.Secure.DOZE_WAKE_SCREEN_GESTURE, user)
+                && wakeScreenGestureAvailable();
+    }
+
+    public boolean wakeScreenGestureAvailable() {
+        return !TextUtils.isEmpty(wakeScreenSensorType());
+    }
+
     public String doubleTapSensorType() {
         return mContext.getResources().getString(R.string.config_dozeDoubleTapSensorType);
     }
@@ -87,6 +96,10 @@
         return mContext.getResources().getString(R.string.config_dozeReachSensorType);
     }
 
+    public String wakeScreenSensorType() {
+        return mContext.getResources().getString(R.string.config_dozeWakeScreenSensorType);
+    }
+
     public boolean pulseOnLongPressEnabled(int user) {
         return pulseOnLongPressAvailable() && boolSettingDefaultOff(
                 Settings.Secure.DOZE_PULSE_ON_LONG_PRESS, user);
diff --git a/core/java/com/android/internal/inputmethod/IInputMethodPrivilegedOperations.aidl b/core/java/com/android/internal/inputmethod/IInputMethodPrivilegedOperations.aidl
new file mode 100644
index 0000000..c32894d
--- /dev/null
+++ b/core/java/com/android/internal/inputmethod/IInputMethodPrivilegedOperations.aidl
@@ -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.internal.inputmethod;
+
+import android.net.Uri;
+import android.view.inputmethod.InputMethodSubtype;
+
+import com.android.internal.inputmethod.IInputContentUriToken;
+
+/**
+ * Defines priviledged operations that only the current IME is allowed to call.
+ * Actual operations are implemented and handled by InputMethodManagerService.
+ */
+interface IInputMethodPrivilegedOperations {
+    void setImeWindowStatus(int vis, int backDisposition);
+    void reportStartInput(in IBinder startInputToken);
+    void clearLastInputMethodWindowForTransition();
+    IInputContentUriToken createInputContentUriToken(in Uri contentUri, in String packageName);
+    void reportFullscreenMode(boolean fullscreen);
+    void setInputMethod(String id);
+    void setInputMethodAndSubtype(String id, in InputMethodSubtype subtype);
+    void hideMySoftInput(int flags);
+    void showMySoftInput(int flags);
+    void updateStatusIcon(String packageName, int iconId);
+    boolean switchToPreviousInputMethod();
+    boolean switchToNextInputMethod(boolean onlyCurrentIme);
+    boolean shouldOfferSwitchingToNextInputMethod();
+
+    oneway void notifyUserActionAsync();
+}
diff --git a/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java b/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java
new file mode 100644
index 0000000..f0e8dc5
--- /dev/null
+++ b/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java
@@ -0,0 +1,365 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.inputmethod;
+
+import android.annotation.AnyThread;
+import android.annotation.DrawableRes;
+import android.annotation.Nullable;
+import android.net.Uri;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Log;
+import android.view.inputmethod.InputMethodSubtype;
+
+import com.android.internal.annotations.GuardedBy;
+
+/**
+ * A utility class to take care of boilerplate code around IPCs.
+ */
+public final class InputMethodPrivilegedOperations {
+    private static final String TAG = "InputMethodPrivilegedOperations";
+
+    private static final class OpsHolder {
+        @Nullable
+        @GuardedBy("this")
+        private IInputMethodPrivilegedOperations mPrivOps;
+
+        /**
+         * Sets {@link IInputMethodPrivilegedOperations}.
+         *
+         * <p>This method can be called only once.</p>
+         *
+         * @param privOps Binder interface to be set
+         */
+        @AnyThread
+        public synchronized void set(IInputMethodPrivilegedOperations privOps) {
+            if (mPrivOps != null) {
+                throw new IllegalStateException(
+                        "IInputMethodPrivilegedOperations must be set at most once."
+                                + " privOps=" + privOps);
+            }
+            mPrivOps = privOps;
+        }
+
+        /**
+         * A simplified version of {@link android.os.Debug#getCaller()}.
+         *
+         * @return method name of the caller.
+         */
+        @AnyThread
+        private static String getCallerMethodName() {
+            final StackTraceElement[] callStack = Thread.currentThread().getStackTrace();
+            if (callStack.length <= 4) {
+                return "<bottom of call stack>";
+            }
+            return callStack[4].getMethodName();
+        }
+
+        @AnyThread
+        @Nullable
+        public synchronized IInputMethodPrivilegedOperations getAndWarnIfNull() {
+            if (mPrivOps == null) {
+                Log.e(TAG, getCallerMethodName() + " is ignored."
+                        + " Call it within attachToken() and InputMethodService.onDestroy()");
+            }
+            return mPrivOps;
+        }
+    }
+    private final OpsHolder mOps = new OpsHolder();
+
+    /**
+     * Sets {@link IInputMethodPrivilegedOperations}.
+     *
+     * <p>This method can be called only once.</p>
+     *
+     * @param privOps Binder interface to be set
+     */
+    @AnyThread
+    public void set(IInputMethodPrivilegedOperations privOps) {
+        mOps.set(privOps);
+    }
+
+    /**
+     * Calls {@link IInputMethodPrivilegedOperations#setImeWindowStatus(int, int)}.
+     *
+     * @param vis visibility flags
+     * @param backDisposition disposition flags
+     * @see android.inputmethodservice.InputMethodService#IME_ACTIVE
+     * @see android.inputmethodservice.InputMethodService#IME_VISIBLE
+     * @see android.inputmethodservice.InputMethodService#BACK_DISPOSITION_DEFAULT
+     * @see android.inputmethodservice.InputMethodService#BACK_DISPOSITION_ADJUST_NOTHING
+     */
+    @AnyThread
+    public void setImeWindowStatus(int vis, int backDisposition) {
+        final IInputMethodPrivilegedOperations ops = mOps.getAndWarnIfNull();
+        if (ops == null) {
+            return;
+        }
+        try {
+            ops.setImeWindowStatus(vis, backDisposition);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Calls {@link IInputMethodPrivilegedOperations#reportStartInput(IBinder)}.
+     *
+     * @param startInputToken {@link IBinder} token to distinguish startInput session
+     */
+    @AnyThread
+    public void reportStartInput(IBinder startInputToken) {
+        final IInputMethodPrivilegedOperations ops = mOps.getAndWarnIfNull();
+        if (ops == null) {
+            return;
+        }
+        try {
+            ops.reportStartInput(startInputToken);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Calls {@link IInputMethodPrivilegedOperations#clearLastInputMethodWindowForTransition()}.
+     */
+    @AnyThread
+    public void clearLastInputMethodWindowForTransition() {
+        final IInputMethodPrivilegedOperations ops = mOps.getAndWarnIfNull();
+        if (ops == null) {
+            return;
+        }
+        try {
+            ops.clearLastInputMethodWindowForTransition();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Calls {@link IInputMethodPrivilegedOperations#createInputContentUriToken(Uri, String)}.
+     *
+     * @param contentUri Content URI to which a temporary read permission should be granted
+     * @param packageName Indicates what package needs to have a temporary read permission
+     * @return special Binder token that should be set to
+     *         {@link android.view.inputmethod.InputContentInfo#setUriToken(IInputContentUriToken)}
+     */
+    @AnyThread
+    public IInputContentUriToken createInputContentUriToken(Uri contentUri, String packageName) {
+        final IInputMethodPrivilegedOperations ops = mOps.getAndWarnIfNull();
+        if (ops == null) {
+            return null;
+        }
+        try {
+            return ops.createInputContentUriToken(contentUri, packageName);
+        } catch (RemoteException e) {
+            // For historical reasons, this error was silently ignored.
+            // Note that the caller already logs error so we do not need additional Log.e() here.
+            // TODO(team): Check if it is safe to rethrow error here.
+            return null;
+        }
+    }
+
+    /**
+     * Calls {@link IInputMethodPrivilegedOperations#reportFullscreenMode(boolean)}.
+     *
+     * @param fullscreen {@code true} if the IME enters full screen mode
+     */
+    @AnyThread
+    public void reportFullscreenMode(boolean fullscreen) {
+        final IInputMethodPrivilegedOperations ops = mOps.getAndWarnIfNull();
+        if (ops == null) {
+            return;
+        }
+        try {
+            ops.reportFullscreenMode(fullscreen);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Calls {@link IInputMethodPrivilegedOperations#updateStatusIcon(String, int)}.
+     *
+     * @param packageName package name from which the status icon should be loaded
+     * @param iconResId resource ID of the icon to be loaded
+     */
+    @AnyThread
+    public void updateStatusIcon(String packageName, @DrawableRes int iconResId) {
+        final IInputMethodPrivilegedOperations ops = mOps.getAndWarnIfNull();
+        if (ops == null) {
+            return;
+        }
+        try {
+            ops.updateStatusIcon(packageName, iconResId);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Calls {@link IInputMethodPrivilegedOperations#setInputMethod(String)}.
+     *
+     * @param id IME ID of the IME to switch to
+     * @see android.view.inputmethod.InputMethodInfo#getId()
+     */
+    @AnyThread
+    public void setInputMethod(String id) {
+        final IInputMethodPrivilegedOperations ops = mOps.getAndWarnIfNull();
+        if (ops == null) {
+            return;
+        }
+        try {
+            ops.setInputMethod(id);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Calls {@link IInputMethodPrivilegedOperations#setInputMethodAndSubtype(String,
+     * InputMethodSubtype)}
+     *
+     * @param id IME ID of the IME to switch to
+     * @param subtype {@link InputMethodSubtype} to switch to
+     * @see android.view.inputmethod.InputMethodInfo#getId()
+     */
+    @AnyThread
+    public void setInputMethodAndSubtype(String id, InputMethodSubtype subtype) {
+        final IInputMethodPrivilegedOperations ops = mOps.getAndWarnIfNull();
+        if (ops == null) {
+            return;
+        }
+        try {
+            ops.setInputMethodAndSubtype(id, subtype);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Calls {@link IInputMethodPrivilegedOperations#hideMySoftInput(int)}
+     *
+     * @param flags additional operating flags
+     * @see android.view.inputmethod.InputMethodManager#HIDE_IMPLICIT_ONLY
+     * @see android.view.inputmethod.InputMethodManager#HIDE_NOT_ALWAYS
+     */
+    @AnyThread
+    public void hideMySoftInput(int flags) {
+        final IInputMethodPrivilegedOperations ops = mOps.getAndWarnIfNull();
+        if (ops == null) {
+            return;
+        }
+        try {
+            ops.hideMySoftInput(flags);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Calls {@link IInputMethodPrivilegedOperations#showMySoftInput(int)}
+     *
+     * @param flags additional operating flags
+     * @see android.view.inputmethod.InputMethodManager#SHOW_IMPLICIT
+     * @see android.view.inputmethod.InputMethodManager#SHOW_FORCED
+     */
+    @AnyThread
+    public void showMySoftInput(int flags) {
+        final IInputMethodPrivilegedOperations ops = mOps.getAndWarnIfNull();
+        if (ops == null) {
+            return;
+        }
+        try {
+            ops.showMySoftInput(flags);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Calls {@link IInputMethodPrivilegedOperations#switchToPreviousInputMethod()}
+     *
+     * @return {@code true} if handled
+     */
+    @AnyThread
+    public boolean switchToPreviousInputMethod() {
+        final IInputMethodPrivilegedOperations ops = mOps.getAndWarnIfNull();
+        if (ops == null) {
+            return false;
+        }
+        try {
+            return ops.switchToPreviousInputMethod();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Calls {@link IInputMethodPrivilegedOperations#switchToNextInputMethod(boolean)}
+     *
+     * @param onlyCurrentIme {@code true} to switch to a {@link InputMethodSubtype} within the same
+     *                       IME
+     * @return {@code true} if handled
+     */
+    @AnyThread
+    public boolean switchToNextInputMethod(boolean onlyCurrentIme) {
+        final IInputMethodPrivilegedOperations ops = mOps.getAndWarnIfNull();
+        if (ops == null) {
+            return false;
+        }
+        try {
+            return ops.switchToNextInputMethod(onlyCurrentIme);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Calls {@link IInputMethodPrivilegedOperations#shouldOfferSwitchingToNextInputMethod()}
+     *
+     * @return {@code true} if the IEM should offer a way to globally switch IME
+     */
+    @AnyThread
+    public boolean shouldOfferSwitchingToNextInputMethod() {
+        final IInputMethodPrivilegedOperations ops = mOps.getAndWarnIfNull();
+        if (ops == null) {
+            return false;
+        }
+        try {
+            return ops.shouldOfferSwitchingToNextInputMethod();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Calls {@link IInputMethodPrivilegedOperations#notifyUserActionAsync()}
+     */
+    @AnyThread
+    public void notifyUserActionAsync() {
+        final IInputMethodPrivilegedOperations ops = mOps.getAndWarnIfNull();
+        if (ops == null) {
+            return;
+        }
+        try {
+            ops.notifyUserActionAsync();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+}
diff --git a/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperationsRegistry.java b/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperationsRegistry.java
new file mode 100644
index 0000000..3255153
--- /dev/null
+++ b/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperationsRegistry.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.internal.inputmethod;
+
+import android.annotation.AnyThread;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.IBinder;
+
+import com.android.internal.annotations.GuardedBy;
+
+import java.lang.ref.WeakReference;
+import java.util.WeakHashMap;
+
+/**
+ * A weak-reference-based mapper from IME token to {@link InputMethodPrivilegedOperations} that is
+ * used only to support deprecated IME APIs in {@link android.view.inputmethod.InputMethodManager}.
+ */
+public final class InputMethodPrivilegedOperationsRegistry {
+    private final Object mLock = new Object();
+    @GuardedBy("mLock")
+    private final WeakHashMap<IBinder, WeakReference<InputMethodPrivilegedOperations>>
+            mRegistry = new WeakHashMap<>();
+
+    @Nullable
+    private static InputMethodPrivilegedOperations sNop;
+
+    @NonNull
+    @AnyThread
+    private static InputMethodPrivilegedOperations getNopOps() {
+        // Strict thread-safety is not necessary because temporarily creating multiple nop instance
+        // is basically harmless
+        if (sNop == null) {
+            sNop = new InputMethodPrivilegedOperations();
+        }
+        return sNop;
+    }
+
+    /**
+     * Put a new entry to the registry.
+     *
+     * <p>Note: {@link InputMethodPrivilegedOperationsRegistry} does not hold strong reference to
+     * {@code token} and {@code ops}.  The caller must be responsible for holding strong references
+     * to those objects, that is until {@link android.inputmethodservice.InputMethodService} is
+     * destroyed.</p>
+     *
+     * @param token IME token
+     * @param ops {@link InputMethodPrivilegedOperations} to be associated with the given IME token
+     */
+    @AnyThread
+    public void put(IBinder token, InputMethodPrivilegedOperations ops) {
+        synchronized (mLock) {
+            final WeakReference<InputMethodPrivilegedOperations> previousOps =
+                    mRegistry.put(token, new WeakReference<>(ops));
+            if (previousOps != null) {
+                throw new IllegalStateException(previousOps.get() + " is already registered for "
+                        + " this token=" + token + " newOps=" + ops);
+            }
+        }
+    }
+
+    /**
+     * Get a {@link InputMethodPrivilegedOperations} from the given IME token.  If it is not
+     * available, return a fake instance that does nothing except for showing warning messages.
+     *
+     * @param token IME token
+     * @return real {@link InputMethodPrivilegedOperations} object if {@code token} is still valid.
+     *         Otherwise a fake instance of {@link InputMethodPrivilegedOperations} hat does nothing
+     *         except for showing warning messages
+     */
+    @NonNull
+    @AnyThread
+    public InputMethodPrivilegedOperations get(IBinder token) {
+        synchronized (mLock) {
+            final WeakReference<InputMethodPrivilegedOperations> wrapperRef = mRegistry.get(token);
+            if (wrapperRef == null) {
+                return getNopOps();
+            }
+            final InputMethodPrivilegedOperations wrapper = wrapperRef.get();
+            if (wrapper == null) {
+                return getNopOps();
+            }
+            return wrapper;
+        }
+    }
+
+    /**
+     * Explicitly removes the specified entry.
+     *
+     * <p>Note: Calling this method is optional. In general, {@link WeakHashMap} and
+     * {@link WeakReference} guarantee that the entry will be removed after specified binder proxies
+     * are garbage collected.</p>
+     *
+     * @param token IME token to be removed.
+     */
+    @AnyThread
+    public void remove(IBinder token) {
+        synchronized (mLock) {
+            mRegistry.remove(token);
+        }
+    }
+}
diff --git a/core/java/com/android/internal/os/BinderCallsStats.java b/core/java/com/android/internal/os/BinderCallsStats.java
index 4aa30f6..c0c358d 100644
--- a/core/java/com/android/internal/os/BinderCallsStats.java
+++ b/core/java/com/android/internal/os/BinderCallsStats.java
@@ -16,16 +16,9 @@
 
 package com.android.internal.os;
 
+import android.annotation.NonNull;
 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;
@@ -37,7 +30,6 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.os.BinderInternal.CallSession;
-import com.android.server.LocalServices;
 
 import java.io.PrintWriter;
 import java.lang.reflect.InvocationTargetException;
@@ -63,7 +55,6 @@
 
     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 int MAX_EXCEPTION_COUNT_SIZE = 50;
     private static final String EXCEPTION_COUNT_OVERFLOW_NAME = "overflow";
 
@@ -81,25 +72,7 @@
     private final Random mRandom;
     private long mStartTime = System.currentTimeMillis();
 
-    // 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;
-            }
-        }
-    };
+    private CachedDeviceState.Readonly mDeviceState;
 
     /** Injector for {@link BinderCallsStats}. */
     public static class Injector {
@@ -112,65 +85,14 @@
         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();
-        }
+    public void setDeviceState(@NonNull CachedDeviceState.Readonly deviceState) {
+        mDeviceState = deviceState;
     }
 
     @Override
     @Nullable
     public CallSession callStarted(Binder binder, int code) {
-        if (mCharging) {
+        if (mDeviceState == null || mDeviceState.isCharging()) {
             return null;
         }
 
@@ -221,7 +143,7 @@
 
         synchronized (mLock) {
             // This was already checked in #callStart but check again while synchronized.
-            if (mCharging) {
+            if (mDeviceState == null || mDeviceState.isCharging()) {
                 return;
             }
 
@@ -233,7 +155,7 @@
                 uidEntry.recordedCallCount++;
 
                 final CallStat callStat = uidEntry.getOrCreate(
-                        s.binderClass, s.transactionCode, mScreenInteractive);
+                        s.binderClass, s.transactionCode, mDeviceState.isScreenInteractive());
                 callStat.callCount++;
                 callStat.recordedCallCount++;
                 callStat.cpuTimeMicros += duration;
@@ -252,7 +174,7 @@
                 // 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);
+                        s.binderClass, s.transactionCode, mDeviceState.isScreenInteractive());
                 if (callStat != null) {
                     callStat.callCount++;
                 }
@@ -319,13 +241,13 @@
     public ArrayList<ExportedCallStat> getExportedCallStats() {
         // We do not collect all the data if detailed tracking is off.
         if (!mDetailedTracking) {
-            return new ArrayList<ExportedCallStat>();
+            return new ArrayList<>();
         }
 
         ArrayList<ExportedCallStat> resultCallStats = new ArrayList<>();
         synchronized (mLock) {
             final int uidEntriesSize = mUidEntries.size();
-            for (int entryIdx = 0; entryIdx < uidEntriesSize; entryIdx++){
+            for (int entryIdx = 0; entryIdx < uidEntriesSize; entryIdx++) {
                 final UidEntry entry = mUidEntries.valueAt(entryIdx);
                 for (CallStat stat : entry.getCallStatsList()) {
                     ExportedCallStat exported = new ExportedCallStat();
@@ -387,13 +309,15 @@
         }
     }
 
-    public void dump(PrintWriter pw, Map<Integer,String> appIdToPkgNameMap, boolean verbose) {
+    /** Writes the collected statistics to the supplied {@link PrintWriter}.*/
+    public void dump(PrintWriter pw, Map<Integer, String> appIdToPkgNameMap, boolean verbose) {
         synchronized (mLock) {
             dumpLocked(pw, appIdToPkgNameMap, verbose);
         }
     }
 
-    private void dumpLocked(PrintWriter pw, Map<Integer,String> appIdToPkgNameMap, boolean verbose) {
+    private void dumpLocked(PrintWriter pw, Map<Integer, String> appIdToPkgNameMap,
+            boolean verbose) {
         long totalCallsCount = 0;
         long totalRecordedCallsCount = 0;
         long totalCpuTime = 0;
@@ -450,13 +374,13 @@
         for (UidEntry entry : summaryEntries) {
             String uidStr = uidToString(entry.uid, appIdToPkgNameMap);
             pw.println(String.format("  %10d %3.0f%% %8d %8d %s",
-                        entry.cpuTimeMicros, 100d * entry.cpuTimeMicros / totalCpuTime,
-                        entry.recordedCallCount, entry.callCount, uidStr));
+                    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 / totalRecordedCallsCount));
+                        + "calls_count=%d, avg_call_cpu_time=%.0f",
+                totalCpuTime, totalCallsCount, (double) totalCpuTime / totalRecordedCallsCount));
         pw.println();
 
         pw.println("Exceptions thrown (exception_count, class_name):");
@@ -723,11 +647,6 @@
         return result;
     }
 
-    @VisibleForTesting
-    public BroadcastReceiver getBroadcastReceiver() {
-        return mBroadcastReceiver;
-    }
-
     private static int compareByCpuDesc(
             ExportedCallStat a, ExportedCallStat b) {
         return Long.compare(b.cpuTimeMicros, a.cpuTimeMicros);
diff --git a/core/java/com/android/internal/os/CachedDeviceState.java b/core/java/com/android/internal/os/CachedDeviceState.java
new file mode 100644
index 0000000..8c90682
--- /dev/null
+++ b/core/java/com/android/internal/os/CachedDeviceState.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.internal.os;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+/**
+ * Stores the device state (e.g. charging/on battery, screen on/off) to be shared with
+ * the System Server telemetry services.
+ *
+ * @hide
+ */
+public class CachedDeviceState {
+    private volatile boolean mScreenInteractive;
+    private volatile boolean mCharging;
+
+    public CachedDeviceState() {
+        mCharging = true;
+        mScreenInteractive = false;
+    }
+
+    @VisibleForTesting
+    public CachedDeviceState(boolean isCharging, boolean isScreenInteractive) {
+        mCharging = isCharging;
+        mScreenInteractive = isScreenInteractive;
+    }
+
+    public void setScreenInteractive(boolean screenInteractive) {
+        mScreenInteractive = screenInteractive;
+    }
+
+    public void setCharging(boolean charging) {
+        mCharging = charging;
+    }
+
+    public Readonly getReadonlyClient() {
+        return new CachedDeviceState.Readonly();
+    }
+
+    /**
+     * Allows for only a readonly access to the device state.
+     */
+    public class Readonly {
+        public boolean isCharging() {
+            return mCharging;
+        }
+
+        public boolean isScreenInteractive() {
+            return mScreenInteractive;
+        }
+    }
+}
diff --git a/core/java/com/android/internal/os/LooperStats.java b/core/java/com/android/internal/os/LooperStats.java
new file mode 100644
index 0000000..02a8b22
--- /dev/null
+++ b/core/java/com/android/internal/os/LooperStats.java
@@ -0,0 +1,292 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.os;
+
+import android.annotation.NonNull;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.SystemClock;
+import android.util.SparseArray;
+
+import com.android.internal.annotations.GuardedBy;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.ThreadLocalRandom;
+
+/**
+ * Collects aggregated telemetry data about Looper message dispatching.
+ *
+ * @hide Only for use within the system server.
+ */
+public class LooperStats implements Looper.Observer {
+    private static final int TOKEN_POOL_SIZE = 50;
+
+    @GuardedBy("mLock")
+    private final SparseArray<Entry> mEntries = new SparseArray<>(512);
+    private final Object mLock = new Object();
+    private final Entry mOverflowEntry = new Entry("OVERFLOW");
+    private final Entry mHashCollisionEntry = new Entry("HASH_COLLISION");
+    private final ConcurrentLinkedQueue<DispatchSession> mSessionPool =
+            new ConcurrentLinkedQueue<>();
+    private final int mEntriesSizeCap;
+    private int mSamplingInterval;
+    private CachedDeviceState.Readonly mDeviceState;
+
+    public LooperStats(int samplingInterval, int entriesSizeCap) {
+        this.mSamplingInterval = samplingInterval;
+        this.mEntriesSizeCap = entriesSizeCap;
+    }
+
+    public void setDeviceState(@NonNull CachedDeviceState.Readonly deviceState) {
+        mDeviceState = deviceState;
+    }
+
+    @Override
+    public Object messageDispatchStarting() {
+        if (deviceStateAllowsCollection() && shouldCollectDetailedData()) {
+            DispatchSession session = mSessionPool.poll();
+            session = session == null ? new DispatchSession() : session;
+            session.startTimeMicro = getElapsedRealtimeMicro();
+            session.cpuStartMicro = getThreadTimeMicro();
+            return session;
+        }
+
+        return DispatchSession.NOT_SAMPLED;
+    }
+
+    @Override
+    public void messageDispatched(Object token, Message msg) {
+        if (!deviceStateAllowsCollection()) {
+            return;
+        }
+
+        DispatchSession session = (DispatchSession) token;
+        Entry entry = getOrCreateEntry(msg);
+        synchronized (entry) {
+            entry.messageCount++;
+            if (session != DispatchSession.NOT_SAMPLED) {
+                entry.recordedMessageCount++;
+                long latency = getElapsedRealtimeMicro() - session.startTimeMicro;
+                long cpuUsage = getThreadTimeMicro() - session.cpuStartMicro;
+                entry.totalLatencyMicro += latency;
+                entry.maxLatencyMicro = Math.max(entry.maxLatencyMicro, latency);
+                entry.cpuUsageMicro += cpuUsage;
+                entry.maxCpuUsageMicro = Math.max(entry.maxCpuUsageMicro, cpuUsage);
+            }
+        }
+
+        recycleSession(session);
+    }
+
+    @Override
+    public void dispatchingThrewException(Object token, Message msg, Exception exception) {
+        if (!deviceStateAllowsCollection()) {
+            return;
+        }
+
+        DispatchSession session = (DispatchSession) token;
+        Entry entry = getOrCreateEntry(msg);
+        synchronized (entry) {
+            entry.exceptionCount++;
+        }
+        recycleSession(session);
+    }
+
+    private boolean deviceStateAllowsCollection() {
+        // Do not collect data if on charger or the state is not set.
+        return mDeviceState != null && !mDeviceState.isCharging();
+    }
+
+    /** Returns an array of {@link ExportedEntry entries} with the aggregated statistics. */
+    public List<ExportedEntry> getEntries() {
+        final ArrayList<ExportedEntry> entries;
+        synchronized (mLock) {
+            final int size = mEntries.size();
+            entries = new ArrayList<>(size);
+            for (int i = 0; i < size; i++) {
+                Entry entry = mEntries.valueAt(i);
+                synchronized (entry) {
+                    entries.add(new ExportedEntry(entry));
+                }
+            }
+        }
+        // Add the overflow and collision entries only if they have any data.
+        if (mOverflowEntry.messageCount > 0 || mOverflowEntry.exceptionCount > 0) {
+            synchronized (mOverflowEntry) {
+                entries.add(new ExportedEntry(mOverflowEntry));
+            }
+        }
+        if (mHashCollisionEntry.messageCount > 0 || mHashCollisionEntry.exceptionCount > 0) {
+            synchronized (mHashCollisionEntry) {
+                entries.add(new ExportedEntry(mHashCollisionEntry));
+            }
+        }
+        return entries;
+    }
+
+    /** Removes all collected data. */
+    public void reset() {
+        synchronized (mLock) {
+            mEntries.clear();
+        }
+        synchronized (mHashCollisionEntry) {
+            mHashCollisionEntry.reset();
+        }
+        synchronized (mOverflowEntry) {
+            mOverflowEntry.reset();
+        }
+    }
+
+    public void setSamplingInterval(int samplingInterval) {
+        mSamplingInterval = samplingInterval;
+    }
+
+    @NonNull
+    private Entry getOrCreateEntry(Message msg) {
+        final boolean isInteractive = mDeviceState.isScreenInteractive();
+        final int id = Entry.idFor(msg, isInteractive);
+        Entry entry;
+        synchronized (mLock) {
+            entry = mEntries.get(id);
+            if (entry == null) {
+                if (mEntries.size() >= mEntriesSizeCap) {
+                    // If over the size cap, track totals under a single entry.
+                    return mOverflowEntry;
+                }
+                entry = new Entry(msg, isInteractive);
+                mEntries.put(id, entry);
+            }
+        }
+
+        if (entry.handler.getClass() != msg.getTarget().getClass()
+                || entry.handler.getLooper().getThread() != msg.getTarget().getLooper().getThread()
+                || entry.isInteractive != isInteractive) {
+            // If a hash collision happened, track totals under a single entry.
+            return mHashCollisionEntry;
+        }
+        return entry;
+    }
+
+    private void recycleSession(DispatchSession session) {
+        if (session != DispatchSession.NOT_SAMPLED && mSessionPool.size() < TOKEN_POOL_SIZE) {
+            mSessionPool.add(session);
+        }
+    }
+
+    protected long getThreadTimeMicro() {
+        return SystemClock.currentThreadTimeMicro();
+    }
+
+    protected long getElapsedRealtimeMicro() {
+        return SystemClock.elapsedRealtimeNanos() / 1000;
+    }
+
+    protected boolean shouldCollectDetailedData() {
+        return ThreadLocalRandom.current().nextInt() % mSamplingInterval == 0;
+    }
+
+    private static class DispatchSession {
+        static final DispatchSession NOT_SAMPLED = new DispatchSession();
+        public long startTimeMicro;
+        public long cpuStartMicro;
+    }
+
+    private static class Entry {
+        public final Handler handler;
+        public final String messageName;
+        public final boolean isInteractive;
+        public long messageCount;
+        public long recordedMessageCount;
+        public long exceptionCount;
+        public long totalLatencyMicro;
+        public long maxLatencyMicro;
+        public long cpuUsageMicro;
+        public long maxCpuUsageMicro;
+
+        Entry(Message msg, boolean isInteractive) {
+            this.handler = msg.getTarget();
+            this.messageName = handler.getMessageName(msg);
+            this.isInteractive = isInteractive;
+        }
+
+        Entry(String specialEntryName) {
+            this.messageName = specialEntryName;
+            this.handler = null;
+            this.isInteractive = false;
+        }
+
+        void reset() {
+            messageCount = 0;
+            recordedMessageCount = 0;
+            exceptionCount = 0;
+            totalLatencyMicro = 0;
+            maxLatencyMicro = 0;
+            cpuUsageMicro = 0;
+            maxCpuUsageMicro = 0;
+        }
+
+        static int idFor(Message msg, boolean isInteractive) {
+            int result = 7;
+            result = 31 * result + msg.getTarget().getLooper().getThread().hashCode();
+            result = 31 * result + msg.getTarget().getClass().hashCode();
+            result = 31 * result + (isInteractive ? 1231 : 1237);
+            if (msg.getCallback() != null) {
+                return 31 * result + msg.getCallback().getClass().hashCode();
+            } else {
+                return 31 * result + msg.what;
+            }
+        }
+    }
+
+    /** Aggregated data of Looper message dispatching in the in the current process. */
+    public static class ExportedEntry {
+        public final String handlerClassName;
+        public final String threadName;
+        public final String messageName;
+        public final boolean isInteractive;
+        public final long messageCount;
+        public final long recordedMessageCount;
+        public final long exceptionCount;
+        public final long totalLatencyMicros;
+        public final long maxLatencyMicros;
+        public final long cpuUsageMicros;
+        public final long maxCpuUsageMicros;
+
+        ExportedEntry(Entry entry) {
+            if (entry.handler != null) {
+                this.handlerClassName = entry.handler.getClass().getName();
+                this.threadName = entry.handler.getLooper().getThread().getName();
+            } else {
+                // Overflow/collision entries do not have a handler set.
+                this.handlerClassName = "";
+                this.threadName = "";
+            }
+            this.isInteractive = entry.isInteractive;
+            this.messageName = entry.messageName;
+            this.messageCount = entry.messageCount;
+            this.recordedMessageCount = entry.recordedMessageCount;
+            this.exceptionCount = entry.exceptionCount;
+            this.totalLatencyMicros = entry.totalLatencyMicro;
+            this.maxLatencyMicros = entry.maxLatencyMicro;
+            this.cpuUsageMicros = entry.cpuUsageMicro;
+            this.maxCpuUsageMicros = entry.maxCpuUsageMicro;
+        }
+    }
+}
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index b60b43a..06c41d8 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -22,6 +22,7 @@
 import static android.system.OsConstants.STDERR_FILENO;
 import static android.system.OsConstants.STDIN_FILENO;
 import static android.system.OsConstants.STDOUT_FILENO;
+
 import static com.android.internal.os.ZygoteConnectionConstants.CONNECTION_TIMEOUT_MILLIS;
 import static com.android.internal.os.ZygoteConnectionConstants.MAX_ZYGOTE_ARGC;
 import static com.android.internal.os.ZygoteConnectionConstants.WRAPPED_PID_TIMEOUT_MILLIS;
@@ -36,12 +37,15 @@
 import android.system.Os;
 import android.system.StructPollfd;
 import android.util.Log;
+
 import dalvik.system.VMRuntime;
+
+import libcore.io.IoUtils;
+
 import java.io.BufferedReader;
 import java.io.ByteArrayInputStream;
 import java.io.DataInputStream;
 import java.io.DataOutputStream;
-import java.io.EOFException;
 import java.io.FileDescriptor;
 import java.io.IOException;
 import java.io.InputStreamReader;
@@ -49,8 +53,6 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 
-import libcore.io.IoUtils;
-
 /**
  * A connection that can make spawn requests.
  */
@@ -377,6 +379,7 @@
      *    are the settings for current and max value.</i>
      *   <li> --instruction-set=<i>instruction-set-string</i> which instruction set to use/emulate.
      *   <li> --nice-name=<i>nice name to appear in ps</i>
+     *   <li> --package-name=<i>package name this process belongs to</i>
      *   <li> --runtime-args indicates that the remaining arg list should
      * be handed off to com.android.internal.os.RuntimeInit, rather than
      * processed directly.
@@ -680,6 +683,9 @@
                     }
                     expectRuntimeArgs = false;
                 } else if (arg.startsWith("--package-name=")) {
+                    if (packageName != null) {
+                        throw new IllegalArgumentException("Duplicate arg specified");
+                    }
                     packageName = arg.substring(arg.indexOf('=') + 1);
                 } else {
                     break;
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index 616520f..c4214cf 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -141,7 +141,7 @@
     void showShutdownUi(boolean isReboot, String reason);
 
     // Used to show the dialog when BiometricService starts authentication
-    void showBiometricDialog(in Bundle bundle, IBiometricPromptReceiver receiver);
+    void showBiometricDialog(in Bundle bundle, IBiometricPromptReceiver receiver, int type);
     // 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
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index b3af147..e48e733 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -91,7 +91,7 @@
     void showPinningEscapeToast();
 
     // Used to show the dialog when BiometricService starts authentication
-    void showBiometricDialog(in Bundle bundle, IBiometricPromptReceiver receiver);
+    void showBiometricDialog(in Bundle bundle, IBiometricPromptReceiver receiver, int type);
     // 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
diff --git a/core/java/com/android/internal/util/ContrastColorUtil.java b/core/java/com/android/internal/util/ContrastColorUtil.java
index 16ca4fc..1038199 100644
--- a/core/java/com/android/internal/util/ContrastColorUtil.java
+++ b/core/java/com/android/internal/util/ContrastColorUtil.java
@@ -455,7 +455,7 @@
      * Resolves {@param color} to an actual color if it is {@link Notification#COLOR_DEFAULT}
      */
     public static int resolveColor(Context context, int color, boolean defaultBackgroundIsDark) {
-        if (color == Notification.COLOR_DEFAULT) {
+        if (color == Notification.COLOR_DEFAULT || defaultBackgroundIsDark) {
             int res = defaultBackgroundIsDark
                     ? com.android.internal.R.color.notification_default_color_dark
                     : com.android.internal.R.color.notification_default_color_light;
diff --git a/core/java/com/android/internal/util/OWNERS b/core/java/com/android/internal/util/OWNERS
index 21d750c..e65d114 100644
--- a/core/java/com/android/internal/util/OWNERS
+++ b/core/java/com/android/internal/util/OWNERS
@@ -1,24 +1,4 @@
-per-file AsyncChannel*=lorenzo@google.com
-per-file AsyncChannel*=satk@google.com
-per-file AsyncChannel*=silberst@google.com
-per-file BitUtils*=ek@google.com
-per-file BitUtils*=lorenzo@google.com
-per-file BitUtils*=satk@google.com
-per-file MessageUtils*=ek@google.com
-per-file MessageUtils*=lorenzo@google.com
-per-file MessageUtils*=satk@google.com
-per-file Protocol*=ek@google.com
-per-file Protocol*=lorenzo@google.com
-per-file Protocol*=quiche@google.com
-per-file Protocol*=satk@google.com
-per-file Protocol*=silberst@google.com
-per-file RingBuffer*=ek@google.com
-per-file RingBuffer*=lorenzo@google.com
-per-file RingBuffer*=satk@google.com
-per-file State*=ek@google.com
-per-file State*=lorenzo@google.com
-per-file State*=quiche@google.com
-per-file State*=silberst@google.com
-per-file TokenBucket*=ek@google.com
-per-file TokenBucket*=lorenzo@google.com
-per-file TokenBucket*=satk@google.com
+per-file AsyncChannel* = lorenzo@google.com, satk@google.com, etancohen@google.com
+per-file BitUtils*, MessageUtils*, Protocol*, RingBuffer*, TokenBucket* = jchalard@google.com, lorenzo@google.com, satk@google.com
+per-file Protocol* = etancohen@google.com, lorenzo@google.com
+per-file State* = jchalard@google.com, lorenzo@google.com, satk@google.com
diff --git a/core/java/com/android/internal/view/IInputConnectionWrapper.java b/core/java/com/android/internal/view/IInputConnectionWrapper.java
index 189c8d5..ececba1 100644
--- a/core/java/com/android/internal/view/IInputConnectionWrapper.java
+++ b/core/java/com/android/internal/view/IInputConnectionWrapper.java
@@ -16,12 +16,10 @@
 
 package com.android.internal.view;
 
-import com.android.internal.annotations.GuardedBy;
-import com.android.internal.os.SomeArgs;
-
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.UnsupportedAppUsage;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
@@ -37,6 +35,9 @@
 import android.view.inputmethod.InputConnectionInspector.MissingMethodFlags;
 import android.view.inputmethod.InputContentInfo;
 
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.os.SomeArgs;
+
 public abstract class IInputConnectionWrapper extends IInputContext.Stub {
     private static final String TAG = "IInputConnectionWrapper";
     private static final boolean DEBUG = false;
@@ -68,7 +69,7 @@
 
     @GuardedBy("mLock")
     @Nullable
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private InputConnection mInputConnection;
 
     private Looper mMainLooper;
@@ -110,12 +111,6 @@
 
     abstract protected boolean isActive();
 
-    /**
-     * Called when the user took some actions that should be taken into consideration to update the
-     * LRU list for input method rotation.
-     */
-    abstract protected void onUserAction();
-
     public void getTextAfterCursor(int length, int flags, int seq, IInputContextCallback callback) {
         dispatchMessage(obtainMessageIISC(DO_GET_TEXT_AFTER_CURSOR, length, flags, seq, callback));
     }
@@ -342,7 +337,6 @@
                     return;
                 }
                 ic.commitText((CharSequence)msg.obj, msg.arg1);
-                onUserAction();
                 return;
             }
             case DO_SET_SELECTION: {
@@ -397,7 +391,6 @@
                     return;
                 }
                 ic.setComposingText((CharSequence)msg.obj, msg.arg1);
-                onUserAction();
                 return;
             }
             case DO_SET_COMPOSING_REGION: {
@@ -437,7 +430,6 @@
                     return;
                 }
                 ic.sendKeyEvent((KeyEvent)msg.obj);
-                onUserAction();
                 return;
             }
             case DO_CLEAR_META_KEY_STATES: {
diff --git a/core/java/com/android/internal/view/IInputMethod.aidl b/core/java/com/android/internal/view/IInputMethod.aidl
index 5b29f4c..97d5a65 100644
--- a/core/java/com/android/internal/view/IInputMethod.aidl
+++ b/core/java/com/android/internal/view/IInputMethod.aidl
@@ -22,6 +22,7 @@
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputBinding;
 import android.view.inputmethod.InputMethodSubtype;
+import com.android.internal.inputmethod.IInputMethodPrivilegedOperations;
 import com.android.internal.view.IInputContext;
 import com.android.internal.view.IInputMethodSession;
 import com.android.internal.view.IInputSessionCallback;
@@ -32,7 +33,7 @@
  * {@hide}
  */
 oneway interface IInputMethod {
-    void attachToken(IBinder token);
+    void initializeInternal(IBinder token, int displayId, IInputMethodPrivilegedOperations privOps);
 
     void bindInput(in InputBinding binding);
 
diff --git a/core/java/com/android/internal/view/IInputMethodClient.aidl b/core/java/com/android/internal/view/IInputMethodClient.aidl
index 5c6dea8..2618356 100644
--- a/core/java/com/android/internal/view/IInputMethodClient.aidl
+++ b/core/java/com/android/internal/view/IInputMethodClient.aidl
@@ -27,6 +27,5 @@
     // unbindReason corresponds to InputMethodClient.UnbindReason.
     void onUnbindMethod(int sequence, int unbindReason);
     void setActive(boolean active, boolean fullscreen);
-    void setUserActionNotificationSequenceNumber(int sequenceNumber);
     void reportFullscreenMode(boolean fullscreen);
 }
diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl
index 4b004e2..543f4a5 100644
--- a/core/java/com/android/internal/view/IInputMethodManager.aidl
+++ b/core/java/com/android/internal/view/IInputMethodManager.aidl
@@ -16,13 +16,12 @@
 
 package com.android.internal.view;
 
-import android.net.Uri;
 import android.os.ResultReceiver;
 import android.text.style.SuggestionSpan;
 import android.view.inputmethod.InputMethodInfo;
 import android.view.inputmethod.InputMethodSubtype;
 import android.view.inputmethod.EditorInfo;
-import com.android.internal.inputmethod.IInputContentUriToken;
+
 import com.android.internal.view.InputBindResult;
 import com.android.internal.view.IInputContext;
 import com.android.internal.view.IInputMethodClient;
@@ -64,28 +63,20 @@
             int auxiliarySubtypeMode);
     void showInputMethodAndSubtypeEnablerFromClient(in IInputMethodClient client, String topId);
     boolean isInputMethodPickerShownForTest();
+    // TODO(Bug 114488811): this can be removed once we deprecate special null token rule.
     void setInputMethod(in IBinder token, String id);
+    // TODO(Bug 114488811): this can be removed once we deprecate special null token rule.
     void setInputMethodAndSubtype(in IBinder token, String id, in InputMethodSubtype subtype);
-    void hideMySoftInput(in IBinder token, int flags);
-    void showMySoftInput(in IBinder token, int flags);
-    void updateStatusIcon(in IBinder token, String packageName, int iconId);
-    void setImeWindowStatus(in IBinder token, int vis, int backDisposition);
-    void reportStartInput(in IBinder token, in IBinder startInputToken);
     void registerSuggestionSpansForNotification(in SuggestionSpan[] spans);
     boolean notifySuggestionPicked(in SuggestionSpan span, String originalString, int index);
     InputMethodSubtype getCurrentInputMethodSubtype();
     boolean setCurrentInputMethodSubtype(in InputMethodSubtype subtype);
+    // TODO(Bug 114488811): this can be removed once we deprecate special null token rule.
     boolean switchToPreviousInputMethod(in IBinder token);
+    // TODO(Bug 114488811): this can be removed once we deprecate special null token rule.
     boolean switchToNextInputMethod(in IBinder token, boolean onlyCurrentIme);
-    boolean shouldOfferSwitchingToNextInputMethod(in IBinder token);
     void setAdditionalInputMethodSubtypes(String id, in InputMethodSubtype[] subtypes);
+    // This is kept due to @UnsupportedAppUsage.
+    // TODO(Bug 113914148): Consider removing this.
     int getInputMethodWindowVisibleHeight();
-    void clearLastInputMethodWindowForTransition(in IBinder token);
-
-    IInputContentUriToken createInputContentUriToken(in IBinder token, in Uri contentUri,
-            in String packageName);
-
-    void reportFullscreenMode(in IBinder token, boolean fullscreen);
-
-    oneway void notifyUserAction(int sequenceNumber);
 }
diff --git a/core/java/com/android/internal/view/InputBindResult.java b/core/java/com/android/internal/view/InputBindResult.java
index 9d4383f..7548c22 100644
--- a/core/java/com/android/internal/view/InputBindResult.java
+++ b/core/java/com/android/internal/view/InputBindResult.java
@@ -60,7 +60,7 @@
         /**
          * Indicates that this is a temporary binding until the
          * {@link android.inputmethodservice.InputMethodService} (IMS) establishes a valid session
-         * to {@link com.android.server.InputMethodManagerService} (IMMS).
+         * to {@link com.android.server.inputmethod.InputMethodManagerService} (IMMS).
          *
          * <p>Note that in this state the IMS is already bound to IMMS but the logical session
          * is not yet established on top of the IPC channel.</p>
@@ -73,7 +73,7 @@
         /**
          * Indicates that this is a temporary binding until the
          * {@link android.inputmethodservice.InputMethodService} (IMS) establishes a valid session
-         * to {@link com.android.server.InputMethodManagerService} (IMMS).
+         * to {@link com.android.server.inputmethod.InputMethodManagerService} (IMMS).
          *
          * <p>Note that in this state the IMMS has already initiated a connection to the IMS but
          * the binding process is not completed yet.</p>
@@ -91,12 +91,14 @@
         int SUCCESS_REPORT_WINDOW_FOCUS_ONLY = 3;
         /**
          * Indicates somehow
-         * {@link com.android.server.InputMethodManagerService#startInputOrWindowGainedFocus} is
-         * trying to return null {@link InputBindResult}, which must never happen.
+         * {@link
+         * com.android.server.inputmethod.InputMethodManagerService#startInputOrWindowGainedFocus}
+         * is trying to return null {@link InputBindResult}, which must never happen.
          */
         int ERROR_NULL = 4;
         /**
-         * Indicates that {@link com.android.server.InputMethodManagerService} recognizes no IME.
+         * Indicates that {@link com.android.server.inputmethod.InputMethodManagerService}
+         * recognizes no IME.
          */
         int ERROR_NO_IME = 5;
         /**
@@ -114,8 +116,8 @@
          */
         int ERROR_SYSTEM_NOT_READY = 7;
         /**
-         * Indicates that {@link com.android.server.InputMethodManagerService} tried to connect to
-         * an {@link android.inputmethodservice.InputMethodService} but failed.
+         * Indicates that {@link com.android.server.inputmethod.InputMethodManagerService} tried to
+         * connect to an {@link android.inputmethodservice.InputMethodService} but failed.
          *
          * @see android.content.Context#bindServiceAsUser(Intent, ServiceConnection, int, UserHandle)
          */
@@ -137,7 +139,8 @@
          * The client should try to restart input when its {@link android.view.Window} is focused
          * again.</p>
          *
-         * @see com.android.server.wm.WindowManagerService#inputMethodClientHasFocus(IInputMethodClient)
+         * @see com.android.server.wm.WindowManagerInternal#inputMethodClientHasFocus(
+         * IInputMethodClient)
          */
         int ERROR_NOT_IME_TARGET_WINDOW = 11;
         /**
@@ -171,20 +174,13 @@
      */
     public final int sequence;
 
-    /**
-     * Sequence number of user action notification.
-     */
-    public final int userActionNotificationSequenceNumber;
-
     public InputBindResult(@ResultCode int _result,
-            IInputMethodSession _method, InputChannel _channel,
-            String _id, int _sequence, int _userActionNotificationSequenceNumber) {
+            IInputMethodSession _method, InputChannel _channel, String _id, int _sequence) {
         result = _result;
         method = _method;
         channel = _channel;
         id = _id;
         sequence = _sequence;
-        userActionNotificationSequenceNumber = _userActionNotificationSequenceNumber;
     }
 
     InputBindResult(Parcel source) {
@@ -197,14 +193,12 @@
         }
         id = source.readString();
         sequence = source.readInt();
-        userActionNotificationSequenceNumber = source.readInt();
     }
 
     @Override
     public String toString() {
         return "InputBindResult{result=" + getResultString() + " method="+ method + " id=" + id
                 + " sequence=" + sequence
-                + " userActionNotificationSequenceNumber=" + userActionNotificationSequenceNumber
                 + "}";
     }
 
@@ -226,7 +220,6 @@
         }
         dest.writeString(id);
         dest.writeInt(sequence);
-        dest.writeInt(userActionNotificationSequenceNumber);
     }
 
     /**
@@ -285,7 +278,7 @@
     }
 
     private static InputBindResult error(@ResultCode int result) {
-        return new InputBindResult(result, null, null, null, -1, -1);
+        return new InputBindResult(result, null, null, null, -1);
     }
 
     /**
diff --git a/core/java/com/android/internal/view/InputConnectionWrapper.java b/core/java/com/android/internal/view/InputConnectionWrapper.java
index 5b65bbe..3bd3072 100644
--- a/core/java/com/android/internal/view/InputConnectionWrapper.java
+++ b/core/java/com/android/internal/view/InputConnectionWrapper.java
@@ -371,6 +371,7 @@
     public boolean commitText(CharSequence text, int newCursorPosition) {
         try {
             mIInputContext.commitText(text, newCursorPosition);
+            notifyUserActionIfNecessary();
             return true;
         } catch (RemoteException e) {
             return false;
@@ -378,6 +379,16 @@
     }
 
     @AnyThread
+    private void notifyUserActionIfNecessary() {
+        final AbstractInputMethodService inputMethodService = mInputMethodService.get();
+        if (inputMethodService == null) {
+            // This basically should not happen, because it's the the caller of this method.
+            return;
+        }
+        inputMethodService.notifyUserActionIfNecessary();
+    }
+
+    @AnyThread
     public boolean commitCompletion(CompletionInfo text) {
         if (isMethodMissing(MissingMethodFlags.COMMIT_CORRECTION)) {
             // This method is not implemented.
@@ -449,6 +460,7 @@
     public boolean setComposingText(CharSequence text, int newCursorPosition) {
         try {
             mIInputContext.setComposingText(text, newCursorPosition);
+            notifyUserActionIfNecessary();
             return true;
         } catch (RemoteException e) {
             return false;
@@ -489,6 +501,7 @@
     public boolean sendKeyEvent(KeyEvent event) {
         try {
             mIInputContext.sendKeyEvent(event);
+            notifyUserActionIfNecessary();
             return true;
         } catch (RemoteException e) {
             return false;
diff --git a/core/java/com/android/internal/widget/PointerLocationView.java b/core/java/com/android/internal/widget/PointerLocationView.java
index 4ee951a..0b37d57 100644
--- a/core/java/com/android/internal/widget/PointerLocationView.java
+++ b/core/java/com/android/internal/widget/PointerLocationView.java
@@ -19,8 +19,8 @@
 import android.content.Context;
 import android.graphics.Canvas;
 import android.graphics.Paint;
-import android.graphics.RectF;
 import android.graphics.Paint.FontMetricsInt;
+import android.graphics.RectF;
 import android.hardware.input.InputManager;
 import android.hardware.input.InputManager.InputDeviceListener;
 import android.os.SystemProperties;
@@ -29,12 +29,12 @@
 import android.view.InputDevice;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
+import android.view.MotionEvent.PointerCoords;
 import android.view.VelocityTracker;
 import android.view.View;
 import android.view.ViewConfiguration;
 import android.view.WindowInsets;
 import android.view.WindowManagerPolicyConstants.PointerEventListener;
-import android.view.MotionEvent.PointerCoords;
 
 import java.util.ArrayList;
 
@@ -105,10 +105,6 @@
         }
     }
 
-    private final int ESTIMATE_PAST_POINTS = 4;
-    private final int ESTIMATE_FUTURE_POINTS = 2;
-    private final float ESTIMATE_INTERVAL = 0.02f;
-
     private final InputManager mIm;
 
     private final ViewConfiguration mVC;
@@ -336,37 +332,14 @@
             }
 
             if (drawn) {
-                // Draw movement estimate curve.
-                mPaint.setARGB(128, 128, 0, 128);
-                float lx = ps.mEstimator.estimateX(-ESTIMATE_PAST_POINTS * ESTIMATE_INTERVAL);
-                float ly = ps.mEstimator.estimateY(-ESTIMATE_PAST_POINTS * ESTIMATE_INTERVAL);
-                for (int i = -ESTIMATE_PAST_POINTS + 1; i <= ESTIMATE_FUTURE_POINTS; i++) {
-                    float x = ps.mEstimator.estimateX(i * ESTIMATE_INTERVAL);
-                    float y = ps.mEstimator.estimateY(i * ESTIMATE_INTERVAL);
-                    canvas.drawLine(lx, ly, x, y, mPaint);
-                    lx = x;
-                    ly = y;
-                }
-
                 // Draw velocity vector.
                 mPaint.setARGB(255, 255, 64, 128);
                 float xVel = ps.mXVelocity * (1000 / 60);
                 float yVel = ps.mYVelocity * (1000 / 60);
                 canvas.drawLine(lastX, lastY, lastX + xVel, lastY + yVel, mPaint);
 
-                // Draw alternate estimate.
+                // Draw velocity vector using an alternate VelocityTracker strategy.
                 if (mAltVelocity != null) {
-                    mPaint.setARGB(128, 0, 128, 128);
-                    lx = ps.mAltEstimator.estimateX(-ESTIMATE_PAST_POINTS * ESTIMATE_INTERVAL);
-                    ly = ps.mAltEstimator.estimateY(-ESTIMATE_PAST_POINTS * ESTIMATE_INTERVAL);
-                    for (int i = -ESTIMATE_PAST_POINTS + 1; i <= ESTIMATE_FUTURE_POINTS; i++) {
-                        float x = ps.mAltEstimator.estimateX(i * ESTIMATE_INTERVAL);
-                        float y = ps.mAltEstimator.estimateY(i * ESTIMATE_INTERVAL);
-                        canvas.drawLine(lx, ly, x, y, mPaint);
-                        lx = x;
-                        ly = y;
-                    }
-
                     mPaint.setARGB(255, 64, 255, 128);
                     xVel = ps.mAltXVelocity * (1000 / 60);
                     yVel = ps.mAltYVelocity * (1000 / 60);
diff --git a/core/java/com/android/server/AppWidgetBackupBridge.java b/core/java/com/android/server/AppWidgetBackupBridge.java
index 2ea2f79..7d82d35 100644
--- a/core/java/com/android/server/AppWidgetBackupBridge.java
+++ b/core/java/com/android/server/AppWidgetBackupBridge.java
@@ -16,6 +16,8 @@
 
 package com.android.server;
 
+import android.annotation.Nullable;
+
 import java.util.List;
 
 /**
@@ -37,6 +39,8 @@
                 : null;
     }
 
+    /** Returns a byte array of widget data for the specified package or {@code null}. */
+    @Nullable
     public static byte[] getWidgetState(String packageName, int userId) {
         return (sAppWidgetService != null)
                 ? sAppWidgetService.getWidgetState(packageName, userId)
diff --git a/core/java/org/apache/http/conn/ssl/SSLSocketFactory.java b/core/java/org/apache/http/conn/ssl/SSLSocketFactory.java
index 65be161..b2e8b5e 100644
--- a/core/java/org/apache/http/conn/ssl/SSLSocketFactory.java
+++ b/core/java/org/apache/http/conn/ssl/SSLSocketFactory.java
@@ -37,6 +37,7 @@
 import org.apache.http.params.HttpParams;
 
 import android.annotation.UnsupportedAppUsage;
+import android.os.Build;
 import javax.net.ssl.HttpsURLConnection;
 import javax.net.ssl.KeyManager;
 import javax.net.ssl.KeyManagerFactory;
@@ -181,7 +182,7 @@
     private final javax.net.ssl.SSLSocketFactory socketfactory;
     @UnsupportedAppUsage
     private final HostNameResolver nameResolver;
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private X509HostnameVerifier hostnameVerifier = BROWSER_COMPATIBLE_HOSTNAME_VERIFIER;
 
     public SSLSocketFactory(
@@ -251,7 +252,7 @@
      * This constructor is used exclusively to instantiate the factory for
      * {@link #getSocketFactory getSocketFactory}.
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private SSLSocketFactory() {
         super();
         this.sslcontext = null;
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index 8083a6a..0a25271 100755
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -1198,6 +1198,10 @@
 
 static jobject Bitmap_createHardwareBitmap(JNIEnv* env, jobject, jobject graphicBuffer) {
     sp<GraphicBuffer> buffer(graphicBufferForJavaObject(env, graphicBuffer));
+    // Bitmap::createFrom currently can only attach to a GraphicBuffer with PIXEL_FORMAT_RGBA_8888
+    // format and SRGB color space.
+    // To support any color space, we need to pass an additional ColorSpace argument to
+    // java Bitmap.createHardwareBitmap.
     sk_sp<Bitmap> bitmap = Bitmap::createFrom(buffer);
     if (!bitmap.get()) {
         ALOGW("failed to create hardware bitmap from graphic buffer");
diff --git a/core/jni/android/graphics/ColorFilter.cpp b/core/jni/android/graphics/ColorFilter.cpp
index 3fcedd0..6ebf35c 100644
--- a/core/jni/android/graphics/ColorFilter.cpp
+++ b/core/jni/android/graphics/ColorFilter.cpp
@@ -22,8 +22,6 @@
 #include "SkColorFilter.h"
 #include "SkColorMatrixFilter.h"
 
-#include <Caches.h>
-
 namespace android {
 
 using namespace uirenderer;
diff --git a/core/jni/android/graphics/Matrix.cpp b/core/jni/android/graphics/Matrix.cpp
index f8bb77a..755fcfb 100644
--- a/core/jni/android/graphics/Matrix.cpp
+++ b/core/jni/android/graphics/Matrix.cpp
@@ -20,7 +20,6 @@
 #include "SkMatrix.h"
 #include "core_jni_helpers.h"
 
-#include <Caches.h>
 #include <jni.h>
 
 namespace android {
diff --git a/core/jni/android/graphics/Shader.cpp b/core/jni/android/graphics/Shader.cpp
index cff7720..68f5bef 100644
--- a/core/jni/android/graphics/Shader.cpp
+++ b/core/jni/android/graphics/Shader.cpp
@@ -6,7 +6,6 @@
 #include "SkBlendMode.h"
 #include "core_jni_helpers.h"
 
-#include <Caches.h>
 #include <jni.h>
 
 using namespace android::uirenderer;
diff --git a/core/jni/android/graphics/SurfaceTexture.cpp b/core/jni/android/graphics/SurfaceTexture.cpp
index d098a35..3e464c6 100644
--- a/core/jni/android/graphics/SurfaceTexture.cpp
+++ b/core/jni/android/graphics/SurfaceTexture.cpp
@@ -36,6 +36,7 @@
 #include "jni.h"
 #include <nativehelper/JNIHelp.h>
 #include <nativehelper/ScopedLocalRef.h>
+#include "surfacetexture/SurfaceTexture.h"
 
 // ----------------------------------------------------------------------------
 
@@ -80,10 +81,10 @@
 // ----------------------------------------------------------------------------
 
 static void SurfaceTexture_setSurfaceTexture(JNIEnv* env, jobject thiz,
-        const sp<GLConsumer>& surfaceTexture)
+        const sp<SurfaceTexture>& surfaceTexture)
 {
-    GLConsumer* const p =
-        (GLConsumer*)env->GetLongField(thiz, fields.surfaceTexture);
+    SurfaceTexture* const p =
+        (SurfaceTexture*)env->GetLongField(thiz, fields.surfaceTexture);
     if (surfaceTexture.get()) {
         surfaceTexture->incStrong((void*)SurfaceTexture_setSurfaceTexture);
     }
@@ -108,10 +109,10 @@
 }
 
 static void SurfaceTexture_setFrameAvailableListener(JNIEnv* env,
-        jobject thiz, sp<GLConsumer::FrameAvailableListener> listener)
+        jobject thiz, sp<SurfaceTexture::FrameAvailableListener> listener)
 {
-    GLConsumer::FrameAvailableListener* const p =
-        (GLConsumer::FrameAvailableListener*)
+    SurfaceTexture::FrameAvailableListener* const p =
+        (SurfaceTexture::FrameAvailableListener*)
             env->GetLongField(thiz, fields.frameAvailableListener);
     if (listener.get()) {
         listener->incStrong((void*)SurfaceTexture_setSurfaceTexture);
@@ -122,8 +123,8 @@
     env->SetLongField(thiz, fields.frameAvailableListener, (jlong)listener.get());
 }
 
-sp<GLConsumer> SurfaceTexture_getSurfaceTexture(JNIEnv* env, jobject thiz) {
-    return (GLConsumer*)env->GetLongField(thiz, fields.surfaceTexture);
+sp<SurfaceTexture> SurfaceTexture_getSurfaceTexture(JNIEnv* env, jobject thiz) {
+    return (SurfaceTexture*)env->GetLongField(thiz, fields.surfaceTexture);
 }
 
 sp<IGraphicBufferProducer> SurfaceTexture_getProducer(JNIEnv* env, jobject thiz) {
@@ -131,7 +132,7 @@
 }
 
 sp<ANativeWindow> android_SurfaceTexture_getNativeWindow(JNIEnv* env, jobject thiz) {
-    sp<GLConsumer> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
+    sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
     sp<IGraphicBufferProducer> producer(SurfaceTexture_getProducer(env, thiz));
     sp<Surface> surfaceTextureClient(surfaceTexture != NULL ? new Surface(producer) : NULL);
     return surfaceTextureClient;
@@ -144,7 +145,7 @@
 
 // ----------------------------------------------------------------------------
 
-class JNISurfaceTextureContext : public GLConsumer::FrameAvailableListener
+class JNISurfaceTextureContext : public SurfaceTexture::FrameAvailableListener
 {
 public:
     JNISurfaceTextureContext(JNIEnv* env, jobject weakThiz, jclass clazz);
@@ -266,12 +267,12 @@
         consumer->setMaxBufferCount(1);
     }
 
-    sp<GLConsumer> surfaceTexture;
+    sp<SurfaceTexture> surfaceTexture;
     if (isDetached) {
-        surfaceTexture = new GLConsumer(consumer, GL_TEXTURE_EXTERNAL_OES,
+        surfaceTexture = new SurfaceTexture(consumer, GL_TEXTURE_EXTERNAL_OES,
                 true, !singleBufferMode);
     } else {
-        surfaceTexture = new GLConsumer(consumer, texName,
+        surfaceTexture = new SurfaceTexture(consumer, texName,
                 GL_TEXTURE_EXTERNAL_OES, true, !singleBufferMode);
     }
 
@@ -306,7 +307,7 @@
 
 static void SurfaceTexture_finalize(JNIEnv* env, jobject thiz)
 {
-    sp<GLConsumer> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
+    sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
     surfaceTexture->setFrameAvailableListener(0);
     SurfaceTexture_setFrameAvailableListener(env, thiz, 0);
     SurfaceTexture_setSurfaceTexture(env, thiz, 0);
@@ -315,13 +316,13 @@
 
 static void SurfaceTexture_setDefaultBufferSize(
         JNIEnv* env, jobject thiz, jint width, jint height) {
-    sp<GLConsumer> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
+    sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
     surfaceTexture->setDefaultBufferSize(width, height);
 }
 
 static void SurfaceTexture_updateTexImage(JNIEnv* env, jobject thiz)
 {
-    sp<GLConsumer> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
+    sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
     status_t err = surfaceTexture->updateTexImage();
     if (err == INVALID_OPERATION) {
         jniThrowException(env, IllegalStateException, "Unable to update texture contents (see "
@@ -333,7 +334,7 @@
 
 static void SurfaceTexture_releaseTexImage(JNIEnv* env, jobject thiz)
 {
-    sp<GLConsumer> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
+    sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
     status_t err = surfaceTexture->releaseTexImage();
     if (err == INVALID_OPERATION) {
         jniThrowException(env, IllegalStateException, "Unable to release texture contents (see "
@@ -345,20 +346,20 @@
 
 static jint SurfaceTexture_detachFromGLContext(JNIEnv* env, jobject thiz)
 {
-    sp<GLConsumer> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
+    sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
     return surfaceTexture->detachFromContext();
 }
 
 static jint SurfaceTexture_attachToGLContext(JNIEnv* env, jobject thiz, jint tex)
 {
-    sp<GLConsumer> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
+    sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
     return surfaceTexture->attachToContext((GLuint)tex);
 }
 
 static void SurfaceTexture_getTransformMatrix(JNIEnv* env, jobject thiz,
         jfloatArray jmtx)
 {
-    sp<GLConsumer> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
+    sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
     float* mtx = env->GetFloatArrayElements(jmtx, NULL);
     surfaceTexture->getTransformMatrix(mtx);
     env->ReleaseFloatArrayElements(jmtx, mtx, 0);
@@ -366,19 +367,19 @@
 
 static jlong SurfaceTexture_getTimestamp(JNIEnv* env, jobject thiz)
 {
-    sp<GLConsumer> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
+    sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
     return surfaceTexture->getTimestamp();
 }
 
 static void SurfaceTexture_release(JNIEnv* env, jobject thiz)
 {
-    sp<GLConsumer> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
+    sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
     surfaceTexture->abandon();
 }
 
 static jboolean SurfaceTexture_isReleased(JNIEnv* env, jobject thiz)
 {
-    sp<GLConsumer> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
+    sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
     return surfaceTexture->isAbandoned();
 }
 
diff --git a/core/jni/android_hardware_display_DisplayViewport.cpp b/core/jni/android_hardware_display_DisplayViewport.cpp
index 23c3877..ab8e685 100644
--- a/core/jni/android_hardware_display_DisplayViewport.cpp
+++ b/core/jni/android_hardware_display_DisplayViewport.cpp
@@ -61,7 +61,7 @@
     jstring uniqueId =
             jstring(env->GetObjectField(viewportObj, gDisplayViewportClassInfo.uniqueId));
     if (uniqueId != nullptr) {
-        viewport->uniqueId.setTo(ScopedUtfChars(env, uniqueId).c_str());
+        viewport->uniqueId = ScopedUtfChars(env, uniqueId).c_str();
     }
 
     jobject logicalFrameObj =
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index a72363c..d4a84c1 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -70,6 +70,9 @@
     jfieldID    mRole;
     jfieldID    mGains;
     jfieldID    mActiveConfig;
+    // Valid only if an AudioDevicePort
+    jfieldID    mType;
+    jfieldID    mAddress;
     // other fields unused by JNI
 } gAudioPortFields;
 
@@ -153,6 +156,9 @@
 static struct {
     jfieldID    mUsage;
     jfieldID    mSource;
+    jfieldID    mContentType;
+    jfieldID    mFlags;
+    jfieldID    mFormattedTags;
 } gAudioAttributesFields;
 
 static const char* const kEventHandlerClassPathName =
@@ -669,6 +675,26 @@
     env->DeleteLocalRef(jValues);
 }
 
+static jint convertAudioAttributesToNative(JNIEnv *env,
+                                           audio_attributes_t *nAudioAttributes,
+                                           const jobject jAudioAttributes)
+{
+    nAudioAttributes->usage = (audio_usage_t)env->GetIntField(jAudioAttributes,
+            gAudioAttributesFields.mUsage);
+    nAudioAttributes->source = (audio_source_t)env->GetIntField(jAudioAttributes,
+            gAudioAttributesFields.mSource);
+    nAudioAttributes->content_type = (audio_content_type_t)env->GetIntField(jAudioAttributes,
+            gAudioAttributesFields.mContentType);
+    nAudioAttributes->flags = env->GetIntField(jAudioAttributes,
+            gAudioAttributesFields.mFlags);
+    const jstring jtags = (jstring)env->GetObjectField(jAudioAttributes,
+            gAudioAttributesFields.mFormattedTags);
+    const char *tags = env->GetStringUTFChars(jtags, NULL);
+    strncpy(nAudioAttributes->tags, tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1);
+    env->ReleaseStringUTFChars(jtags, tags);
+    return (jint)AUDIO_JAVA_SUCCESS;
+}
+
 
 static jint convertAudioPortConfigToNative(JNIEnv *env,
                                                struct audio_port_config *nAudioPortConfig,
@@ -745,6 +771,42 @@
     return (jint)AUDIO_JAVA_SUCCESS;
 }
 
+/**
+ * Extends convertAudioPortConfigToNative with extra device port info.
+ * Mix / Session specific info is not fulfilled.
+ */
+static jint convertAudioPortConfigToNativeWithDevicePort(JNIEnv *env,
+                                                         struct audio_port_config *nAudioPortConfig,
+                                                         const jobject jAudioPortConfig,
+                                                         bool useConfigMask)
+{
+    jint jStatus = convertAudioPortConfigToNative(env,
+            nAudioPortConfig,
+            jAudioPortConfig,
+            useConfigMask);
+    if (jStatus != AUDIO_JAVA_SUCCESS) {
+        return jStatus;
+    }
+    // Supports AUDIO_PORT_TYPE_DEVICE only
+    if (nAudioPortConfig->type != AUDIO_PORT_TYPE_DEVICE) {
+        return (jint)AUDIO_JAVA_BAD_VALUE;
+    }
+
+    jobject jAudioDevicePort = env->GetObjectField(jAudioPortConfig,
+            gAudioPortConfigFields.mPort);
+    nAudioPortConfig->ext.device.type = env->GetIntField(jAudioDevicePort,
+            gAudioPortFields.mType);
+    jstring jDeviceAddress = (jstring)env->GetObjectField(jAudioDevicePort,
+            gAudioPortFields.mAddress);
+    const char *nDeviceAddress = env->GetStringUTFChars(jDeviceAddress, NULL);
+    strncpy(nAudioPortConfig->ext.device.address,
+            nDeviceAddress, AUDIO_DEVICE_MAX_ADDRESS_LEN - 1);
+    env->ReleaseStringUTFChars(jDeviceAddress, nDeviceAddress);
+    env->DeleteLocalRef(jDeviceAddress);
+    env->DeleteLocalRef(jAudioDevicePort);
+    return jStatus;
+}
+
 static jint convertAudioPortConfigFromNative(JNIEnv *env,
                                                  jobject jAudioPort,
                                                  jobject *jAudioPortConfig,
@@ -1592,6 +1654,51 @@
     return jStatus;
 }
 
+/**
+ * Returns handle if the audio source is successfully started.
+ */
+static jint
+android_media_AudioSystem_startAudioSource(JNIEnv *env, jobject clazz,
+                                           jobject jAudioPortConfig,
+                                           jobject jAudioAttributes)
+{
+    ALOGV("startAudioSource");
+    if (jAudioPortConfig == NULL || jAudioAttributes == NULL) {
+        return AUDIO_JAVA_BAD_VALUE;
+    }
+    if (!env->IsInstanceOf(jAudioPortConfig, gAudioPortConfigClass)) {
+        return AUDIO_JAVA_BAD_VALUE;
+    }
+    if (!env->IsInstanceOf(jAudioAttributes, gAudioAttributesClass)) {
+        return AUDIO_JAVA_BAD_VALUE;
+    }
+    struct audio_port_config nAudioPortConfig = {};
+    jint jStatus = convertAudioPortConfigToNativeWithDevicePort(env,
+            &nAudioPortConfig, jAudioPortConfig, false);
+    if (jStatus != AUDIO_JAVA_SUCCESS) {
+        return jStatus;
+    }
+    audio_attributes_t nAudioAttributes = {};
+    jStatus = convertAudioAttributesToNative(env, &nAudioAttributes, jAudioAttributes);
+    if (jStatus != AUDIO_JAVA_SUCCESS) {
+        return jStatus;
+    }
+    audio_port_handle_t handle;
+    status_t status = AudioSystem::startAudioSource(&nAudioPortConfig, &nAudioAttributes, &handle);
+    ALOGV("AudioSystem::startAudioSource() returned %d handle %d", status, handle);
+    return handle > 0 ? handle : nativeToJavaStatus(status);
+}
+
+static jint
+android_media_AudioSystem_stopAudioSource(JNIEnv *env, jobject clazz, jint handle)
+{
+    ALOGV("stopAudioSource");
+    status_t status = AudioSystem::stopAudioSource(
+            static_cast <audio_port_handle_t>(handle));
+    ALOGV("AudioSystem::stopAudioSource() returned %d", status);
+    return nativeToJavaStatus(status);
+}
+
 static void
 android_media_AudioSystem_eventHandlerSetup(JNIEnv *env, jobject thiz, jobject weak_this)
 {
@@ -1947,6 +2054,9 @@
                                                 (void *)android_media_AudioSystem_listAudioPatches},
     {"setAudioPortConfig",   "(Landroid/media/AudioPortConfig;)I",
                                             (void *)android_media_AudioSystem_setAudioPortConfig},
+    {"startAudioSource",    "(Landroid/media/AudioPortConfig;Landroid/media/AudioAttributes;)I",
+                                            (void *)android_media_AudioSystem_startAudioSource},
+    {"stopAudioSource",     "(I)I", (void *)android_media_AudioSystem_stopAudioSource},
     {"getAudioHwSyncForSession", "(I)I",
                                     (void *)android_media_AudioSystem_getAudioHwSyncForSession},
     {"registerPolicyMixes",    "(Ljava/util/ArrayList;Z)I",
@@ -2040,6 +2150,11 @@
     gAudioDevicePortCstor = GetMethodIDOrDie(env, audioDevicePortClass, "<init>",
             "(Landroid/media/AudioHandle;Ljava/lang/String;[I[I[I[I[Landroid/media/AudioGain;ILjava/lang/String;)V");
 
+    // When access AudioPort as AudioDevicePort
+    gAudioPortFields.mType = GetFieldIDOrDie(env, audioDevicePortClass, "mType", "I");
+    gAudioPortFields.mAddress = GetFieldIDOrDie(env, audioDevicePortClass, "mAddress",
+            "Ljava/lang/String;");
+
     jclass audioMixPortClass = FindClassOrDie(env, "android/media/AudioMixPort");
     gAudioMixPortClass = MakeGlobalRefOrDie(env, audioMixPortClass);
     gAudioMixPortCstor = GetMethodIDOrDie(env, audioMixPortClass, "<init>",
@@ -2120,6 +2235,11 @@
     gAudioAttributesClass = MakeGlobalRefOrDie(env, audioAttributesClass);
     gAudioAttributesFields.mUsage = GetFieldIDOrDie(env, audioAttributesClass, "mUsage", "I");
     gAudioAttributesFields.mSource = GetFieldIDOrDie(env, audioAttributesClass, "mSource", "I");
+    gAudioAttributesFields.mContentType = GetFieldIDOrDie(env,
+            audioAttributesClass, "mContentType", "I");
+    gAudioAttributesFields.mFlags = GetFieldIDOrDie(env, audioAttributesClass, "mFlags", "I");
+    gAudioAttributesFields.mFormattedTags = GetFieldIDOrDie(env,
+            audioAttributesClass, "mFormattedTags", "Ljava/lang/String;");
 
     AudioSystem::setErrorCallback(android_media_AudioSystem_error_callback);
 
diff --git a/core/jni/android_view_InputDevice.cpp b/core/jni/android_view_InputDevice.cpp
index 494fad7..a698d66 100644
--- a/core/jni/android_view_InputDevice.cpp
+++ b/core/jni/android_view_InputDevice.cpp
@@ -37,13 +37,13 @@
 } gInputDeviceClassInfo;
 
 jobject android_view_InputDevice_create(JNIEnv* env, const InputDeviceInfo& deviceInfo) {
-    ScopedLocalRef<jstring> nameObj(env, env->NewStringUTF(deviceInfo.getDisplayName().string()));
+    ScopedLocalRef<jstring> nameObj(env, env->NewStringUTF(deviceInfo.getDisplayName().c_str()));
     if (!nameObj.get()) {
         return NULL;
     }
 
     ScopedLocalRef<jstring> descriptorObj(env,
-            env->NewStringUTF(deviceInfo.getIdentifier().descriptor.string()));
+            env->NewStringUTF(deviceInfo.getIdentifier().descriptor.c_str()));
     if (!descriptorObj.get()) {
         return NULL;
     }
diff --git a/core/jni/android_view_TextureLayer.cpp b/core/jni/android_view_TextureLayer.cpp
index d3a447f..1ccb6a8 100644
--- a/core/jni/android_view_TextureLayer.cpp
+++ b/core/jni/android_view_TextureLayer.cpp
@@ -67,8 +67,7 @@
 static void TextureLayer_setSurfaceTexture(JNIEnv* env, jobject clazz,
         jlong layerUpdaterPtr, jobject surface) {
     DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerUpdaterPtr);
-    sp<GLConsumer> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, surface));
-    layer->setSurfaceTexture(surfaceTexture);
+    layer->setSurfaceTexture(SurfaceTexture_getSurfaceTexture(env, surface));
 }
 
 static void TextureLayer_updateSurfaceTexture(JNIEnv* env, jobject clazz,
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index 4a17742..3c59bd1 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -1024,6 +1024,9 @@
         // Continue I guess?
     }
     sk_sp<Bitmap> bitmap = Bitmap::createFrom(buffer);
+    // Bitmap::createFrom currently can only attach to a GraphicBuffer with PIXEL_FORMAT_RGBA_8888
+    // format and SRGB color space.
+    // To support any color space, we could extract it from BufferItem and pass it to Bitmap.
     return bitmap::createBitmap(env, bitmap.release(),
             android::bitmap::kBitmapCreateFlag_Premultiplied);
 }
diff --git a/core/jni/include/android_runtime/android_graphics_SurfaceTexture.h b/core/jni/include/android_runtime/android_graphics_SurfaceTexture.h
index c534d4b..0ad2587 100644
--- a/core/jni/include/android_runtime/android_graphics_SurfaceTexture.h
+++ b/core/jni/include/android_runtime/android_graphics_SurfaceTexture.h
@@ -23,14 +23,14 @@
 
 namespace android {
 
-class GLConsumer;
 class IGraphicBufferProducer;
+class SurfaceTexture;
 
 extern sp<ANativeWindow> android_SurfaceTexture_getNativeWindow(JNIEnv* env, jobject thiz);
 extern bool android_SurfaceTexture_isInstanceOf(JNIEnv* env, jobject thiz);
 
-/* Gets the underlying GLConsumer from a SurfaceTexture Java object. */
-extern sp<GLConsumer> SurfaceTexture_getSurfaceTexture(JNIEnv* env, jobject thiz);
+/* Gets the underlying C++ SurfaceTexture object from a SurfaceTexture Java object. */
+extern sp<SurfaceTexture> SurfaceTexture_getSurfaceTexture(JNIEnv* env, jobject thiz);
 
 /* gets the producer end of the SurfaceTexture */
 extern sp<IGraphicBufferProducer> SurfaceTexture_getProducer(JNIEnv* env, jobject thiz);
diff --git a/core/proto/android/providers/settings/secure.proto b/core/proto/android/providers/settings/secure.proto
index 6e661e1..3ead633 100644
--- a/core/proto/android/providers/settings/secure.proto
+++ b/core/proto/android/providers/settings/secure.proto
@@ -72,6 +72,9 @@
         // List of the accessibility services to which the user has granted
         // permission to put the device into touch exploration mode.
         optional SettingProto touch_exploration_granted_accessibility_services = 31;
+        optional SettingProto minimum_ui_timeout_enabled = 32 [ (android.privacy).dest = DEST_AUTOMATIC ];
+        optional SettingProto minimum_ui_timeout_ms = 33 [ (android.privacy).dest = DEST_AUTOMATIC ];
+
     }
     optional Accessibility accessibility = 2;
 
diff --git a/core/proto/android/server/windowmanagerservice.proto b/core/proto/android/server/windowmanagerservice.proto
index f1bd63b..1257336 100644
--- a/core/proto/android/server/windowmanagerservice.proto
+++ b/core/proto/android/server/windowmanagerservice.proto
@@ -271,7 +271,7 @@
     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 content_insets = 11 [deprecated=true];
     optional .android.graphics.RectProto surface_insets = 12;
     optional WindowStateAnimatorProto animator = 13;
     optional bool animating_exit = 14;
@@ -288,10 +288,10 @@
     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.graphics.RectProto overscan_insets = 29 [deprecated=true];
+    optional .android.graphics.RectProto visible_insets = 30 [deprecated=true];
+    optional .android.graphics.RectProto stable_insets = 31 [deprecated=true];
+    optional .android.graphics.RectProto outsets = 32 [deprecated=true];
     optional .android.view.DisplayCutoutProto cutout = 33 [deprecated=true];
     optional bool remove_on_exit = 34;
     optional bool destroying = 35;
@@ -380,4 +380,9 @@
     optional .android.graphics.RectProto parent_frame = 8;
     optional .android.graphics.RectProto visible_frame = 9;
     optional .android.view.DisplayCutoutProto cutout = 10;
+    optional .android.graphics.RectProto content_insets = 11;
+    optional .android.graphics.RectProto overscan_insets = 12;
+    optional .android.graphics.RectProto visible_insets = 13;
+    optional .android.graphics.RectProto stable_insets = 14;
+    optional .android.graphics.RectProto outsets = 15;
 }
diff --git a/core/proto/android/service/notification.proto b/core/proto/android/service/notification.proto
index 25059be..8836c2e 100644
--- a/core/proto/android/service/notification.proto
+++ b/core/proto/android/service/notification.proto
@@ -72,7 +72,8 @@
     option (android.msg_privacy).dest = DEST_AUTOMATIC;
 
     optional int32 hint = 1;
-    repeated ManagedServiceInfoProto listeners = 2;
+    reserved 2; // ManagedServiceInfoProto listeners
+    repeated android.content.ComponentNameProto listener_components = 3;
 }
 
 message ManagedServiceInfoProto {
@@ -199,6 +200,7 @@
     optional string condition_id = 8;
     optional ConditionProto condition = 9;
     optional android.content.ComponentNameProto component = 10;
+    optional ZenPolicyProto zenPolicy = 11;
 }
 
 // A dump from com.android.server.notification.ZenModeHelper.
@@ -211,3 +213,47 @@
     repeated android.content.ComponentNameProto suppressors = 4;
     optional android.app.PolicyProto policy = 5;
 }
+
+// An android.service.notification.ZenPolicy object
+message ZenPolicyProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+    enum State {
+        STATE_UNSET = 0;
+        STATE_ALLOW = 1;
+        STATE_DISALLOW = 2;
+    }
+
+    // Notifications and sounds allowed/disallowed when DND is active
+    optional State reminders = 1;
+    optional State events = 2;
+    optional State messages = 3;
+    optional State calls = 4;
+    optional State repeat_callers = 5;
+    optional State alarms = 6;
+    optional State media = 7;
+    optional State system = 8;
+
+    // Visual effects allowed/disallowed for intercepted notifications when DND is active
+    optional State full_screen_intent = 9;
+    optional State lights = 10;
+    optional State peek = 11;
+    optional State status_bar = 12;
+    optional State badge= 13;
+    optional State ambient = 14;
+    optional State notification_list = 15;
+
+    enum Sender {
+        SENDER_UNSET = 0;
+        // Any sender is prioritized.
+        SENDER_ANY = 1;
+        // Saved contacts are prioritized.
+        SENDER_CONTACTS = 2;
+        // Only starred contacts are prioritized.
+        SENDER_STARRED = 3;
+        // No calls/messages are prioritized.
+        SENDER_NONE = 4;
+    }
+    optional Sender priority_calls = 16;
+    optional Sender priority_messages = 17;
+}
diff --git a/core/proto/android/service/procstats.proto b/core/proto/android/service/procstats.proto
index 736871f..ce19ce3 100644
--- a/core/proto/android/service/procstats.proto
+++ b/core/proto/android/service/procstats.proto
@@ -21,6 +21,7 @@
 option java_outer_classname = "ProcessStatsServiceProto";
 
 import "frameworks/base/core/proto/android/util/common.proto";
+import "frameworks/base/core/proto/android/service/procstats_enum.proto";
 import "frameworks/base/libs/incident/proto/android/privacy.proto";
 
 /**
@@ -86,55 +87,12 @@
 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
@@ -189,74 +147,85 @@
     optional ProcessStatsStateProto total_running_state = 6;
 }
 
-// Next Tag: 7
-message ProcessStatsServiceStateProto {
+// Next Tag: 4
+message PackageServiceOperationStatsProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+    // Operate enum: Started, Foreground, Bound, Executing
+    optional ServiceOperationState operation = 1;
+
+    // Number of times the service was in this operation.
+    optional int32 count = 2;
+
+    // Information about a state the service can be in.
+    message StateStats {
+        option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+        // Screen state enum.
+        optional android.service.procstats.ScreenState screen_state = 1;
+        // Memory state enum.
+        optional android.service.procstats.MemoryState memory_state = 2;
+
+        // duration in milliseconds.
+        optional int64 duration_ms = 3;
+        // Millisecond elapsed realtime duration spent in this state
+        optional int64 realtime_duration_ms = 4;
+    }
+    repeated StateStats state_stats = 3;
+}
+
+// Next Tag: 3
+message PackageServiceStatsProto {
     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;
-
-        // Number of times the service was in this operation.
-        optional int32 count = 1;
-
-        // Time this operation was active in various states.  process_state will not be set;
-        // includes only uptime, not memory info.
-        repeated ProcessStatsStateProto states = 2;
-    }
-
-    // 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;
+    // The operation stats.
+    // The package_name, package_uid, package_version, service_name will not be set to save space.
+    repeated PackageServiceOperationStatsProto operation_stats = 2;
 }
 
 // Next Tag: 7
-message ProcessStatsAssociationStateProto {
+message PackageAssociationSourceProcessStatsProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+    // Uid of the process.
+    optional int32 process_uid = 1;
+    // Process name.
+    optional string process_name = 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;
+
+    // Information on one source in this association.
+    message StateStats {
+        option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+        // Process state enum.
+        optional android.service.procstats.ProcessState process_state = 1;
+        // Millisecond uptime duration spent in this state
+        optional int64 duration_ms = 2;
+        // Millisecond elapsed realtime duration spent in this state
+        optional int64 realtime_duration_ms = 3;
+    }
+    repeated StateStats active_state_stats = 6;
+}
+
+// Next Tag: 3
+message PackageAssociationProcessStatsProto {
     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;
+    repeated PackageAssociationSourceProcessStatsProto sources = 2;
 }
 
 // Next Tag: 7
@@ -276,8 +245,8 @@
     repeated ProcessStatsProto process_stats = 4;
 
     // Stats for each of the package's services.
-    repeated ProcessStatsServiceStateProto service_stats = 5;
+    repeated PackageServiceStatsProto service_stats = 5;
 
     // Stats for each association with the package.
-    repeated ProcessStatsAssociationStateProto association_stats = 6;
+    repeated PackageAssociationProcessStatsProto association_stats = 6;
 }
diff --git a/core/proto/android/service/procstats_enum.proto b/core/proto/android/service/procstats_enum.proto
new file mode 100644
index 0000000..cc3fe5a
--- /dev/null
+++ b/core/proto/android/service/procstats_enum.proto
@@ -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.
+ */
+
+syntax = "proto2";
+package android.service.procstats;
+
+option java_multiple_files = true;
+option java_outer_classname = "ProcessStatsEnums";
+
+enum ScreenState {
+    SCREEN_STATE_UNKNOWN = 0;
+    SCREEN_STATE_OFF = 1;
+    SCREEN_STATE_ON = 2;
+}
+
+enum MemoryState {
+    MEMORY_STATE_UNKNOWN = 0;
+    MEMORY_STATE_NORMAL = 1;     // normal.
+    MEMORY_STATE_MODERATE = 2;   // moderate memory pressure.
+    MEMORY_STATE_LOW = 3;        // low memory.
+    MEMORY_STATE_CRITICAL = 4;   // critical memory.
+}
+
+// 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_STATE_UNKNOWN = 0;
+    // Persistent system process.
+    PROCESS_STATE_PERSISTENT = 1;
+    // Top activity; actually any visible activity.
+    PROCESS_STATE_TOP = 2;
+    // Important foreground process (ime, wallpaper, etc).
+    PROCESS_STATE_IMPORTANT_FOREGROUND = 3;
+    // Important background process.
+    PROCESS_STATE_IMPORTANT_BACKGROUND = 4;
+    // Performing backup operation.
+    PROCESS_STATE_BACKUP = 5;
+    // Background process running a service.
+    PROCESS_STATE_SERVICE = 6;
+    // Process not running, but would be if there was enough RAM.
+    PROCESS_STATE_SERVICE_RESTARTING = 7;
+    // Process running a receiver.
+    PROCESS_STATE_RECEIVER = 8;
+    // Heavy-weight process (currently not used).
+    PROCESS_STATE_HEAVY_WEIGHT = 9;
+    // Process hosting home/launcher app when not on top.
+    PROCESS_STATE_HOME = 10;
+    // Process hosting the last app the user was in.
+    PROCESS_STATE_LAST_ACTIVITY = 11;
+    // Cached process hosting a previous activity.
+    PROCESS_STATE_CACHED_ACTIVITY = 12;
+    // Cached process hosting a client activity.
+    PROCESS_STATE_CACHED_ACTIVITY_CLIENT = 13;
+    // Cached process that is empty.
+    PROCESS_STATE_CACHED_EMPTY = 14;
+}
+
+enum ServiceOperationState {
+    SERVICE_OPERATION_STATE_UNKNOWN = 0;
+    SERVICE_OPERATION_STATE_RUNNING = 1;
+    SERVICE_OPERATION_STATE_STARTED = 2;
+    SERVICE_OPERATION_STATE_FOREGROUND = 3;
+    SERVICE_OPERATION_STATE_BOUND = 4;
+    SERVICE_OPERATION_STATE_EXECUTING = 5;
+}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 5258518..2bf16d3 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -584,7 +584,7 @@
     <protected-broadcast android:name="android.media.tv.action.PREVIEW_PROGRAM_BROWSABLE_DISABLED" />
     <protected-broadcast android:name="android.media.tv.action.WATCH_NEXT_PROGRAM_BROWSABLE_DISABLED" />
     <protected-broadcast android:name="android.media.tv.action.CHANNEL_BROWSABLE_REQUESTED" />
-    <protected-broadcast android:name="com.android.server.InputMethodManagerService.SHOW_INPUT_METHOD_PICKER" />
+    <protected-broadcast android:name="com.android.server.inputmethod.InputMethodManagerService.SHOW_INPUT_METHOD_PICKER" />
 
     <!-- Time zone rules update intents fired by the system server -->
     <protected-broadcast android:name="com.android.intent.action.timezone.RULES_UPDATE_OPERATION" />
@@ -3345,14 +3345,14 @@
           @hide
           @removed -->
     <permission android:name="android.permission.CAPTURE_VIDEO_OUTPUT"
-        android:protectionLevel="signature" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Allows an application to capture secure video output.
          <p>Not for use by third-party applications.</p>
           @hide
           @removed -->
     <permission android:name="android.permission.CAPTURE_SECURE_VIDEO_OUTPUT"
-        android:protectionLevel="signature" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to know what content is playing and control its playback.
          <p>Not for use by third-party applications due to privacy of media consumption</p>  -->
@@ -3756,6 +3756,10 @@
     <permission android:name="android.permission.USE_BIOMETRIC_INTERNAL"
         android:protectionLevel="signature" />
 
+    <!-- Allows the system to control the BiometricDialog (SystemUI). Reserved for the system. @hide -->
+    <permission android:name="android.permission.MANAGE_BIOMETRIC_DIALOG"
+        android:protectionLevel="signature" />
+
     <!-- Allows an app to reset face authentication attempt counter. Reserved for the system. @hide -->
     <permission android:name="android.permission.RESET_FACE_LOCKOUT"
         android:protectionLevel="signature" />
@@ -4120,11 +4124,6 @@
     <permission android:name="android.permission.DISABLE_HIDDEN_API_CHECKS"
                 android:protectionLevel="signature" />
 
-    <!-- Allows an application to read emergency info name.
-         @hide <p>Not for use by third-party applications. -->
-    <permission android:name="com.android.emergency.permission.READ_EMERGENCY_INFO_NAME"
-                android:protectionLevel="signature" />
-
     <application android:process="system"
                  android:persistent="true"
                  android:hasCode="false"
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index e136d2e..c2c9254 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -514,6 +514,7 @@
     <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="biometric_error_hw_unavailable" msgid="645781226537551036">"Biometriese hardeware is nie beskikbaar nie"</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>
@@ -521,7 +522,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Vinger is te stadig beweer. Probeer asseblief weer."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Nie herken nie"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"Nie herken nie"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Vingerafdruk is gestaaf"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Vingerafdrukhardeware is nie beskikbaar nie."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Vingerafdruk kan nie gestoor word nie. Verwyder asseblief \'n bestaande vingerafdruk."</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 5a7e643..45f962b 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -514,6 +514,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"መተግበሪያው የፎቶ ስብስብዎን እንዲቀይረው ያስችለዋል።"</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"አካባቢዎችን ከሚዲያ ስብስብዎ ማንበብ"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"መተግበሪያው አካባቢዎችን ከሚዲያ ስብስብዎ እንዲያነብብ ያስችለዋል።"</string>
+    <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"ባዮሜትራዊ ሃርድዌር አይገኝም"</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,7 +522,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"ጣት ከልክ በላይ ተንቀራፎ ተንቀሳቅሷል። እባክዎ እንደገና ይሞክሩ።"</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"አልታወቀም"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"አልታወቀም"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"የጣት አሻራ ትክክለኛነት ተረጋግጧል"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"የጣት አሻራ ሃርድዌር አይገኝም።"</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"የጣት አሻራ ሊከማች አይችልም። እባክዎ አሁን ያለውን የጣት አሻራ ያስወግዱ።"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index d46f758..bbdea6a 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -526,6 +526,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"للسماح للتطبيق بتعديل مجموعة صورك."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"قراءة المواقع من مجموعة الوسائط التابعة لك"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"للسماح للتطبيق بقراءة المواقع من مجموعة الوسائط التابعة لك."</string>
+    <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"معدّات المقاييس الحيوية غير متاحة."</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>
@@ -533,7 +534,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"تم تحريك الإصبع ببطء شديد. يُرجى إعادة المحاولة."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"لم يتم التعرف عليها"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"لم يتم التعرف عليها."</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"تم مصادقة بصمة الإصبع"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"جهاز بصمة الإصبع غير متاح."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"يتعذر تخزين بصمة الإصبع؛ يرجى إزالة إحدى البصمات المخزنة."</string>
diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml
index 10b7da43..48d44b0 100644
--- a/core/res/res/values-as/strings.xml
+++ b/core/res/res/values-as/strings.xml
@@ -514,6 +514,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"এপক আপোনাৰ ফট’ সংগ্ৰহ সালসলনি কৰিবলৈ দিয়ে।"</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"আপোনাৰ মিডিয়া সংগ্ৰহৰ অৱস্থান পঢ়িবলৈ"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"এপক আপোনাৰ মিডিয়া সংগ্ৰহৰ অৱস্থান পঢ়িবলৈ দিয়ে।"</string>
+    <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"বায়োমেট্ৰিক হাৰ্ডৱেৰ উপলব্ধ নহয়"</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,7 +522,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"আঙুলিৰ গতি অতি মন্থৰ আছিল। অনুগ্ৰহ কৰি আকৌ চেষ্টা কৰক৷"</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"চিনাক্ত কৰিবপৰা নগ\'ল"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"চিনাক্ত কৰিব পৰা নাই"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"ফিংগাৰপ্ৰিণ্টৰ সত্যাপন কৰা হ’ল"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"ফিংগাৰপ্ৰিণ্ট হাৰ্ডৱেৰ নাই।"</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"ফিংগাৰপ্ৰিণ্ট সঞ্চয় কৰিব পৰা নগ\'ল। পূর্বে সঞ্চিত ফিংগাৰপ্ৰিণ্ট এটা আঁতৰাওক।"</string>
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index 6464c61..44bcd56 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -514,6 +514,7 @@
     <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="biometric_error_hw_unavailable" msgid="645781226537551036">"Biometrik proqram əlçatan deyil"</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>
@@ -521,7 +522,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Barmağınızı çox yavaş hərəkət etdirdiniz. Lütfən, yenidən cəhd edin."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Tanınmır"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"Tanınmır"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Barmaq izi doğrulandı"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Barmaq izi üçün avadanlıq yoxdur."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Barmaq izi saxlana bilməz. Lütfən, mövcud barmaq izini silin."</string>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index 4d31b1b..260f63e 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -517,6 +517,7 @@
     <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="biometric_error_hw_unavailable" msgid="645781226537551036">"Biometrijski hardver nije dostupan"</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>
@@ -524,7 +525,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Previše sporo ste pomerili prst. Probajte ponovo."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Nije prepoznat"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"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 otiske prstiju nije dostupan."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Nije moguće sačuvati otisak prsta. Uklonite neki od postojećih otisaka prstiju."</string>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 77223d7..3d46662 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -520,6 +520,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Праграма зможа змяняць фотакалекцыю."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"паказваць месцазнаходжанне ў калекцыі мультымедыя"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Праграма зможа паказваць месцазнаходжанне ў калекцыі мультымедыя."</string>
+    <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"Біяметрычнае абсталяванне недаступнае"</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,7 +528,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Палец рухаўся занадта павольна. Паспрабуйце яшчэ раз."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Не распазнаны"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"Не распазнана"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Адбітак пальца распазнаны"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Апаратныя сродкі адбіткаў пальцаў недаступныя."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Адбіткі пальцаў нельга захаваць. Выдаліце існы адбітак."</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 3fc31f0..e9ecba6 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -514,6 +514,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Разрешава на приложението да променя колекцията ви от снимки."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"да чете местоположенията от мултимедийната ви колекция"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Разрешава на приложението да чете местоположенията от мултимедийната ви колекция."</string>
+    <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"Биометричният хардуер не е налице"</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,7 +522,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Преместихте пръста си твърде бавно. Моля, опитайте отново."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Не е разпознато"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"Не е разпознато"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Отпечатъкът е удостоверен"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Хардуерът за отпечатъци не е налице."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Отпечатъкът не може да бъде съхранен. Моля, премахнете съществуващ."</string>
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index e7990ca..4ece21b 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -514,6 +514,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"অ্যাপকে আপনার ফটো সংগ্রহ পরিবর্তন করার অনুমতি দিন।"</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"ডিয়া সংগ্রহ থেকে লোকেশন দেখতে দিন"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"আপনার মিডিয়া সংগ্রহ থেকে লোকেশন দেখতে অ্যাপকে অনুমতি দিন।"</string>
+    <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"বায়োমেট্রিক হার্ডওয়্যার পাওয়া যাবে না"</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,7 +522,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"আঙ্গুল খুব ধীরে সরানো হয়েছে৷ অনুগ্রহ করে আবার চেষ্টা করুন৷"</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"স্বীকৃত নয়"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"স্বীকৃত নয়"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"আঙ্গুলের ছাপ যাচাই করা হয়েছে"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"আঙ্গুলের ছাপ নেওয়ার হার্ডওয়্যার অনুপলব্ধ৷"</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"আঙ্গুলের ছাপ সংরক্ষণ করা যাবে না৷ অনুগ্রহ করে একটি বিদ্যমান আঙ্গুলের ছাপ সরান৷"</string>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index 244af73..918ecf9 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -517,6 +517,7 @@
     <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="biometric_error_hw_unavailable" msgid="645781226537551036">"Biometrijski hardver nije dostupan"</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>
@@ -524,7 +525,7 @@
     <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 prepoznato"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"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>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 2c74e82..f6c46ba 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -216,7 +216,7 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Opcions del telèfon"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Bloqueig de pantalla"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Apaga"</string>
-    <string name="global_action_emergency" msgid="7112311161137421166">"Emergències"</string>
+    <string name="global_action_emergency" msgid="7112311161137421166">"Emergència"</string>
     <string name="global_action_bug_report" msgid="7934010578922304799">"Informe d\'error"</string>
     <string name="global_action_logout" msgid="935179188218826050">"Finalitza la sessió"</string>
     <string name="global_action_screenshot" msgid="8329831278085426283">"Captura de pantalla"</string>
@@ -514,6 +514,7 @@
     <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="biometric_error_hw_unavailable" msgid="645781226537551036">"Maquinari biomètric no disponible"</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>
@@ -521,7 +522,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"El dit s\'ha mogut massa lentament. Torna-ho a provar."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"No s\'ha reconegut"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"No s\'ha reconegut"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"L\'empremta digital s\'ha autenticat"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"El maquinari per a empremtes digitals no està disponible."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"L\'empremta digital no es pot desar. Suprimeix-ne una."</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 278ab957..e882f42 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -520,6 +520,7 @@
     <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="biometric_error_hw_unavailable" msgid="645781226537551036">"Biometrický hardware není k dispozici"</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>
@@ -527,7 +528,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Pohyb prstem byl příliš pomalý. Zkuste to znovu."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Nerozpoznáno"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"Nerozpoznáno"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Otisk byl ověřen"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Není k dispozici hardware ke snímání otisků prstů."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Otisk prstu nelze uložit. Odstraňte existující otisk prstu."</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 32be0d3..9a793a8 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -383,13 +383,13 @@
     <string name="permdesc_broadcastSticky" product="tv" msgid="6839285697565389467">"Giver appen lov til at sende klæbende udsendelser, som ikke forsvinder, når udsendelsen er slut. Overdreven brug kan gøre fjernsynet langsomt eller ustabilt ved at få det til at bruge for meget hukommelse."</string>
     <string name="permdesc_broadcastSticky" product="default" msgid="2825803764232445091">"Tillader, at appen kan sende klæbende udsendelser, der forbliver tilbage, når udsendelsen er slut. Overdreven brug kan gøre din telefon langsom eller ustabil ved at tvinge den til at bruge for meget hukommelse."</string>
     <string name="permlab_readContacts" msgid="8348481131899886131">"læse dine kontaktpersoner"</string>
-    <string name="permdesc_readContacts" product="tablet" msgid="5294866856941149639">"Tillader, at appen kan læse data om de kontaktpersoner, der er gemt på din tablet, f.eks. hvor ofte du har ringet til, sendt mail til eller på anden måde kommunikeret med bestemte personer. Med denne tilladelse kan apps gemme dine kontaktdata, og skadelige apps kan dele kontaktdata uden din viden."</string>
-    <string name="permdesc_readContacts" product="tv" msgid="1839238344654834087">"Giver appen lov til at læse data om dine kontaktpersoner, der er gemt på dit tv, herunder hvor ofte du har ringet, mailet eller på andre måder kommunikeret med bestemte personer. Denne tilladelse gør det muligt for apps at gemme dine kontaktoplysninger, og ondsindede apps kan dele kontaktoplysninger uden din viden."</string>
-    <string name="permdesc_readContacts" product="default" msgid="8440654152457300662">"Tillader, at appen kan læse data om de kontaktpersoner, der er gemt på din telefon, f.eks. hvor ofte du har ringet til, sendt mail til eller på anden måde kommunikeret med bestemte personer. Med denne tilladelse kan apps gemme dine kontaktdata, og skadelige apps kan dele kontaktdata uden din viden."</string>
+    <string name="permdesc_readContacts" product="tablet" msgid="5294866856941149639">"Tillader, at appen kan læse data om de kontakter, der er gemt på din tablet, f.eks. hvor ofte du har ringet til, sendt mail til eller på anden måde kommunikeret med bestemte personer. Med denne tilladelse kan apps gemme dine kontaktdata, og skadelige apps kan dele kontaktdata uden din viden."</string>
+    <string name="permdesc_readContacts" product="tv" msgid="1839238344654834087">"Giver appen lov til at læse data om dine kontakter, der er gemt på dit tv, herunder hvor ofte du har ringet, mailet eller på andre måder kommunikeret med bestemte personer. Denne tilladelse gør det muligt for apps at gemme dine kontaktoplysninger, og ondsindede apps kan dele kontaktoplysninger uden din viden."</string>
+    <string name="permdesc_readContacts" product="default" msgid="8440654152457300662">"Tillader, at appen kan læse data om de kontakter, der er gemt på din telefon, f.eks. hvor ofte du har ringet til, sendt mail til eller på anden måde kommunikeret med bestemte personer. Med denne tilladelse kan apps gemme dine kontaktdata, og skadelige apps kan dele kontaktdata uden din viden."</string>
     <string name="permlab_writeContacts" msgid="5107492086416793544">"ændre dine kontaktpersoner"</string>
-    <string name="permdesc_writeContacts" product="tablet" msgid="897243932521953602">"Tillader, at appen kan ændre data om de kontaktpersoner, der er gemt på din tablet, f.eks. hvor ofte du har ringet til dem, sendt dem en mail eller på anden måde kommunikeret med bestemte kontaktpersoner. Med denne tilladelse kan apps slette kontaktoplysninger."</string>
-    <string name="permdesc_writeContacts" product="tv" msgid="5438230957000018959">"Giver appen lov til at ændre data om dine kontaktpersoner, der er gemt på dit tv, herunder hvor ofte du har ringet, mailet eller på anden måde kommunikeret med bestemte kontaktpersoner. Denne tilladelse gør det muligt for apps at slette kontaktoplysninger."</string>
-    <string name="permdesc_writeContacts" product="default" msgid="589869224625163558">"Tillader, at appen kan ændre data om de kontaktpersoner, der er gemt på din telefon, f.eks. hvor ofte du har ringet til dem, sendt en mail til dem eller på anden måde kommunikeret med bestemte kontaktpersoner. Med denne tilladelse kan apps slette kontaktoplysninger."</string>
+    <string name="permdesc_writeContacts" product="tablet" msgid="897243932521953602">"Tillader, at appen kan ændre data om de kontakter, der er gemt på din tablet, f.eks. hvor ofte du har ringet til dem, sendt dem en mail eller på anden måde kommunikeret med bestemte kontakter. Med denne tilladelse kan apps slette kontaktoplysninger."</string>
+    <string name="permdesc_writeContacts" product="tv" msgid="5438230957000018959">"Giver appen lov til at ændre data om dine kontakter, der er gemt på dit tv, herunder hvor ofte du har ringet, mailet eller på anden måde kommunikeret med bestemte kontakter. Denne tilladelse gør det muligt for apps at slette kontaktoplysninger."</string>
+    <string name="permdesc_writeContacts" product="default" msgid="589869224625163558">"Tillader, at appen kan ændre data om de kontakter, der er gemt på din telefon, f.eks. hvor ofte du har ringet til dem, sendt en mail til dem eller på anden måde kommunikeret med bestemte kontakter. Med denne tilladelse kan apps slette kontaktoplysninger."</string>
     <string name="permlab_readCallLog" msgid="3478133184624102739">"læse opkaldsliste"</string>
     <string name="permdesc_readCallLog" msgid="3204122446463552146">"Denne app kan læse din opkaldshistorik."</string>
     <string name="permlab_writeCallLog" msgid="8552045664743499354">"skriv opkaldsliste"</string>
@@ -514,6 +514,7 @@
     <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="biometric_error_hw_unavailable" msgid="645781226537551036">"Biometrisk hardware er ikke tilgængelig"</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,7 +522,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Du bevægede fingeren for langsomt. Prøv igen."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Ikke genkendt"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"Ikke genkendt"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Fingeraftrykket blev godkendt"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Hardwaren til fingeraftryk er ikke tilgængelig."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Fingeraftrykket kan ikke gemmes. Fjern et eksisterende fingeraftryk."</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index e5b9372..8eb0eb8 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -514,6 +514,7 @@
     <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="biometric_error_hw_unavailable" msgid="645781226537551036">"Biometrische Hardware nicht verfügbar"</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>
@@ -521,7 +522,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Finger zu langsam bewegt. Versuche es erneut."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Nicht erkannt"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"Nicht erkannt"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Fingerabdruck wurde authentifiziert"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Fingerabdruckhardware nicht verfügbar"</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Fingerabdruck kann nicht gespeichert werden. Entferne einen vorhandenen Fingerabdruck."</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 482e29f..3a50f9e 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -514,6 +514,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Επιτρέπει στην εφαρμογή να τροποποιήσει τη συλλογή φωτογραφιών σας."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"ανάγνωση τοποθεσιών από τη συλλογή πολυμέσων σας"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Επιτρέπει στην εφαρμογή να διαβάσει τοποθεσίες από τη συλλογή πολυμέσων σας."</string>
+    <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"Δεν υπάρχει διαθέσιμος βιομετρικός εξοπλισμός"</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,7 +522,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Πολύ αργή κίνηση δαχτύλου. Δοκιμάστε ξανά."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Δεν αναγνωρίστηκε"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"Δεν αναγνωρίστηκε"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Η ταυτότητα του δακτυλικού αποτυπώματος ελέγχθηκε"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Ο εξοπλισμός μοναδικού χαρακτηριστικού δεν είναι διαθέσιμος."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Δεν είναι δυνατή η αποθήκευση μοναδικού χαρακτηριστικού. Καταργήστε το υπάρχον μοναδικό χαρακτηριστικό."</string>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index 19d0916..04b20ba 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -514,6 +514,7 @@
     <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="biometric_error_hw_unavailable" msgid="645781226537551036">"Biometric hardware unavailable"</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>
@@ -521,7 +522,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Finger moved too slow. Please try again."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Not recognised"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"Not recognised"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Fingerprint authenticated"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Fingerprint hardware not available."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Fingerprint can\'t be stored. Please remove an existing fingerprint."</string>
diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml
index 1e2e081..c1ca0c4 100644
--- a/core/res/res/values-en-rCA/strings.xml
+++ b/core/res/res/values-en-rCA/strings.xml
@@ -514,6 +514,7 @@
     <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="biometric_error_hw_unavailable" msgid="645781226537551036">"Biometric hardware unavailable"</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>
@@ -521,7 +522,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Finger moved too slow. Please try again."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Not recognised"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"Not recognised"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Fingerprint authenticated"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Fingerprint hardware not available."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Fingerprint can\'t be stored. Please remove an existing fingerprint."</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 19d0916..04b20ba 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -514,6 +514,7 @@
     <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="biometric_error_hw_unavailable" msgid="645781226537551036">"Biometric hardware unavailable"</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>
@@ -521,7 +522,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Finger moved too slow. Please try again."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Not recognised"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"Not recognised"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Fingerprint authenticated"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Fingerprint hardware not available."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Fingerprint can\'t be stored. Please remove an existing fingerprint."</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 19d0916..04b20ba 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -514,6 +514,7 @@
     <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="biometric_error_hw_unavailable" msgid="645781226537551036">"Biometric hardware unavailable"</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>
@@ -521,7 +522,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Finger moved too slow. Please try again."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Not recognised"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"Not recognised"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Fingerprint authenticated"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Fingerprint hardware not available."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Fingerprint can\'t be stored. Please remove an existing fingerprint."</string>
diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml
index 68bc261..4add775 100644
--- a/core/res/res/values-en-rXC/strings.xml
+++ b/core/res/res/values-en-rXC/strings.xml
@@ -514,6 +514,7 @@
     <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="biometric_error_hw_unavailable" msgid="645781226537551036">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‎‎‏‏‏‏‎‏‏‎‎‏‎‎‎‏‏‎‏‎‎‏‏‎‏‎‏‎‏‎‎‎‏‎‎‏‏‎‎‎‏‏‎‎‎‎‎‏‎‎‏‎‏‏‏‏‎‎‎Biometric hardware unavailable‎‏‎‎‏‎"</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>
@@ -521,7 +522,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‎‎‏‏‎‏‎‎‏‎‏‎‎‎‎‎‎‎‎‏‎‏‏‏‎‏‏‏‎‏‏‎‏‎‎‎‏‎‏‎‎‎‏‏‎‏‏‎‎‎‏‏‎‏‎‏‎‏‎Finger moved too slow. Please try again.‎‏‎‎‏‎"</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‎‏‎‏‎‏‎‏‏‏‎‎‏‎‎‏‏‎‏‎‏‏‏‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‎‎‎‎‎‎‎‎‏‏‏‎‏‎‏‏‏‎‎‏‎Not recognized‎‏‎‎‏‎"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‎‎‎‎‎‏‎‏‎‎‏‏‏‏‏‎‎‏‏‏‏‎‎‎‏‎‎‏‏‏‎‎‏‏‎‏‎‎‏‏‎‎‎‎‎‎‏‎‎‏‎‏‎‏‎‎‏‎‎Not recognized‎‏‎‎‏‎"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‏‏‎‏‎‏‏‏‎‏‎‎‎‏‎‏‏‎‎‏‎‎‎‎‎‏‎‏‎‎‎‏‎‏‏‎‎‎‏‏‎‏‎‎‎‎‎‏‎‏‏‏‏‎‎‎‎‎Fingerprint authenticated‎‏‎‎‏‎"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‏‎‎‏‏‎‏‎‎‏‎‎‎‏‏‏‎‎‏‎‎‏‏‎‎‎‏‎‏‏‎‏‎‏‏‏‏‏‎‎‏‏‏‎‎‎‏‏‏‏‎‏‎‏‎‏‎‎‎Fingerprint hardware not available.‎‏‎‎‏‎"</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‎‏‎‏‎‎‏‏‏‎‎‎‎‎‏‎‏‏‏‎‎‏‎‎‏‏‎‎‏‏‏‎‏‎‎‏‏‏‎‎‏‏‏‏‎‎‏‎‏‏‏‎‎‎‏‏‎‎Fingerprint can\'t be stored. Please remove an existing fingerprint.‎‏‎‎‏‎"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 9969af3..f317a4e 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -514,6 +514,7 @@
     <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="biometric_error_hw_unavailable" msgid="645781226537551036">"No hay hardware biométrico disponible"</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>
@@ -521,7 +522,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Moviste el dedo muy lento. Vuelve a intentarlo."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"No reconocido"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"No se reconoció"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Se autenticó la huella digital"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"El hardware para detectar huellas digitales no está disponible."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"No se puede almacenar la huella digital. Elimina una de las existentes."</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index e40a546..c42f53c 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -514,6 +514,7 @@
     <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="biometric_error_hw_unavailable" msgid="645781226537551036">"Hardware biométrico no disponible"</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,7 +522,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Has movido el dedo demasiado despacio. Vuelve a intentarlo."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"No reconocido"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"No se reconoce"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Se ha autenticado la huella digital"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"El hardware de huella digital no está disponible."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"No se puede almacenar la huella digital. Elimina una ya creada."</string>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index 56181c8..cc052c4 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -514,6 +514,7 @@
     <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="biometric_error_hw_unavailable" msgid="645781226537551036">"Biomeetriline riistvara ei ole saadaval"</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>
@@ -521,7 +522,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Sõrm liikus liiga aeglaselt. Proovige uuesti."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Ei tuvastatud"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"Ei tuvastatud"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Sõrmejälg autenditi"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Sõrmejälje riistvara pole saadaval."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Sõrmejälge ei saa salvestada. Eemaldage olemasolev sõrmejälg."</string>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index 5ec5637..275e171 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -514,6 +514,7 @@
     <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="biometric_error_hw_unavailable" msgid="645781226537551036">"Hardware biometrikoa ez dago erabilgarri"</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>
@@ -521,7 +522,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Mantsoegi mugitu duzu hatza. Saiatu berriro."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Ez da ezagutzen"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"Ez da ezagutu"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Autentifikatu da hatz-marka"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Hatz-markaren hardwarea ez dago erabilgarri."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Ezin da gorde hatz-marka digitala. Kendu lehendik gordeta duzunetako bat."</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index b64937c..5055e8b 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -514,6 +514,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"به برنامه اجازه می‌دهد مجموعه عکستان را تغییر دهد."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"خواندن مکان‌ها از مجموعه رسانه شما"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"به برنامه اجازه می‌دهد مکان‌ها را از مجموعه رسانه‌تان بخواند."</string>
+    <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"سخت‌افزار زیست‌سنجی دردسترس نیست"</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,7 +522,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"حرکت انگشت خیلی آهسته بود. لطفاً دوباره امتحان کنید."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"شناخته نشد"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"شناسایی نشد"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"اثر انگشت احراز هویت شد"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"سخت‌افزار اثرانگشت در دسترس نیست."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"ذخیره اثر انگشت ممکن نیست. لطفاً یک اثر انگشت موجود را حذف کنید."</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index e13a01f..d54cb72 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -514,6 +514,7 @@
     <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="biometric_error_hw_unavailable" msgid="645781226537551036">"Biometrinen laitteisto ei käytettävissä"</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>
@@ -521,7 +522,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Liikutit sormea liian hitaasti. Yritä uudelleen."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Ei tunnistettu"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"Ei tunnistettu"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Sormenjälki tunnistettu"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Sormenjälkilaitteisto ei ole käytettävissä."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Sormenjälkeä ei voida tallentaa. Poista aiemmin lisätty sormenjälki."</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 2409202..0c0cdea 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -253,7 +253,7 @@
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"Alertes réseau"</string>
     <string name="notification_channel_network_available" msgid="4531717914138179517">"Réseau accessible"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"État du RPV"</string>
-    <string name="notification_channel_device_admin" msgid="1568154104368069249">"Administration d\'appareils"</string>
+    <string name="notification_channel_device_admin" msgid="1568154104368069249">"Gestion de l\'appareil"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Alertes"</string>
     <string name="notification_channel_retail_mode" msgid="6088920674914038779">"Démo en magasin"</string>
     <string name="notification_channel_usb" msgid="9006850475328924681">"Connexion USB"</string>
@@ -514,6 +514,7 @@
     <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="biometric_error_hw_unavailable" msgid="645781226537551036">"Matériel biométrique indisponible"</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>
@@ -521,7 +522,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Vous avez déplacé votre doigt trop lentement. Veuillez réessayer."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Doigt non reconnu"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"Données biométriques non reconnues"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Empreinte digitale authentifiée"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Matériel d\'empreinte numérique indisponible."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"L\'empreinte digitale ne peut pas être enregistrée. Veuillez supprimer une empreinte existante."</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 9c8a7e7..e153082 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -284,7 +284,7 @@
     <string name="permgrouprequest_sms" msgid="7168124215838204719">"Permettre à &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; d\'envoyer et d\'afficher des SMS ?"</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Stockage"</string>
     <string name="permgroupdesc_storage" msgid="637758554581589203">"accéder à des photos, à des contenus multimédias et à des fichiers sur votre appareil"</string>
-    <string name="permgrouprequest_storage" msgid="7885942926944299560">"Permettre à &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; d\'accéder aux photos, contenus multimédias et fichiers sur votre appareil ?"</string>
+    <string name="permgrouprequest_storage" msgid="7885942926944299560">"Autoriser &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; à accéder aux photos, contenus multimédias et fichiers sur votre appareil ?"</string>
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Microphone"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"enregistrer des fichiers audio"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"Permettre à &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; d\'enregistrer des contenus audio ?"</string>
@@ -514,6 +514,7 @@
     <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="biometric_error_hw_unavailable" msgid="645781226537551036">"Matériel biométrique indisponible"</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>
@@ -521,7 +522,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Vous avez déplacé votre doigt trop lentement. Veuillez réessayer."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Non reconnu"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"Non reconnu"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Empreinte digitale authentifiée"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Matériel d\'empreinte numérique indisponible."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Impossible d\'enregistrer l\'empreinte numérique. Veuillez supprimer une empreinte."</string>
@@ -1339,7 +1340,7 @@
     <string name="ext_media_unmountable_notification_message" msgid="4193858924381066522">"Appuyez sur la notification pour résoudre le problème"</string>
     <string name="ext_media_unmountable_notification_message" product="tv" msgid="3941179940297874950">"La <xliff:g id="NAME">%s</xliff:g> est corrompue. Sélectionnez cette option pour résoudre le problème."</string>
     <string name="ext_media_unsupported_notification_title" msgid="3797642322958803257">"<xliff:g id="NAME">%s</xliff:g> non compatible"</string>
-    <string name="ext_media_unsupported_notification_message" msgid="6121601473787888589">"Cet appareil n\'est pas compatible avec la mémoire de stockage \"<xliff:g id="NAME">%s</xliff:g>\". Appuyez ici pour le configurer dans un format accepté."</string>
+    <string name="ext_media_unsupported_notification_message" msgid="6121601473787888589">"Cet appareil n\'est pas compatible avec le support \"<xliff:g id="NAME">%s</xliff:g>\". Appuyez ici pour le configurer dans un format accepté."</string>
     <string name="ext_media_unsupported_notification_message" product="tv" msgid="3725436899820390906">"Cet appareil n\'est pas compatible avec cette <xliff:g id="NAME">%s</xliff:g>. Sélectionnez cette option pour la configurer dans un format accepté."</string>
     <string name="ext_media_badremoval_notification_title" msgid="3206248947375505416">"Retrait inattendu de mémoire \"<xliff:g id="NAME">%s</xliff:g>\""</string>
     <string name="ext_media_badremoval_notification_message" msgid="8556885808951260574">"Éjectez le périphérique externe avant de le retirer pour éviter toute perte de contenu"</string>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index 27efff8..ba66adf 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -514,6 +514,7 @@
     <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="biometric_error_hw_unavailable" msgid="645781226537551036">"O hardware biométrico non está dispoñible"</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>
@@ -521,7 +522,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"O dedo moveuse demasiado lento. Téntao de novo."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Non se recoñece"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"Non se recoñeceu"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Autenticouse a impresión dixital"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Hardware de impresión dixital non dispoñible."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Non se pode almacenar a impresión dixital. Elimina unha impresión dixital existente."</string>
@@ -1891,8 +1892,8 @@
     </plurals>
     <string name="autofill_save_title" msgid="3345527308992082601">"Queres gardar o contido en: &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
     <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_save_title_with_2types" msgid="5214035651838265325">"Queres gardar estes datos (<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 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>) 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>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index 5e6c34d..2b96f3f 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -514,6 +514,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"એપને તમારો ફોટો સંગ્રહ સંશોધિત કરવાની મંજૂરી આપે છે."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"આપના મીડિયા સંગ્રહમાંથી સ્થાનો વાંચવા"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"એપને તમારા મીડિયા સંગ્રહમાંથી સ્થાનો વાંચવાની મંજૂરી આપે છે."</string>
+    <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"બાયોમેટ્રિક હાર્ડવેર ઉપલબ્ધ નથી"</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,7 +522,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"આંગળી બહુ જ ધીમેથી ખસેડી. કૃપા કરીને ફરી પ્રયાસ કરો."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"ઓળખાયેલ નથી"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"ઓળખાયેલ નથી"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"ફિંગરપ્રિન્ટ પ્રમાણિત કરી"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"ફિંગરપ્રિન્ટ હાર્ડવેર ઉપલબ્ધ નથી."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"ફિંગરપ્રિન્ટ સંગ્રહિત કરી શકાતી નથી. કૃપા કરીને અસ્તિત્વમાંની ફિંગરપ્રિન્ટ દૂર કરો."</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index a85d6fa..6afe603 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -300,18 +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>
-    <!-- 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="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>
@@ -506,33 +500,21 @@
     <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) -->
+    <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>
+    <!-- no translation found for biometric_error_hw_unavailable (645781226537551036) -->
     <skip />
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"आंशिक फ़िंगरप्रिंट की पहचान की गई. कृपया पुनः प्रयास करें."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"फ़िंगरप्रिंट संसाधित नहीं हो सका. कृपया पुन: प्रयास करें."</string>
@@ -541,7 +523,8 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"उंगली बहुत धीरे चलाई गई. कृपया फिर से कोशिश करें."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"पहचाना नहीं गया"</string>
+    <!-- no translation found for biometric_not_recognized (5770511773560736082) -->
+    <skip />
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"फ़िंगरप्रिंट की पुष्टि हो गई"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"फ़िंगरप्रिंट हार्डवेयर उपलब्ध नहीं है."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"फ़िंगरप्रिंट को संग्रहित नहीं किया जा सका. कृपया कोई मौजूदा फ़िंगरप्रिंट निकालें."</string>
@@ -1912,18 +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>
-    <!-- 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_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>
-    <!-- no translation found for autofill_update_yes (310358413273276958) -->
-    <skip />
+    <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-hr/strings.xml b/core/res/res/values-hr/strings.xml
index f24a3c4..e7b6b5f 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -517,6 +517,7 @@
     <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="biometric_error_hw_unavailable" msgid="645781226537551036">"Biometrijski hardver nije dostupan"</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>
@@ -524,7 +525,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Presporo pomicanje prsta. Pokušajte ponovo."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Nije prepoznat"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"Nije prepoznato"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Autentificirano otiskom prsta"</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 nije pohranjen. Uklonite postojeći otisak prsta."</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index e7c1bf2..3d9a35b 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -514,6 +514,7 @@
     <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="biometric_error_hw_unavailable" msgid="645781226537551036">"Biometrikus hardver nem áll rendelkezésre"</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>
@@ -521,7 +522,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Túl lassan húzta az ujját. Próbálkozzon újra."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Nem sikerült felismerni"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"Nem ismerhető fel"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Ujjlenyomat hitelesítve"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Az ujjlenyomathoz szükséges hardver nem érhető el."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Az ujjlenyomat nem tárolható. Távolítson el egy meglévő ujjlenyomatot."</string>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index a46d5e6..6a5f287 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -514,6 +514,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Թույլ է տալիս հավելվածին փոփոխել ձեր լուսանկարների հավաքածուն:"</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"ճանաչել տեղադրության մասին տվյալները մեդիա բովանդակության հավաքածուից"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Թույլ է տալիս հավելվածին ճանաչել տեղադրության մասին տվյալները ձեր մեդիա բովանդակության հավաքածուից:"</string>
+    <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"Կենսաչափական սարքը հասանելի չէ"</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,7 +522,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Շատ դանդաղ անցկացրեցիք մատը: Փորձեք նորից:"</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Չճանաչվեց"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"Չհաջողվեց ճանաչել"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Մատնահետքը նույնականացվեց"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Մատնահետքի սարքն անհասանելի է:"</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Հնարավոր չէ պահել մատնահետքը: Հեռացրեք առկա մատնահետքը:"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index ed5444d..6d1da48 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -514,6 +514,7 @@
     <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="biometric_error_hw_unavailable" msgid="645781226537551036">"Hardware biometrik tidak tersedia"</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,7 +522,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Jari digerakkan terlalu lambat. Coba lagi."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Tidak dikenali"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"Tidak dikenali"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Sidik jari diautentikasi"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Hardware sidik jari tidak tersedia."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Sidik jari tidak dapat disimpan. Hapus sidik jari yang ada."</string>
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index 330b010..4d7996f 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -514,6 +514,7 @@
     <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="biometric_error_hw_unavailable" msgid="645781226537551036">"Lífkennavélbúnaður ekki tiltækur"</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>
@@ -521,7 +522,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Fingurinn hreyfðist of hægt. Reyndu aftur."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Þekktist ekki"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"Þekktist ekki"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Fingrafar staðfest"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Fingrafarsvélbúnaður ekki til staðar."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Ekki er hægt að vista fingrafarið. Fjarlægðu eitthvert af fingraförunum sem fyrir eru."</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index a7c1ae2..44818a3 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -514,6 +514,7 @@
     <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="biometric_error_hw_unavailable" msgid="645781226537551036">"Hardware biometrico non disponibile"</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>
@@ -521,7 +522,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Movimento del dito troppo lento. Riprova."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Non riconosciuto"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"Non riconosciuto"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Impronta digitale autenticata"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Hardware per l\'impronta digitale non disponibile."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Impossibile memorizzare l\'impronta digitale. Rimuovi un\'impronta esistente."</string>
@@ -832,7 +833,7 @@
     <string name="lockscreen_forgot_pattern_button_text" msgid="2626999449610695930">"Hai dimenticato la sequenza?"</string>
     <string name="lockscreen_glogin_forgot_pattern" msgid="2588521501166032747">"Sblocco account"</string>
     <string name="lockscreen_glogin_too_many_attempts" msgid="2751368605287288808">"Troppi tentativi di inserimento della sequenza"</string>
-    <string name="lockscreen_glogin_instructions" msgid="3931816256100707784">"Per sbloccare, accedi tramite il tuo account Google."</string>
+    <string name="lockscreen_glogin_instructions" msgid="3931816256100707784">"Per sbloccare, accedi tramite il tuo Account Google."</string>
     <string name="lockscreen_glogin_username_hint" msgid="8846881424106484447">"Nome utente (email)"</string>
     <string name="lockscreen_glogin_password_hint" msgid="5958028383954738528">"Password"</string>
     <string name="lockscreen_glogin_submit_button" msgid="7130893694795786300">"Accedi"</string>
@@ -1585,7 +1586,7 @@
     <string name="kg_invalid_puk" msgid="3638289409676051243">"Inserisci di nuovo il codice PUK corretto. Ripetuti tentativi comportano la disattivazione definitiva della scheda SIM."</string>
     <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"I codici PIN non corrispondono"</string>
     <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"Troppi tentativi di inserimento della sequenza"</string>
-    <string name="kg_login_instructions" msgid="1100551261265506448">"Per sbloccare, accedi con il tuo account Google."</string>
+    <string name="kg_login_instructions" msgid="1100551261265506448">"Per sbloccare, accedi con il tuo Account Google."</string>
     <string name="kg_login_username_hint" msgid="5718534272070920364">"Nome utente (email)"</string>
     <string name="kg_login_password_hint" msgid="9057289103827298549">"Password"</string>
     <string name="kg_login_submit_button" msgid="5355904582674054702">"Accedi"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 9a3fe87..fd5c2a1 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -520,6 +520,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"מאפשרת לאפליקציה לשנות את אוסף התמונות שלך."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"לקרוא מיקומים מאוסף המדיה שלך"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"מאפשרת לאפליקציה לקרוא מיקומים מאוסף המדיה שלך."</string>
+    <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"חומרה ביומטרית לא זמינה"</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,7 +528,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"הזזת את האצבע לאט מדי. נסה שוב."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"לא זוהתה"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"לא זוהתה"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"טביעת האצבע אומתה"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"החומרה בשביל טביעת אצבע אינה זמינה."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"לא ניתן לאחסן טביעת אצבע. הסר טביעת אצבע קיימת."</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index ec2ada4..4915111 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -284,7 +284,7 @@
     <string name="permgrouprequest_sms" msgid="7168124215838204719">"SMS メッセージの送信と表示を &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; に許可しますか?"</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"ストレージ"</string>
     <string name="permgroupdesc_storage" msgid="637758554581589203">"端末内の写真、メディア、ファイルへのアクセス"</string>
-    <string name="permgrouprequest_storage" msgid="7885942926944299560">"端末内の写真、メディア、ファイルへのアクセスを &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; に許可しますか?"</string>
+    <string name="permgrouprequest_storage" msgid="7885942926944299560">"端末内の写真、メディア、ファイルへのアクセスを「&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;」に許可しますか?"</string>
     <string name="permgrouplab_microphone" msgid="171539900250043464">"マイク"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"音声の録音"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"音声の録音を &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; に許可しますか?"</string>
@@ -514,6 +514,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"写真コレクションの変更をアプリに許可します。"</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"メディア コレクションの位置情報の読み取り"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"メディア コレクションの位置情報の読み取りをアプリに許可します。"</string>
+    <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"生体認証ハードウェアが利用できません"</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,7 +522,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"指の動きが遅すぎました。もう一度お試しください。"</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"認識されませんでした"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"認識されませんでした"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"指紋認証を完了しました"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"指紋ハードウェアは使用できません。"</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"指紋を保存できません。既存の指紋を削除してください。"</string>
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index 0a383df..51a4c28 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -514,6 +514,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"აპი შეძლებს თქვენი ფოტოკოლექციის შეცვლას."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"მდებარეობების გაცნობა თქვენი მედიაკოლექციიდან"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"აპი შეძლებს მდებარეობების გაცნობას თქვენი მედიაკოლექციიდან."</string>
+    <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"ბიომეტრიული აპარატურა მიუწვდომელია"</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,7 +522,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"თითის აღება მეტისმეტად ნელა მოხდა. გთხოვთ, სცადოთ ხელახლა."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"არ არის ამოცნობილი"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"არ არის ამოცნობილი"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"თითის ანაბეჭდი ავტორიზებულია"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"თითის ანაბეჭდის აპარატურა არ არის ხელმისაწვდომი."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"თითის ანაბეჭდის შენახვა ვერ ხერხდება. გთხოვთ, ამოშალოთ არსებული თითის ანაბეჭდი."</string>
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index 2509958..18be1e6 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -514,6 +514,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Қолданбаға суреттер жинағын өзгертуге мүмкіндік береді."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"медиамазмұн жинағынан геодеректерді оқу"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Қолданбаға медиамазмұн жинағынан геодеректерді оқуға мүмкіндік береді."</string>
+    <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"Биометрикалық жабдық жоқ"</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,7 +522,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Саусағыңызды тым баяу қозғалттыңыз. Әрекетті қайталап көріңіз."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Анықталмаған"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"Танылмады"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Саусақ ізі аутентификацияланды"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Саусақ ізі жабдығы қолжетімді емес."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Саусақ ізін сақтау мүмкін емес. Бар саусақ ізін жойыңыз."</string>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index e24c9a0..091fa71 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -514,6 +514,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"អនុញ្ញាតឱ្យ​កម្មវិធី​កែប្រែ​បណ្ដុំ​រូបថត​របស់​អ្នក។"</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"អាន​ទីតាំង​ពី​បណ្ដុំ​មេឌៀ​របស់​អ្នក"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"អនុញ្ញាតឱ្យ​កម្មវិធី​អាន​ទីតាំង​ពីបណ្ដុំ​មេឌៀ​របស់​អ្នក។"</string>
+    <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"មិនអាច​ប្រើឧបករណ៍​ស្កេន​ស្នាមម្រាមដៃ​បានទេ"</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,7 +522,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"ចលនាម្រាមដៃយឺតពេកហើយ។ សូមព្យាយាមម្តងទៀត។"</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"មិនអាចសម្គាល់បានទេ"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"មិនអាចសម្គាល់បានទេ"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"បាន​ផ្ទៀង​ផ្ទាត់​ស្នាម​ម្រាមដៃ"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"ផ្នែករឹងស្នាមម្រាមដៃមិនមានទេ។"</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"មិនអាចផ្ទុកស្នាមម្រាមដៃទេ។ សូមយកស្នាមម្រាមដៃដែលមានស្រាប់ចេញ។"</string>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index 158a316..e228d35 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -284,7 +284,7 @@
     <string name="permgrouprequest_sms" msgid="7168124215838204719">"ಎಸ್‌ಎಂಎಸ್‌ ಸಂದೇಶಗಳನ್ನು ಕಳುಹಿಸಲು ಮತ್ತು ವೀಕ್ಷಿಸಲು &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ಗೆ ಅನುಮತಿಸಬೇಕೇ?"</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"ಸಂಗ್ರಹಣೆ"</string>
     <string name="permgroupdesc_storage" msgid="637758554581589203">"ಸಾಧನದಲ್ಲಿ ಫೋಟೋಗಳು, ಮಾಧ್ಯಮ ಮತ್ತು ಫೈಲ್‌ಗಳನ್ನು ಪ್ರವೇಶಿಸಲು"</string>
-    <string name="permgrouprequest_storage" msgid="7885942926944299560">"ನಿಮ್ಮ ಸಾಧನದಲ್ಲಿ ಫೋಟೋಗಳು, ಮಾಧ್ಯಮ ಮತ್ತು ಫೈಲ್‌ಗಳನ್ನು ಪ್ರವೇಶಿಸಲು &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ಗೆ ಅನುಮತಿಸಬೇಕೇ?"</string>
+    <string name="permgrouprequest_storage" msgid="7885942926944299560">"ಸಾಧನದಲ್ಲಿ ಫೋಟೋಗಳು, ಮಾಧ್ಯಮ, ಫೈಲ್‌ಗಳನ್ನು ಪ್ರವೇಶಿಸಲು &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ಗೆ ಅನುಮತಿಸಬೇಕೇ?"</string>
     <string name="permgrouplab_microphone" msgid="171539900250043464">"ಮೈಕ್ರೋಫೋನ್‌"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"ಆಡಿಯೊ ರೆಕಾರ್ಡ್ ಮಾಡಿ"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"ಆಡಿಯೋ ರೆಕಾರ್ಡ್‌ ಮಾಡಲು &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ಗೆ ಅನುಮತಿಸಬೇಕೇ?"</string>
@@ -514,6 +514,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"ನಿಮ್ಮ ಫೋಟೋ ಸಂಗ್ರಹಣೆಯನ್ನು ಮಾರ್ಪಡಿಸಲು ಆ್ಯಪ್‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"ನಿಮ್ಮ ಮೀಡಿಯಾ ಸಂಗ್ರಹಣೆಯಿಂದ ಸ್ಥಳಗಳನ್ನು ಓದಿ"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"ನಿಮ್ಮ ಮೀಡಿಯಾ ಸಂಗ್ರಹಣೆಯಿಂದ ಸ್ಥಳಗಳನ್ನು ಓದಲು ಆ್ಯಪ್‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ."</string>
+    <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"ಬಯೋಮೆಟ್ರಿಕ್ ಹಾರ್ಡ್‌ವೇರ್‌ ಲಭ್ಯವಿಲ್ಲ"</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,7 +522,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"ಬೆರಳನ್ನು ತುಂಬಾ ನಿಧಾನವಾಗಿ ಸರಿಸಲಾಗಿದೆ. ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"ಗುರುತಿಸಲಾಗಿಲ್ಲ"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"ಗುರುತಿಸಲಾಗಿಲ್ಲ"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಅನ್ನು ಪ್ರಮಾಣೀಕರಣ ಮಾಡಲಾಗಿದೆ"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"ಬೆರಳಚ್ಚು ಹಾರ್ಡ್‌ವೇರ್‌ ಲಭ್ಯವಿಲ್ಲ."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"ಬೆರಳಚ್ಚು ಸಂಗ್ರಹಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ. ಅಸ್ತಿತ್ವದಲ್ಲಿರುವ ಬೆರಳಚ್ಚು ತೆಗೆದುಹಾಕಿ."</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 776f773..d37a475 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -284,7 +284,7 @@
     <string name="permgrouprequest_sms" msgid="7168124215838204719">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;에서 SMS 메시지를 전송하고 보도록 허용하시겠습니까?"</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"저장용량"</string>
     <string name="permgroupdesc_storage" msgid="637758554581589203">"기기 사진, 미디어, 파일 액세스"</string>
-    <string name="permgrouprequest_storage" msgid="7885942926944299560">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;에서 기기의 사진, 미디어, 파일에 액세스하도록 허용하시겠습니까.?"</string>
+    <string name="permgrouprequest_storage" msgid="7885942926944299560">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;에서 기기의 사진, 미디어, 파일에 액세스하도록 허용하시겠습니까?"</string>
     <string name="permgrouplab_microphone" msgid="171539900250043464">"마이크"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"오디오 녹음"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;에서 오디오를 녹음하도록 허용하시겠습니까?"</string>
@@ -514,6 +514,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"앱에서 사진 컬렉션을 수정하도록 허용합니다."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"미디어 컬렉션에서 위치 읽기"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"앱에서 미디어 컬렉션의 위치를 읽도록 허용합니다."</string>
+    <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"생체 인식 하드웨어를 사용할 수 없음"</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,7 +522,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"손가락을 너무 느리게 움직였습니다. 다시 시도해 주세요."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"인식할 수 없습니다."</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"인식할 수 없음"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"지문이 인증됨"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"지문 인식 하드웨어를 사용할 수 없습니다."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"지문을 저장할 수 없습니다. 기존 지문을 삭제하세요."</string>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index 1c1e9a9..cf5f531 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -514,6 +514,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Колдонмого сүрөт жыйнагыңызды өзгөртүүгө мүмкүнчүлүк берет."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"медиа жыйнагыңыз сакталган жерлерди окуу"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Колдонмого медиа жыйнагыңыз сакталган жерлерди окууга мүмкүнчүлүк берет."</string>
+    <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"Биометрикалык аппарат жеткиликсиз"</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,7 +522,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Манжа өтө жай жылды. Кайра аракет кылыңыз."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Таанылган жок"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"Таанылган жок"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Манжа изинин аныктыгы текшерилди"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Манжа изинин аппараттык камсыздоосу жеткиликтүү эмес."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Манжа изин сактоо мүмкүн эмес. Учурдагы манжа изин алып салыңыз."</string>
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index b17b5ab..7d8a4e2 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -514,6 +514,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"ອະນຸຍາດໃຫ້ແອັບແກ້ໄຂຄໍເລັກຊັນຮູບຂອງທ່ານ."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"ອ່ານສະຖານທີ່ຈາກຄໍເລັກຊັນມີເດຍຂອງທ່ານ"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"ອະນຸຍາດໃຫ້ແອັບອ່ານສະຖານທີ່ຈາກຄໍເລັກຊັນມີເດຍຂອງທ່ານ."</string>
+    <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"ຮາດແວຊີວະມິຕິບໍ່ສາມາດໃຊ້ໄດ້"</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,7 +522,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"ຍ້າຍ​ນີ້ວ​ມື​ໄປຊ້າ​ເກີນ​ໄປ. ກະ​ລຸ​ນາ​ລອງ​ໃໝ່​ອີກ."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"ບໍ່​ຈົດ​ຈຳ​ໄດ້"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"ບໍ່ຮັບຮູ້"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"ພິສູດຢືນຢັນລາຍນິ້ວມືແລ້ວ"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"ບໍ່​ມີ​ຮາດ​ແວລາຍ​ນີ້ວ​ມື​ໃຫ້​ຢູ່."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"ບໍ່​ສາ​ມາດ​ເກັບ​ຮັກ​ສາ​ລາຍ​ນີ້ວ​ມື​ໄວ້​ໄດ້. ກະ​ລຸ​ນາ​ເອົາ​ລາຍ​ນີ້ວ​ມື​ທີ່​ມີ​ຢູ່​ອອກ​ໄປ."</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 9409c7d..a0015c3 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -520,6 +520,7 @@
     <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="biometric_error_hw_unavailable" msgid="645781226537551036">"Biometrinė aparatinė įranga nepasiekiama"</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>
@@ -527,7 +528,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Per lėtai judinate pirštą. Bandykite dar kartą."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Neatpažintas"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"Neatpažinta"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Kontrolinis kodas autentifikuotas"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Kontrolinio kodo aparatinė įranga nepasiekiama."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Negalima išsaugoti kontrolinio kodo. Pašalinkite esamą kontrolinį kodą."</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 272deb3..a1aebe1 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -517,6 +517,7 @@
     <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="biometric_error_hw_unavailable" msgid="645781226537551036">"Biometrisko datu aparatūra nav pieejama"</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>
@@ -524,7 +525,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Pārāk lēna pirksta kustība. Lūdzu, mēģiniet vēlreiz."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Nav atpazīts"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"Dati nav atpazīti"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Pirksta nospiedums tika autentificēts."</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Nospieduma aparatūra nav pieejama."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Pirkstu nospiedumu nevar saglabāt. Lūdzu, noņemiet esošu pirksta nospiedumu."</string>
diff --git a/core/res/res/values-mcc302-mnc220/config.xml b/core/res/res/values-mcc302-mnc220/config.xml
index 3308128..13f6bce 100644
--- a/core/res/res/values-mcc302-mnc220/config.xml
+++ b/core/res/res/values-mcc302-mnc220/config.xml
@@ -40,7 +40,7 @@
         <item>SUPL_PORT=7275</item>
         <item>SUPL_VER=0x20000</item>
         <item>SUPL_MODE=1</item>
-        <item>SUPL_ES=0</item>
+        <item>SUPL_ES=1</item>
         <item>LPP_PROFILE=3</item>
         <item>USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL=1</item>
         <item>A_GLONASS_POS_PROTOCOL_SELECT=0</item>
diff --git a/core/res/res/values-mcc302-mnc221/config.xml b/core/res/res/values-mcc302-mnc221/config.xml
index bb0d4d5..d45b91a 100644
--- a/core/res/res/values-mcc302-mnc221/config.xml
+++ b/core/res/res/values-mcc302-mnc221/config.xml
@@ -38,7 +38,7 @@
         <item>SUPL_PORT=7275</item>
         <item>SUPL_VER=0x20000</item>
         <item>SUPL_MODE=1</item>
-        <item>SUPL_ES=0</item>
+        <item>SUPL_ES=1</item>
         <item>LPP_PROFILE=3</item>
         <item>USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL=1</item>
         <item>A_GLONASS_POS_PROTOCOL_SELECT=0</item>
diff --git a/core/res/res/values-mcc302-mnc370/config.xml b/core/res/res/values-mcc302-mnc370/config.xml
index 1241a9d..b520d5d 100644
--- a/core/res/res/values-mcc302-mnc370/config.xml
+++ b/core/res/res/values-mcc302-mnc370/config.xml
@@ -41,7 +41,7 @@
         <item>SUPL_PORT=7275</item>
         <item>SUPL_VER=0x20000</item>
         <item>SUPL_MODE=1</item>
-        <item>SUPL_ES=0</item>
+        <item>SUPL_ES=1</item>
         <item>LPP_PROFILE=2</item>
         <item>USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL=1</item>
         <item>A_GLONASS_POS_PROTOCOL_SELECT=0</item>
diff --git a/core/res/res/values-mcc302-mnc610/config.xml b/core/res/res/values-mcc302-mnc610/config.xml
index 232f149..650aa62 100644
--- a/core/res/res/values-mcc302-mnc610/config.xml
+++ b/core/res/res/values-mcc302-mnc610/config.xml
@@ -28,7 +28,7 @@
         <item>SUPL_PORT=7275</item>
         <item>SUPL_VER=0x20000</item>
         <item>SUPL_MODE=1</item>
-        <item>SUPL_ES=0</item>
+        <item>SUPL_ES=1</item>
         <item>LPP_PROFILE=2</item>
         <item>USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL=1</item>
         <item>A_GLONASS_POS_PROTOCOL_SELECT=0</item>
diff --git a/core/res/res/values-mcc302-mnc640/config.xml b/core/res/res/values-mcc302-mnc640/config.xml
index 1d2e625..4bb68dc 100644
--- a/core/res/res/values-mcc302-mnc640/config.xml
+++ b/core/res/res/values-mcc302-mnc640/config.xml
@@ -24,7 +24,7 @@
         <item>SUPL_PORT=7275</item>
         <item>SUPL_VER=0x20000</item>
         <item>SUPL_MODE=1</item>
-        <item>SUPL_ES=0</item>
+        <item>SUPL_ES=1</item>
         <item>LPP_PROFILE=2</item>
         <item>USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL=1</item>
         <item>A_GLONASS_POS_PROTOCOL_SELECT=0</item>
diff --git a/core/res/res/values-mcc302-mnc720/config.xml b/core/res/res/values-mcc302-mnc720/config.xml
index ef1ecd2..11bfa05 100644
--- a/core/res/res/values-mcc302-mnc720/config.xml
+++ b/core/res/res/values-mcc302-mnc720/config.xml
@@ -43,7 +43,7 @@
         <item>SUPL_PORT=7275</item>
         <item>SUPL_VER=0x20000</item>
         <item>SUPL_MODE=1</item>
-        <item>SUPL_ES=0</item>
+        <item>SUPL_ES=1</item>
         <item>LPP_PROFILE=2</item>
         <item>USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL=1</item>
         <item>A_GLONASS_POS_PROTOCOL_SELECT=0</item>
diff --git a/core/res/res/values-mcc310-mnc030-pt-rBR/strings.xml b/core/res/res/values-mcc310-mnc030-pt-rBR/strings.xml
index 663261c..60a143f 100644
--- a/core/res/res/values-mcc310-mnc030-pt-rBR/strings.xml
+++ b/core/res/res/values-mcc310-mnc030-pt-rBR/strings.xml
@@ -20,7 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"SIM não aprovisionado MM#2"</string>
-    <string name="mmcc_illegal_ms" msgid="1930079814544869756">"SIM não permitido MM#3"</string>
+    <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"Chip não aprovisionado MM#2"</string>
+    <string name="mmcc_illegal_ms" msgid="1930079814544869756">"Chip não permitido MM#3"</string>
     <string name="mmcc_illegal_me" msgid="2995576894416087107">"Smartphone não permitido MM#6"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc030-pt/strings.xml b/core/res/res/values-mcc310-mnc030-pt/strings.xml
index 663261c..60a143f 100644
--- a/core/res/res/values-mcc310-mnc030-pt/strings.xml
+++ b/core/res/res/values-mcc310-mnc030-pt/strings.xml
@@ -20,7 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"SIM não aprovisionado MM#2"</string>
-    <string name="mmcc_illegal_ms" msgid="1930079814544869756">"SIM não permitido MM#3"</string>
+    <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"Chip não aprovisionado MM#2"</string>
+    <string name="mmcc_illegal_ms" msgid="1930079814544869756">"Chip não permitido MM#3"</string>
     <string name="mmcc_illegal_me" msgid="2995576894416087107">"Smartphone não permitido MM#6"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc170-pt-rBR/strings.xml b/core/res/res/values-mcc310-mnc170-pt-rBR/strings.xml
index fcffa16..c774e95 100644
--- a/core/res/res/values-mcc310-mnc170-pt-rBR/strings.xml
+++ b/core/res/res/values-mcc310-mnc170-pt-rBR/strings.xml
@@ -20,7 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"SIM não aprovisionado MM#2"</string>
-    <string name="mmcc_illegal_ms" msgid="1130721094178658338">"SIM não permitido MM#3"</string>
+    <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"Chip não aprovisionado MM#2"</string>
+    <string name="mmcc_illegal_ms" msgid="1130721094178658338">"Chip não permitido MM#3"</string>
     <string name="mmcc_illegal_me" msgid="3173546391131606065">"Smartphone não permitido MM#6"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc170-pt/strings.xml b/core/res/res/values-mcc310-mnc170-pt/strings.xml
index fcffa16..c774e95 100644
--- a/core/res/res/values-mcc310-mnc170-pt/strings.xml
+++ b/core/res/res/values-mcc310-mnc170-pt/strings.xml
@@ -20,7 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"SIM não aprovisionado MM#2"</string>
-    <string name="mmcc_illegal_ms" msgid="1130721094178658338">"SIM não permitido MM#3"</string>
+    <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"Chip não aprovisionado MM#2"</string>
+    <string name="mmcc_illegal_ms" msgid="1130721094178658338">"Chip não permitido MM#3"</string>
     <string name="mmcc_illegal_me" msgid="3173546391131606065">"Smartphone não permitido MM#6"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc280-pt-rBR/strings.xml b/core/res/res/values-mcc310-mnc280-pt-rBR/strings.xml
index f7fb684..3a269b6 100644
--- a/core/res/res/values-mcc310-mnc280-pt-rBR/strings.xml
+++ b/core/res/res/values-mcc310-mnc280-pt-rBR/strings.xml
@@ -20,7 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"SIM não aprovisionado MM#2"</string>
-    <string name="mmcc_illegal_ms" msgid="5562215652599183258">"SIM não permitido MM#3"</string>
+    <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"Chip não aprovisionado MM#2"</string>
+    <string name="mmcc_illegal_ms" msgid="5562215652599183258">"Chip não permitido MM#3"</string>
     <string name="mmcc_illegal_me" msgid="822496463303720579">"Smartphone não permitido MM#6"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc280-pt/strings.xml b/core/res/res/values-mcc310-mnc280-pt/strings.xml
index f7fb684..3a269b6 100644
--- a/core/res/res/values-mcc310-mnc280-pt/strings.xml
+++ b/core/res/res/values-mcc310-mnc280-pt/strings.xml
@@ -20,7 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"SIM não aprovisionado MM#2"</string>
-    <string name="mmcc_illegal_ms" msgid="5562215652599183258">"SIM não permitido MM#3"</string>
+    <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"Chip não aprovisionado MM#2"</string>
+    <string name="mmcc_illegal_ms" msgid="5562215652599183258">"Chip não permitido MM#3"</string>
     <string name="mmcc_illegal_me" msgid="822496463303720579">"Smartphone não permitido MM#6"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc380-pt-rBR/strings.xml b/core/res/res/values-mcc310-mnc380-pt-rBR/strings.xml
index 06bc55a..6f8fb21 100644
--- a/core/res/res/values-mcc310-mnc380-pt-rBR/strings.xml
+++ b/core/res/res/values-mcc310-mnc380-pt-rBR/strings.xml
@@ -20,6 +20,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"SIM não aprovisionado MM#2"</string>
-    <string name="mmcc_illegal_ms" msgid="6367773216941648568">"SIM não permitido MM#3"</string>
+    <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"Chip não aprovisionado MM#2"</string>
+    <string name="mmcc_illegal_ms" msgid="6367773216941648568">"Chip não permitido MM#3"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc380-pt/strings.xml b/core/res/res/values-mcc310-mnc380-pt/strings.xml
index 06bc55a..6f8fb21 100644
--- a/core/res/res/values-mcc310-mnc380-pt/strings.xml
+++ b/core/res/res/values-mcc310-mnc380-pt/strings.xml
@@ -20,6 +20,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"SIM não aprovisionado MM#2"</string>
-    <string name="mmcc_illegal_ms" msgid="6367773216941648568">"SIM não permitido MM#3"</string>
+    <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"Chip não aprovisionado MM#2"</string>
+    <string name="mmcc_illegal_ms" msgid="6367773216941648568">"Chip não permitido MM#3"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc410-pt-rBR/strings.xml b/core/res/res/values-mcc310-mnc410-pt-rBR/strings.xml
index f6bfc67..f80ff85 100644
--- a/core/res/res/values-mcc310-mnc410-pt-rBR/strings.xml
+++ b/core/res/res/values-mcc310-mnc410-pt-rBR/strings.xml
@@ -20,7 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"SIM não aprovisionado MM#2"</string>
-    <string name="mmcc_illegal_ms" msgid="1593063035884873292">"SIM não permitido MM#3"</string>
+    <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"Chip não aprovisionado MM#2"</string>
+    <string name="mmcc_illegal_ms" msgid="1593063035884873292">"Chip não permitido MM#3"</string>
     <string name="mmcc_illegal_me" msgid="4477688981805467729">"Smartphone não permitido MM#6"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc410-pt/strings.xml b/core/res/res/values-mcc310-mnc410-pt/strings.xml
index f6bfc67..f80ff85 100644
--- a/core/res/res/values-mcc310-mnc410-pt/strings.xml
+++ b/core/res/res/values-mcc310-mnc410-pt/strings.xml
@@ -20,7 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"SIM não aprovisionado MM#2"</string>
-    <string name="mmcc_illegal_ms" msgid="1593063035884873292">"SIM não permitido MM#3"</string>
+    <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"Chip não aprovisionado MM#2"</string>
+    <string name="mmcc_illegal_ms" msgid="1593063035884873292">"Chip não permitido MM#3"</string>
     <string name="mmcc_illegal_me" msgid="4477688981805467729">"Smartphone não permitido MM#6"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc560-pt-rBR/strings.xml b/core/res/res/values-mcc310-mnc560-pt-rBR/strings.xml
index fba400c..1d16be7 100644
--- a/core/res/res/values-mcc310-mnc560-pt-rBR/strings.xml
+++ b/core/res/res/values-mcc310-mnc560-pt-rBR/strings.xml
@@ -20,7 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"SIM não aprovisionado MM#2"</string>
-    <string name="mmcc_illegal_ms" msgid="2519618694918727742">"SIM não permitido MM#3"</string>
+    <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"Chip não aprovisionado MM#2"</string>
+    <string name="mmcc_illegal_ms" msgid="2519618694918727742">"Chip não permitido MM#3"</string>
     <string name="mmcc_illegal_me" msgid="7030488670186895244">"Smartphone não permitido MM#6"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc560-pt/strings.xml b/core/res/res/values-mcc310-mnc560-pt/strings.xml
index fba400c..1d16be7 100644
--- a/core/res/res/values-mcc310-mnc560-pt/strings.xml
+++ b/core/res/res/values-mcc310-mnc560-pt/strings.xml
@@ -20,7 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"SIM não aprovisionado MM#2"</string>
-    <string name="mmcc_illegal_ms" msgid="2519618694918727742">"SIM não permitido MM#3"</string>
+    <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"Chip não aprovisionado MM#2"</string>
+    <string name="mmcc_illegal_ms" msgid="2519618694918727742">"Chip não permitido MM#3"</string>
     <string name="mmcc_illegal_me" msgid="7030488670186895244">"Smartphone não permitido MM#6"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc950-pt-rBR/strings.xml b/core/res/res/values-mcc310-mnc950-pt-rBR/strings.xml
index 83c84ce..e74582c 100644
--- a/core/res/res/values-mcc310-mnc950-pt-rBR/strings.xml
+++ b/core/res/res/values-mcc310-mnc950-pt-rBR/strings.xml
@@ -20,7 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"SIM não aprovisionado MM#2"</string>
-    <string name="mmcc_illegal_ms" msgid="2418195136279399212">"SIM não permitido MM#3"</string>
+    <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"Chip não aprovisionado MM#2"</string>
+    <string name="mmcc_illegal_ms" msgid="2418195136279399212">"Chip não permitido MM#3"</string>
     <string name="mmcc_illegal_me" msgid="8920048244573695129">"Smartphone não permitido MM#6"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc950-pt/strings.xml b/core/res/res/values-mcc310-mnc950-pt/strings.xml
index 83c84ce..e74582c 100644
--- a/core/res/res/values-mcc310-mnc950-pt/strings.xml
+++ b/core/res/res/values-mcc310-mnc950-pt/strings.xml
@@ -20,7 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"SIM não aprovisionado MM#2"</string>
-    <string name="mmcc_illegal_ms" msgid="2418195136279399212">"SIM não permitido MM#3"</string>
+    <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"Chip não aprovisionado MM#2"</string>
+    <string name="mmcc_illegal_ms" msgid="2418195136279399212">"Chip não permitido MM#3"</string>
     <string name="mmcc_illegal_me" msgid="8920048244573695129">"Smartphone não permitido MM#6"</string>
 </resources>
diff --git a/core/res/res/values-mcc311-mnc180-pt-rBR/strings.xml b/core/res/res/values-mcc311-mnc180-pt-rBR/strings.xml
index 637a91c..beb1715 100644
--- a/core/res/res/values-mcc311-mnc180-pt-rBR/strings.xml
+++ b/core/res/res/values-mcc311-mnc180-pt-rBR/strings.xml
@@ -20,7 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"SIM não aprovisionado MM#2"</string>
-    <string name="mmcc_illegal_ms" msgid="97745044956236881">"SIM não permitido MM#3"</string>
+    <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"Chip não aprovisionado MM#2"</string>
+    <string name="mmcc_illegal_ms" msgid="97745044956236881">"Chip não permitido MM#3"</string>
     <string name="mmcc_illegal_me" msgid="5766888847785331904">"Smartphone não permitido MM#6"</string>
 </resources>
diff --git a/core/res/res/values-mcc311-mnc180-pt/strings.xml b/core/res/res/values-mcc311-mnc180-pt/strings.xml
index 637a91c..beb1715 100644
--- a/core/res/res/values-mcc311-mnc180-pt/strings.xml
+++ b/core/res/res/values-mcc311-mnc180-pt/strings.xml
@@ -20,7 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"SIM não aprovisionado MM#2"</string>
-    <string name="mmcc_illegal_ms" msgid="97745044956236881">"SIM não permitido MM#3"</string>
+    <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"Chip não aprovisionado MM#2"</string>
+    <string name="mmcc_illegal_ms" msgid="97745044956236881">"Chip não permitido MM#3"</string>
     <string name="mmcc_illegal_me" msgid="5766888847785331904">"Smartphone não permitido MM#6"</string>
 </resources>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index b2beb3a..0ab31b3 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -514,6 +514,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Дозволува апликацијата да ја менува вашата збирка на фотографии."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"да чита локации од вашата збирка на аудиовизуелни содржини"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Дозволува апликацијата да чита локации од вашата збирка на аудиовизуелни содржини."</string>
+    <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"Биометрискиот хардвер е недостапен"</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,7 +522,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Прстот се движеше премногу бавно. Обидете се повторно."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Не е препознаено"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"Непознат"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Отпечатокот е проверен"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Хардвер за отпечаток од прст не е достапен."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Отпечатокот не може да се складира. Отстранете го постоечкиот отпечаток."</string>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index 81421bb..eafd6a4 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -514,6 +514,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"നിങ്ങളുടെ ഫോട്ടോ ശേഖരം പരിഷ്‌ക്കരിക്കുന്നതിന് ആപ്പിനെ അനുവദിക്കുന്നു."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"നിങ്ങളുടെ മീഡിയ ശേഖരത്തിൽ നിന്നും ലൊക്കേഷനുകൾ റീഡ് ചെയ്യുക"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"നിങ്ങളുടെ മീഡിയ ശേഖരത്തിൽ നിന്നും ലൊക്കേഷനുകൾ റീഡ് ചെയ്യുന്നതിന് ആപ്പിനെ അനുവദിക്കുന്നു."</string>
+    <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"ബയോമെട്രിക് ഹാർ‌ഡ്‌വെയർ ലഭ്യമല്ല"</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,7 +522,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"വിരൽ വളരെ പതുക്കെ നീക്കി. വീണ്ടും ശ്രമിക്കുക."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"തിരിച്ചറിഞ്ഞില്ല"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"തിരിച്ചറിഞ്ഞില്ല"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"ഫിംഗർപ്രിന്റ് പരിശോധിച്ചുറപ്പിച്ചു"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"ഫിംഗർപ്രിന്റ് ഹാർഡ്‌വെയർ ലഭ്യമല്ല."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"വിരലടയാളം സംഭരിക്കാനാവില്ല. നിലവിലുള്ള വിരലടയാളം നീക്കംചെയ്യുക."</string>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index ddf1bc6..12e3186 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -514,6 +514,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Таны зургийн цуглуулгыг тохируулах зөвшөөрлийг аппад олгодог."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"медиа цуглуулгаасаа байршлыг унших"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Таны медиа цуглуулгаас байршлыг унших зөвшөөрлийг аппад олгодог."</string>
+    <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"Биометрийн техник хангамж боломжгүй байна"</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,7 +522,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Хуруу хэт удаан хөдөлгөсөн байна. Дахин оролдоно уу."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Танигдахгүй байна"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"Таниагүй"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Хурууны хээг нотолсон"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Хурууны хээний тоног төхөөрөмж бэлэн бус байна."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Хурууны хээг хадгалах боломжгүй байна. Одоо байгаа хурууны хээг арилгана уу."</string>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index c257008..fe248c1 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -514,6 +514,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"अॅपला तुमच्या फोटो संग्रहामध्ये सुधारणा करण्याची अनुमती देते."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"तुमच्या मीडिया संग्रहातून स्थाने वाचा"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"अॅपला तुमच्या मीडिया संग्रहामध्येील स्थाने वाचण्यासाठी अनुमती देते."</string>
+    <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"बायोमेट्रिक हार्डवेअर उपलब्ध नाही"</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,7 +522,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"बोट खूप सावकाश हलविले. कृपया पुन्हा प्रयत्न करा."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"ओळखले नाही"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"ओळखले नाही"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"फिंगरप्रिंट ऑथेंटिकेट केली आहे"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"फिंगरप्रिंट हार्डवेअर उपलब्‍ध नाही."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"फिंगरप्रिंट स्टोअर केले जाऊ शकत नाही. कृपया विद्यमान फिंगरप्रिंट काढा."</string>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index 939b9a4..a813a7b 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -514,6 +514,7 @@
     <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="biometric_error_hw_unavailable" msgid="645781226537551036">"Perkakasan biometrik tidak tersedia"</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>
@@ -521,7 +522,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Jari digerakkan terlalu perlahan. Sila cuba lagi."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Tidak dicam"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"Tidak dikenali"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Cap jari disahkan"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Perkakasan cap jari tidak tersedia."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Cap jari tidak dapat disimpan. Sila alih keluar cap jari sedia ada."</string>
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index 23a73ff..812ff75 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -514,6 +514,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"အက်ပ်အား သင့်ဓာတ်ပုံစုစည်းမှုကို ပြုပြင်ခွင့်ပေးသည်။"</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"သင့်မီဒီယာစုစည်းမှုမှ တည်နေရာများကို ဖတ်ခြင်း"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"အက်ပ်အား သင့်မီဒီယာစုစည်းမှုမှ တည်နေရာများကို ဖတ်ခွင့်ပေးသည်။"</string>
+    <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"ဇီဝအချက်အလက်သုံး ကွန်ပျူတာစက်ပစ္စည်း မရရှိနိုင်ပါ"</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,7 +522,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"လက်ညှိုးအလွန်နှေးကွေးစွာ ရွေ့ခဲ့သည်။ ကျေးဇူးပြု၍ ထပ်မံကြိုးစားပါ။"</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"အသိအမှတ်မပြုပါ"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"မသိပါ"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"လက်ဗွေကို အထောက်အထား စိစစ်ပြီးပါပြီ"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"လက်ဗွေရာ ဟာ့ဒ်ဝဲ မရနိုင်ပါ။"</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"လက်ဗွေရာ သိုလှောင်၍မရပါ။ ကျေးဇူးပြု၍ ရှိပြီးလက်ဗွေရာအား ဖယ်ရှားပါ။"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 7d3fe48..439b0de 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -514,6 +514,7 @@
     <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="biometric_error_hw_unavailable" msgid="645781226537551036">"Biometrisk maskinvare er utilgjengelig"</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>
@@ -521,7 +522,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Du flyttet fingeren for sakte. Prøv på nytt."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Ikke gjenkjent"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"Ikke gjenkjent"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Fingeravtrykket er godkjent"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Maskinvare for fingeravtrykk er ikke tilgjengelig."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Fingeravtrykket kan ikke lagres. Fjern et eksisterende fingeravtrykk."</string>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index 55e62ff..d45e28b 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -514,6 +514,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"यसले अनुप्रयोगलाई तपाईंको तस्बिरको सङ्ग्रह परिमार्जन गर्न दिन्छ।"</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"आफ्नो मिडियाको सङ्ग्रहका स्थानहरू पढ्नुहोस्‌"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"यसले अनुप्रयोगलाई तपाईंको मिडिया सङ्ग्रहका स्थानहरू पढ्न दिन्छ।"</string>
+    <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"बायोमेट्रिक हार्डवेयर उपलब्ध छैन"</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,7 +522,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"औंला निकै सुस्त सारियो। कृपया फेरि प्रयास गर्नुहोस्।"</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"चिनिएको छैन"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"पहिचान भएन"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"फिंगरप्रिन्ट प्रमाणीकरण गरियो"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"औँठाछाप हार्डवेयर उपलब्ध छैन।"</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"औँठाछाप भण्डारण गर्न सकिँदैन। कृपया अवस्थित औठाछाप हटाउनुहोस्।"</string>
diff --git a/core/res/res/values-night/colors.xml b/core/res/res/values-night/colors.xml
index 351f8ea..6bbd258 100644
--- a/core/res/res/values-night/colors.xml
+++ b/core/res/res/values-night/colors.xml
@@ -27,5 +27,5 @@
     <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>
+    <color name="notification_material_background_color">@color/black</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
index 5e3675a..c8d4d05 100644
--- a/core/res/res/values-night/themes_device_defaults.xml
+++ b/core/res/res/values-night/themes_device_defaults.xml
@@ -51,4 +51,7 @@
           -->
     <!-- DeviceDefault theme for a window that should look like the Settings app.  -->
     <style name="Theme.DeviceDefault.Settings" parent="Theme.DeviceDefault"/>
+
+    <!-- Theme for the dialog shown when an app crashes or ANRs. -->
+    <style name="Theme.DeviceDefault.Dialog.AppError" parent="Theme.DeviceDefault.Dialog.Alert" />
 </resources>
diff --git a/core/res/res/values-night/values.xml b/core/res/res/values-night/values.xml
index 4eb2ff3..45cf0f0 100644
--- a/core/res/res/values-night/values.xml
+++ b/core/res/res/values-night/values.xml
@@ -26,7 +26,7 @@
         <item name="alertDialogTheme">@style/Theme.DeviceDefault.Dialog.Alert</item>
 
         <!-- QS panel background -->
-        <item name="colorBackgroundFloating">@color/material_grey_900</item>
+        <item name="colorBackgroundFloating">@color/black</item>
 
         <!-- volume background -->
         <item name="panelColorBackground">@color/material_grey_800</item>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 0e13132..df152b2 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -514,6 +514,7 @@
     <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="biometric_error_hw_unavailable" msgid="645781226537551036">"Biometrische hardware niet beschikbaar"</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>
@@ -521,7 +522,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Vinger te langzaam bewogen. Probeer het opnieuw."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Niet herkend"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"Niet herkend"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Vingerafdruk geverifieerd"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Hardware voor vingerafdruk niet beschikbaar."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Vingerafdruk kan niet worden opgeslagen. Verwijder een bestaande vingerafdruk."</string>
diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml
index b3a2c81..78566da 100644
--- a/core/res/res/values-or/strings.xml
+++ b/core/res/res/values-or/strings.xml
@@ -514,6 +514,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"ଆପଣଙ୍କ ଫଟୋ ସଂଗ୍ରହ ପରିବର୍ତ୍ତନ କରିବାକୁ ଆପ୍‍ ଅନୁମତି ଦେଇଥାଏ।"</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"ଆପଣଙ୍କ ମିଡିଆ ସଂଗ୍ରହ ଠାରୁ ଲୋକେସନ୍‍ଗୁଡିକୁ ପଢନ୍ତୁ"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"ଆପଣଙ୍କ ମିଡିଆ ସଂଗ୍ରହ ଠାରୁ ଅବସ୍ଥାନଗୁଡିକୁ ପଢିବାକୁ ଆପ୍‍ ଅନୁମତି ଦେଇଥାଏ।"</string>
+    <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"ବାୟୋମେଟ୍ରିକ୍‌ ହାର୍ଡୱେର୍‌ ଉପଲବ୍ଧ ନାହିଁ"</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,7 +522,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"ଆଙ୍ଗୁଠି ଖୁବ୍‍ ଧୀରେ ନିଆଗଲା। ଦୟାକରି ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"ଚିହ୍ନଟ ହେଲା ନାହିଁ"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"ଚିହ୍ନଟ ହେଲାନାହିଁ"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"ଆଙ୍ଗୁଠି ଚିହ୍ନ ପ୍ରମାଣୀକୃତ ହେଲା"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"ଆଙ୍ଗୁଠି ଚିହ୍ନ ହାର୍ଡୱେର୍‍ ଉପଲବ୍ଧ ନାହିଁ।"</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"ଆଙ୍ଗୁଠି ଚିହ୍ନ ଷ୍ଟୋର୍‍ କରାଯାଇପାରିବ ନାହିଁ। ଦୟାକରି ପୂର୍ବରୁ ଥିବା ଆଙ୍ଗୁଠି ଚିହ୍ନକୁ ବାହାର କରିଦିଅନ୍ତୁ।"</string>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index d581e6b..bb38c88 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -514,6 +514,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"ਐਪ ਨੂੰ ਤੁਹਾਡੇ ਫ਼ੋਟੋ ਸੰਗ੍ਰਹਿ ਨੂੰ ਸੋਧਣ ਦਿੰਦੀ ਹੈ।"</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"ਤੁਹਾਡੇ ਮੀਡੀਆ ਸੰਗ੍ਰਹਿ ਦੇ ਟਿਕਾਣਿਆਂ ਨੂੰ ਪੜ੍ਹਨਾ"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"ਐਪ ਨੂੰ ਤੁਹਾਡੇ ਮੀਡੀਆ ਸੰਗ੍ਰਹਿ ਦੇ ਟਿਕਾਣਿਆਂ ਨੂੰ ਪੜ੍ਹਨ ਦਿੰਦੀ ਹੈ।"</string>
+    <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"ਬਾਇਓਮੈਟ੍ਰਿਕ ਹਾਰਡਵੇਅਰ ਉਪਲਬਧ ਨਹੀਂ ਹੈ"</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,7 +522,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"ਉਂਗਲ ਕਾਫ਼ੀ ਹੌਲੀ ਮੂਵ ਹੋਈ। ਕਿਰਪਾ ਕਰਕੇ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"ਪਛਾਣ ਨਹੀਂ ਹੋਈ"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"ਪਛਾਣ ਨਹੀਂ ਹੋਈ"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਪ੍ਰਮਾਣਿਤ ਹੋਇਆ"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਹਾਰਡਵੇਅਰ ਉਪਲਬਧ ਨਹੀਂ।"</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਸਟੋਰ ਨਹੀਂ ਕੀਤਾ ਸਕਦਾ। ਕਿਰਪਾ ਕਰਕੇ ਇੱਕ ਮੌਜੂਦਾ ਫਿੰਗਰਪ੍ਰਿੰਟ ਹਟਾਓ।"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 6f56e7f..d59b138 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -520,6 +520,7 @@
     <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="biometric_error_hw_unavailable" msgid="645781226537551036">"Sprzęt biometryczny niedostępny"</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>
@@ -527,7 +528,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Palec został obrócony zbyt wolno. Spróbuj ponownie."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Nie rozpoznano odcisku palca."</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"Nie rozpoznano"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Uwierzytelniono odciskiem palca"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Czytnik linii papilarnych nie jest dostępny."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Nie można zapisać odcisku palca. Usuń istniejący odcisk palca."</string>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index ad68dde..48302a0 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -47,12 +47,12 @@
     <string name="mismatchPin" msgid="609379054496863419">"Os PINs digitados não correspondem."</string>
     <string name="invalidPin" msgid="3850018445187475377">"Digite um PIN com 4 a 8 números."</string>
     <string name="invalidPuk" msgid="8761456210898036513">"Digite um PUK com oito números ou mais."</string>
-    <string name="needPuk" msgid="919668385956251611">"O seu cartão SIM está bloqueado por um PUK. Digite o código PUK para desbloqueá-lo."</string>
-    <string name="needPuk2" msgid="4526033371987193070">"Digite o PUK2 para desbloquear o cartão SIM."</string>
-    <string name="enablePin" msgid="209412020907207950">"Falha. Ative o bloqueio do SIM/R-UIM."</string>
+    <string name="needPuk" msgid="919668385956251611">"O seu chip está bloqueado por um PUK. Digite o código PUK para desbloqueá-lo."</string>
+    <string name="needPuk2" msgid="4526033371987193070">"Digite o PUK2 para desbloquear o chip."</string>
+    <string name="enablePin" msgid="209412020907207950">"Falha. Ative o bloqueio do chip/R-UIM."</string>
     <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
-      <item quantity="one">Tentativas restantes: <xliff:g id="NUMBER_1">%d</xliff:g>. Caso o código correto não seja digitado, o SIM será bloqueado.</item>
-      <item quantity="other">Tentativas restantes: <xliff:g id="NUMBER_1">%d</xliff:g>. Caso o código correto não seja digitado, o SIM será bloqueado.</item>
+      <item quantity="one">Tentativas restantes: <xliff:g id="NUMBER_1">%d</xliff:g>. Caso o código correto não seja digitado, o chip será bloqueado.</item>
+      <item quantity="other">Tentativas restantes: <xliff:g id="NUMBER_1">%d</xliff:g>. Caso o código correto não seja digitado, o chip será bloqueado.</item>
     </plurals>
     <string name="imei" msgid="2625429890869005782">"IMEI"</string>
     <string name="meid" msgid="4841221237681254195">"MEID"</string>
@@ -82,7 +82,7 @@
     <string name="RestrictedOnNormalTitle" msgid="3179574012752700984">"Sem serviço de voz"</string>
     <string name="RestrictedOnAllVoiceTitle" msgid="8037246983606545202">"Nenhum serviço de voz nem chamada de emergência"</string>
     <string name="RestrictedStateContent" msgid="6538703255570997248">"Temporariamente desativado pela sua operadora"</string>
-    <string name="RestrictedStateContentMsimTemplate" msgid="673416791370248176">"Temporariamente desativado pela sua operadora para o SIM <xliff:g id="SIMNUMBER">%d</xliff:g>"</string>
+    <string name="RestrictedStateContentMsimTemplate" msgid="673416791370248176">"Temporariamente desativado pela sua operadora para o chip <xliff:g id="SIMNUMBER">%d</xliff:g>"</string>
     <string name="NetworkPreferenceSwitchTitle" msgid="6982395015324165258">"Não foi possível acessar a rede móvel"</string>
     <string name="NetworkPreferenceSwitchSummary" msgid="509327194863482733">"Tente alterar a rede preferencial. Toque para alterar."</string>
     <string name="EmergencyCallWarningTitle" msgid="813380189532491336">"Chamadas de emergência indisponíveis"</string>
@@ -94,7 +94,7 @@
     <string name="notification_channel_sms" msgid="3441746047346135073">"Mensagens SMS"</string>
     <string name="notification_channel_voice_mail" msgid="3954099424160511919">"Mensagens do correio de voz"</string>
     <string name="notification_channel_wfc" msgid="2130802501654254801">"Chamadas por Wi-Fi"</string>
-    <string name="notification_channel_sim" msgid="4052095493875188564">"Status do SIM"</string>
+    <string name="notification_channel_sim" msgid="4052095493875188564">"Status do chip"</string>
     <string name="peerTtyModeFull" msgid="6165351790010341421">"TTD modo COMPLETO solicitado"</string>
     <string name="peerTtyModeHco" msgid="5728602160669216784">"TTD modo HCO solicitado"</string>
     <string name="peerTtyModeVco" msgid="1742404978686538049">"TTD modo VCO solicitado"</string>
@@ -420,8 +420,8 @@
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Permite que o app modifique configurações de áudio globais como volume e alto-falantes de saída."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"gravar áudio"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"Este app pode gravar áudio usando o microfone a qualquer momento."</string>
-    <string name="permlab_sim_communication" msgid="2935852302216852065">"enviar comandos para o SIM"</string>
-    <string name="permdesc_sim_communication" msgid="5725159654279639498">"Permite que o app envie comandos ao SIM. Muito perigoso."</string>
+    <string name="permlab_sim_communication" msgid="2935852302216852065">"enviar comandos para o chip"</string>
+    <string name="permdesc_sim_communication" msgid="5725159654279639498">"Permite que o app envie comandos ao chip. Muito perigoso."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"tirar fotos e gravar vídeos"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"Este app pode tirar fotos e gravar vídeos usando a câmera a qualquer momento."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"controlar vibração"</string>
@@ -514,6 +514,7 @@
     <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="biometric_error_hw_unavailable" msgid="645781226537551036">"Hardware biométrico indisponível"</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>
@@ -521,7 +522,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"O movimento do dedo está muito lento. Tente novamente."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Não reconhecido"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"Não reconhecido"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Impressão digital autenticada"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Hardware de impressão digital não disponível."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Não foi possível armazenar a impressão digital. Remova uma impressão digital já existente."</string>
@@ -795,14 +796,14 @@
     <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Tente novamente"</string>
     <string name="lockscreen_storage_locked" msgid="9167551160010625200">"Desbloqueio para todos os recursos e dados"</string>
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"O número máximo de tentativas de Desbloqueio por reconhecimento facial foi excedido"</string>
-    <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Sem cartão SIM"</string>
-    <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Não há um cartão SIM no tablet."</string>
-    <string name="lockscreen_missing_sim_message" product="tv" msgid="1943633865476989599">"Nenhum cartão SIM na TV."</string>
-    <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Não há um cartão SIM no telefone."</string>
-    <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"Insera um cartão SIM."</string>
-    <string name="lockscreen_missing_sim_instructions_long" msgid="3526573099019319472">"O cartão SIM não foi inserido ou não é possível lê-lo. Insira um cartão SIM."</string>
-    <string name="lockscreen_permanent_disabled_sim_message_short" msgid="5096149665138916184">"Cartão SIM inutilizável."</string>
-    <string name="lockscreen_permanent_disabled_sim_instructions" msgid="910904643433151371">"O cartão SIM foi desativado permanentemente.\nEntre em contato com seu provedor de serviços sem fio para obter outro cartão SIM."</string>
+    <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Sem chip"</string>
+    <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Não há um chip no tablet."</string>
+    <string name="lockscreen_missing_sim_message" product="tv" msgid="1943633865476989599">"Nenhum chip na TV."</string>
+    <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Não há um chip no telefone."</string>
+    <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"Insera um chip."</string>
+    <string name="lockscreen_missing_sim_instructions_long" msgid="3526573099019319472">"O chip não foi inserido ou não é possível lê-lo. Insira um chip."</string>
+    <string name="lockscreen_permanent_disabled_sim_message_short" msgid="5096149665138916184">"Chip inutilizável."</string>
+    <string name="lockscreen_permanent_disabled_sim_instructions" msgid="910904643433151371">"O chip foi desativado permanentemente.\nEntre em contato com seu provedor de serviços sem fio para obter outro chip."</string>
     <string name="lockscreen_transport_prev_description" msgid="6300840251218161534">"Faixa anterior"</string>
     <string name="lockscreen_transport_next_description" msgid="573285210424377338">"Próxima faixa"</string>
     <string name="lockscreen_transport_pause_description" msgid="3980308465056173363">"Pausar"</string>
@@ -812,10 +813,10 @@
     <string name="lockscreen_transport_ffw_description" msgid="42987149870928985">"Avançar"</string>
     <string name="emergency_calls_only" msgid="6733978304386365407">"Só chamadas de emergência"</string>
     <string name="lockscreen_network_locked_message" msgid="143389224986028501">"Rede bloqueada"</string>
-    <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"O cartão SIM está bloqueado pelo PUK."</string>
+    <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"O chip está bloqueado pelo PUK."</string>
     <string name="lockscreen_sim_puk_locked_instructions" msgid="8127916255245181063">"Consulte o Guia do usuário ou entre em contato com o Serviço de atendimento ao cliente."</string>
-    <string name="lockscreen_sim_locked_message" msgid="8066660129206001039">"O cartão SIM está bloqueado."</string>
-    <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"Desbloqueando o cartão SIM…"</string>
+    <string name="lockscreen_sim_locked_message" msgid="8066660129206001039">"O chip está bloqueado."</string>
+    <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"Desbloqueando o chip…"</string>
     <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="6481623830344107222">"Você desenhou seu padrão de desbloqueio incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. \n\nTente novamente em <xliff:g id="NUMBER_1">%2$d</xliff:g> segundos."</string>
     <string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="2725973286239344555">"Você digitou sua senha incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. \n\nTente novamente em <xliff:g id="NUMBER_1">%2$d</xliff:g> segundos."</string>
     <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6216672706545696955">"Você digitou seu PIN incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes.\n\nTente novamente em <xliff:g id="NUMBER_1">%2$d</xliff:g> segundos."</string>
@@ -866,8 +867,8 @@
     <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Desbloqueio com padrão."</string>
     <string name="keyguard_accessibility_face_unlock" msgid="4817282543351718535">"Desbloqueio facial."</string>
     <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Desbloqueio com PIN."</string>
-    <string name="keyguard_accessibility_sim_pin_unlock" msgid="9149698847116962307">"Desbloqueio com PIN do SIM."</string>
-    <string name="keyguard_accessibility_sim_puk_unlock" msgid="9106899279724723341">"Desbloqueio com PUK do SIM."</string>
+    <string name="keyguard_accessibility_sim_pin_unlock" msgid="9149698847116962307">"Desbloqueio com PIN do chip."</string>
+    <string name="keyguard_accessibility_sim_puk_unlock" msgid="9106899279724723341">"Desbloqueio com PUK do chip."</string>
     <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Desbloqueio com senha."</string>
     <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Área do padrão."</string>
     <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Área de deslize."</string>
@@ -1277,17 +1278,17 @@
     <string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"P/ alterar: Configurações &gt; Apps"</string>
     <string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Sempre permitir"</string>
     <string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Nunca permitir"</string>
-    <string name="sim_removed_title" msgid="6227712319223226185">"Cartão SIM removido"</string>
-    <string name="sim_removed_message" msgid="2333164559970958645">"A rede móvel ficará indisponível até que você reinicie com um cartão SIM válido inserido."</string>
+    <string name="sim_removed_title" msgid="6227712319223226185">"Chip removido"</string>
+    <string name="sim_removed_message" msgid="2333164559970958645">"A rede móvel ficará indisponível até que você reinicie com um chip válido inserido."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Concluído"</string>
-    <string name="sim_added_title" msgid="3719670512889674693">"Cartão SIM adicionado"</string>
+    <string name="sim_added_title" msgid="3719670512889674693">"Chip adicionado"</string>
     <string name="sim_added_message" msgid="6599945301141050216">"Reinicie o dispositivo para acessar a rede móvel."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"Reiniciar"</string>
     <string name="install_carrier_app_notification_title" msgid="9056007111024059888">"Ativar serviço móvel"</string>
-    <string name="install_carrier_app_notification_text" msgid="3346681446158696001">"Faça o download do app da operadora para ativar seu novo SIM"</string>
-    <string name="install_carrier_app_notification_text_app_name" msgid="1196505084835248137">"Faça o download do app <xliff:g id="APP_NAME">%1$s</xliff:g> para ativar seu novo SIM"</string>
+    <string name="install_carrier_app_notification_text" msgid="3346681446158696001">"Faça o download do app da operadora para ativar seu novo chip"</string>
+    <string name="install_carrier_app_notification_text_app_name" msgid="1196505084835248137">"Faça o download do app <xliff:g id="APP_NAME">%1$s</xliff:g> para ativar seu novo chip"</string>
     <string name="install_carrier_app_notification_button" msgid="3094206295081900849">"Fazer download do app"</string>
-    <string name="carrier_app_notification_title" msgid="8921767385872554621">"Novo SIM inserido"</string>
+    <string name="carrier_app_notification_title" msgid="8921767385872554621">"Novo chip inserido"</string>
     <string name="carrier_app_notification_text" msgid="1132487343346050225">"Toque para configurar"</string>
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Definir hora"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Definir data"</string>
@@ -1572,17 +1573,17 @@
       <item quantity="other">Tente novamente em <xliff:g id="NUMBER">%d</xliff:g> segundos.</item>
     </plurals>
     <string name="kg_pattern_instructions" msgid="398978611683075868">"Desenhe seu padrão"</string>
-    <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"Digite o PIN do cartão SIM"</string>
+    <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"Digite o PIN do chip"</string>
     <string name="kg_pin_instructions" msgid="2377242233495111557">"Digite o PIN"</string>
     <string name="kg_password_instructions" msgid="5753646556186936819">"Digite a senha"</string>
-    <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"O SIM foi desativado. Insira o código PUK para continuar. Entre em contato com a operadora para obter mais detalhes."</string>
+    <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"O chip foi desativado. Insira o código PUK para continuar. Entre em contato com a operadora para obter mais detalhes."</string>
     <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"Digite o código PIN desejado"</string>
     <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"Confirme o código PIN desejado"</string>
-    <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"Desbloqueando o cartão SIM…"</string>
+    <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"Desbloqueando o chip…"</string>
     <string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"Código PIN incorreto."</string>
     <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"Digite um PIN com quatro a oito números."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="6025069204539532000">"O código PUK deve ter oito números."</string>
-    <string name="kg_invalid_puk" msgid="3638289409676051243">"Introduza novamente o código PUK correto. Muitas tentativas malsucedidas desativarão permanentemente o SIM."</string>
+    <string name="kg_invalid_puk" msgid="3638289409676051243">"Introduza novamente o código PUK correto. Muitas tentativas malsucedidas desativarão permanentemente o chip."</string>
     <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"Os códigos PIN não coincidem"</string>
     <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"Muitas tentativas de padrão"</string>
     <string name="kg_login_instructions" msgid="1100551261265506448">"Para desbloquear, faça login usando sua Conta do Google."</string>
@@ -1910,9 +1911,9 @@
     <string name="etws_primary_default_message_test" msgid="2709597093560037455">"Teste de mensagens de emergência"</string>
     <string name="notification_reply_button_accessibility" msgid="3621714652387814344">"Responder"</string>
     <string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
-    <string name="mmcc_authentication_reject" msgid="5767701075994754356">"SIM não autorizado para voz"</string>
-    <string name="mmcc_imsi_unknown_in_hlr" msgid="5316658473301462825">"SIM não aprovisionado para voz"</string>
-    <string name="mmcc_illegal_ms" msgid="807334478177362062">"SIM não autorizado para voz"</string>
+    <string name="mmcc_authentication_reject" msgid="5767701075994754356">"Chip não autorizado para voz"</string>
+    <string name="mmcc_imsi_unknown_in_hlr" msgid="5316658473301462825">"Chip não aprovisionado para voz"</string>
+    <string name="mmcc_illegal_ms" msgid="807334478177362062">"Chip não autorizado para voz"</string>
     <string name="mmcc_illegal_me" msgid="1950705155760872972">"Smartphone não autorizado para voz"</string>
     <string name="mmcc_authentication_reject_msim_template" msgid="1217031195834766479">"SIM <xliff:g id="SIMNUMBER">%d</xliff:g> não permitido"</string>
     <string name="mmcc_imsi_unknown_in_hlr_msim_template" msgid="5636464607596778986">"SIM <xliff:g id="SIMNUMBER">%d</xliff:g> não aprovisionado"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 631e9f3..3f02828 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -514,6 +514,7 @@
     <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="biometric_error_hw_unavailable" msgid="645781226537551036">"Hardware biométrico indisponível."</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>
@@ -521,7 +522,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Moveu o dedo demasiado lentamente. Tente novamente."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Não reconhecido"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"Não reconhecido."</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"A impressão digital foi autenticada."</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Hardware de impressão digital não disponível."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Não é possível armazenar a impressão digital. Remova uma impressão digital existente."</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index ad68dde..48302a0 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -47,12 +47,12 @@
     <string name="mismatchPin" msgid="609379054496863419">"Os PINs digitados não correspondem."</string>
     <string name="invalidPin" msgid="3850018445187475377">"Digite um PIN com 4 a 8 números."</string>
     <string name="invalidPuk" msgid="8761456210898036513">"Digite um PUK com oito números ou mais."</string>
-    <string name="needPuk" msgid="919668385956251611">"O seu cartão SIM está bloqueado por um PUK. Digite o código PUK para desbloqueá-lo."</string>
-    <string name="needPuk2" msgid="4526033371987193070">"Digite o PUK2 para desbloquear o cartão SIM."</string>
-    <string name="enablePin" msgid="209412020907207950">"Falha. Ative o bloqueio do SIM/R-UIM."</string>
+    <string name="needPuk" msgid="919668385956251611">"O seu chip está bloqueado por um PUK. Digite o código PUK para desbloqueá-lo."</string>
+    <string name="needPuk2" msgid="4526033371987193070">"Digite o PUK2 para desbloquear o chip."</string>
+    <string name="enablePin" msgid="209412020907207950">"Falha. Ative o bloqueio do chip/R-UIM."</string>
     <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
-      <item quantity="one">Tentativas restantes: <xliff:g id="NUMBER_1">%d</xliff:g>. Caso o código correto não seja digitado, o SIM será bloqueado.</item>
-      <item quantity="other">Tentativas restantes: <xliff:g id="NUMBER_1">%d</xliff:g>. Caso o código correto não seja digitado, o SIM será bloqueado.</item>
+      <item quantity="one">Tentativas restantes: <xliff:g id="NUMBER_1">%d</xliff:g>. Caso o código correto não seja digitado, o chip será bloqueado.</item>
+      <item quantity="other">Tentativas restantes: <xliff:g id="NUMBER_1">%d</xliff:g>. Caso o código correto não seja digitado, o chip será bloqueado.</item>
     </plurals>
     <string name="imei" msgid="2625429890869005782">"IMEI"</string>
     <string name="meid" msgid="4841221237681254195">"MEID"</string>
@@ -82,7 +82,7 @@
     <string name="RestrictedOnNormalTitle" msgid="3179574012752700984">"Sem serviço de voz"</string>
     <string name="RestrictedOnAllVoiceTitle" msgid="8037246983606545202">"Nenhum serviço de voz nem chamada de emergência"</string>
     <string name="RestrictedStateContent" msgid="6538703255570997248">"Temporariamente desativado pela sua operadora"</string>
-    <string name="RestrictedStateContentMsimTemplate" msgid="673416791370248176">"Temporariamente desativado pela sua operadora para o SIM <xliff:g id="SIMNUMBER">%d</xliff:g>"</string>
+    <string name="RestrictedStateContentMsimTemplate" msgid="673416791370248176">"Temporariamente desativado pela sua operadora para o chip <xliff:g id="SIMNUMBER">%d</xliff:g>"</string>
     <string name="NetworkPreferenceSwitchTitle" msgid="6982395015324165258">"Não foi possível acessar a rede móvel"</string>
     <string name="NetworkPreferenceSwitchSummary" msgid="509327194863482733">"Tente alterar a rede preferencial. Toque para alterar."</string>
     <string name="EmergencyCallWarningTitle" msgid="813380189532491336">"Chamadas de emergência indisponíveis"</string>
@@ -94,7 +94,7 @@
     <string name="notification_channel_sms" msgid="3441746047346135073">"Mensagens SMS"</string>
     <string name="notification_channel_voice_mail" msgid="3954099424160511919">"Mensagens do correio de voz"</string>
     <string name="notification_channel_wfc" msgid="2130802501654254801">"Chamadas por Wi-Fi"</string>
-    <string name="notification_channel_sim" msgid="4052095493875188564">"Status do SIM"</string>
+    <string name="notification_channel_sim" msgid="4052095493875188564">"Status do chip"</string>
     <string name="peerTtyModeFull" msgid="6165351790010341421">"TTD modo COMPLETO solicitado"</string>
     <string name="peerTtyModeHco" msgid="5728602160669216784">"TTD modo HCO solicitado"</string>
     <string name="peerTtyModeVco" msgid="1742404978686538049">"TTD modo VCO solicitado"</string>
@@ -420,8 +420,8 @@
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Permite que o app modifique configurações de áudio globais como volume e alto-falantes de saída."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"gravar áudio"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"Este app pode gravar áudio usando o microfone a qualquer momento."</string>
-    <string name="permlab_sim_communication" msgid="2935852302216852065">"enviar comandos para o SIM"</string>
-    <string name="permdesc_sim_communication" msgid="5725159654279639498">"Permite que o app envie comandos ao SIM. Muito perigoso."</string>
+    <string name="permlab_sim_communication" msgid="2935852302216852065">"enviar comandos para o chip"</string>
+    <string name="permdesc_sim_communication" msgid="5725159654279639498">"Permite que o app envie comandos ao chip. Muito perigoso."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"tirar fotos e gravar vídeos"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"Este app pode tirar fotos e gravar vídeos usando a câmera a qualquer momento."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"controlar vibração"</string>
@@ -514,6 +514,7 @@
     <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="biometric_error_hw_unavailable" msgid="645781226537551036">"Hardware biométrico indisponível"</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>
@@ -521,7 +522,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"O movimento do dedo está muito lento. Tente novamente."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Não reconhecido"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"Não reconhecido"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Impressão digital autenticada"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Hardware de impressão digital não disponível."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Não foi possível armazenar a impressão digital. Remova uma impressão digital já existente."</string>
@@ -795,14 +796,14 @@
     <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Tente novamente"</string>
     <string name="lockscreen_storage_locked" msgid="9167551160010625200">"Desbloqueio para todos os recursos e dados"</string>
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"O número máximo de tentativas de Desbloqueio por reconhecimento facial foi excedido"</string>
-    <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Sem cartão SIM"</string>
-    <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Não há um cartão SIM no tablet."</string>
-    <string name="lockscreen_missing_sim_message" product="tv" msgid="1943633865476989599">"Nenhum cartão SIM na TV."</string>
-    <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Não há um cartão SIM no telefone."</string>
-    <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"Insera um cartão SIM."</string>
-    <string name="lockscreen_missing_sim_instructions_long" msgid="3526573099019319472">"O cartão SIM não foi inserido ou não é possível lê-lo. Insira um cartão SIM."</string>
-    <string name="lockscreen_permanent_disabled_sim_message_short" msgid="5096149665138916184">"Cartão SIM inutilizável."</string>
-    <string name="lockscreen_permanent_disabled_sim_instructions" msgid="910904643433151371">"O cartão SIM foi desativado permanentemente.\nEntre em contato com seu provedor de serviços sem fio para obter outro cartão SIM."</string>
+    <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Sem chip"</string>
+    <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Não há um chip no tablet."</string>
+    <string name="lockscreen_missing_sim_message" product="tv" msgid="1943633865476989599">"Nenhum chip na TV."</string>
+    <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Não há um chip no telefone."</string>
+    <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"Insera um chip."</string>
+    <string name="lockscreen_missing_sim_instructions_long" msgid="3526573099019319472">"O chip não foi inserido ou não é possível lê-lo. Insira um chip."</string>
+    <string name="lockscreen_permanent_disabled_sim_message_short" msgid="5096149665138916184">"Chip inutilizável."</string>
+    <string name="lockscreen_permanent_disabled_sim_instructions" msgid="910904643433151371">"O chip foi desativado permanentemente.\nEntre em contato com seu provedor de serviços sem fio para obter outro chip."</string>
     <string name="lockscreen_transport_prev_description" msgid="6300840251218161534">"Faixa anterior"</string>
     <string name="lockscreen_transport_next_description" msgid="573285210424377338">"Próxima faixa"</string>
     <string name="lockscreen_transport_pause_description" msgid="3980308465056173363">"Pausar"</string>
@@ -812,10 +813,10 @@
     <string name="lockscreen_transport_ffw_description" msgid="42987149870928985">"Avançar"</string>
     <string name="emergency_calls_only" msgid="6733978304386365407">"Só chamadas de emergência"</string>
     <string name="lockscreen_network_locked_message" msgid="143389224986028501">"Rede bloqueada"</string>
-    <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"O cartão SIM está bloqueado pelo PUK."</string>
+    <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"O chip está bloqueado pelo PUK."</string>
     <string name="lockscreen_sim_puk_locked_instructions" msgid="8127916255245181063">"Consulte o Guia do usuário ou entre em contato com o Serviço de atendimento ao cliente."</string>
-    <string name="lockscreen_sim_locked_message" msgid="8066660129206001039">"O cartão SIM está bloqueado."</string>
-    <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"Desbloqueando o cartão SIM…"</string>
+    <string name="lockscreen_sim_locked_message" msgid="8066660129206001039">"O chip está bloqueado."</string>
+    <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"Desbloqueando o chip…"</string>
     <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="6481623830344107222">"Você desenhou seu padrão de desbloqueio incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. \n\nTente novamente em <xliff:g id="NUMBER_1">%2$d</xliff:g> segundos."</string>
     <string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="2725973286239344555">"Você digitou sua senha incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. \n\nTente novamente em <xliff:g id="NUMBER_1">%2$d</xliff:g> segundos."</string>
     <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6216672706545696955">"Você digitou seu PIN incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes.\n\nTente novamente em <xliff:g id="NUMBER_1">%2$d</xliff:g> segundos."</string>
@@ -866,8 +867,8 @@
     <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Desbloqueio com padrão."</string>
     <string name="keyguard_accessibility_face_unlock" msgid="4817282543351718535">"Desbloqueio facial."</string>
     <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Desbloqueio com PIN."</string>
-    <string name="keyguard_accessibility_sim_pin_unlock" msgid="9149698847116962307">"Desbloqueio com PIN do SIM."</string>
-    <string name="keyguard_accessibility_sim_puk_unlock" msgid="9106899279724723341">"Desbloqueio com PUK do SIM."</string>
+    <string name="keyguard_accessibility_sim_pin_unlock" msgid="9149698847116962307">"Desbloqueio com PIN do chip."</string>
+    <string name="keyguard_accessibility_sim_puk_unlock" msgid="9106899279724723341">"Desbloqueio com PUK do chip."</string>
     <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Desbloqueio com senha."</string>
     <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Área do padrão."</string>
     <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Área de deslize."</string>
@@ -1277,17 +1278,17 @@
     <string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"P/ alterar: Configurações &gt; Apps"</string>
     <string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Sempre permitir"</string>
     <string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Nunca permitir"</string>
-    <string name="sim_removed_title" msgid="6227712319223226185">"Cartão SIM removido"</string>
-    <string name="sim_removed_message" msgid="2333164559970958645">"A rede móvel ficará indisponível até que você reinicie com um cartão SIM válido inserido."</string>
+    <string name="sim_removed_title" msgid="6227712319223226185">"Chip removido"</string>
+    <string name="sim_removed_message" msgid="2333164559970958645">"A rede móvel ficará indisponível até que você reinicie com um chip válido inserido."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Concluído"</string>
-    <string name="sim_added_title" msgid="3719670512889674693">"Cartão SIM adicionado"</string>
+    <string name="sim_added_title" msgid="3719670512889674693">"Chip adicionado"</string>
     <string name="sim_added_message" msgid="6599945301141050216">"Reinicie o dispositivo para acessar a rede móvel."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"Reiniciar"</string>
     <string name="install_carrier_app_notification_title" msgid="9056007111024059888">"Ativar serviço móvel"</string>
-    <string name="install_carrier_app_notification_text" msgid="3346681446158696001">"Faça o download do app da operadora para ativar seu novo SIM"</string>
-    <string name="install_carrier_app_notification_text_app_name" msgid="1196505084835248137">"Faça o download do app <xliff:g id="APP_NAME">%1$s</xliff:g> para ativar seu novo SIM"</string>
+    <string name="install_carrier_app_notification_text" msgid="3346681446158696001">"Faça o download do app da operadora para ativar seu novo chip"</string>
+    <string name="install_carrier_app_notification_text_app_name" msgid="1196505084835248137">"Faça o download do app <xliff:g id="APP_NAME">%1$s</xliff:g> para ativar seu novo chip"</string>
     <string name="install_carrier_app_notification_button" msgid="3094206295081900849">"Fazer download do app"</string>
-    <string name="carrier_app_notification_title" msgid="8921767385872554621">"Novo SIM inserido"</string>
+    <string name="carrier_app_notification_title" msgid="8921767385872554621">"Novo chip inserido"</string>
     <string name="carrier_app_notification_text" msgid="1132487343346050225">"Toque para configurar"</string>
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Definir hora"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Definir data"</string>
@@ -1572,17 +1573,17 @@
       <item quantity="other">Tente novamente em <xliff:g id="NUMBER">%d</xliff:g> segundos.</item>
     </plurals>
     <string name="kg_pattern_instructions" msgid="398978611683075868">"Desenhe seu padrão"</string>
-    <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"Digite o PIN do cartão SIM"</string>
+    <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"Digite o PIN do chip"</string>
     <string name="kg_pin_instructions" msgid="2377242233495111557">"Digite o PIN"</string>
     <string name="kg_password_instructions" msgid="5753646556186936819">"Digite a senha"</string>
-    <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"O SIM foi desativado. Insira o código PUK para continuar. Entre em contato com a operadora para obter mais detalhes."</string>
+    <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"O chip foi desativado. Insira o código PUK para continuar. Entre em contato com a operadora para obter mais detalhes."</string>
     <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"Digite o código PIN desejado"</string>
     <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"Confirme o código PIN desejado"</string>
-    <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"Desbloqueando o cartão SIM…"</string>
+    <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"Desbloqueando o chip…"</string>
     <string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"Código PIN incorreto."</string>
     <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"Digite um PIN com quatro a oito números."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="6025069204539532000">"O código PUK deve ter oito números."</string>
-    <string name="kg_invalid_puk" msgid="3638289409676051243">"Introduza novamente o código PUK correto. Muitas tentativas malsucedidas desativarão permanentemente o SIM."</string>
+    <string name="kg_invalid_puk" msgid="3638289409676051243">"Introduza novamente o código PUK correto. Muitas tentativas malsucedidas desativarão permanentemente o chip."</string>
     <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"Os códigos PIN não coincidem"</string>
     <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"Muitas tentativas de padrão"</string>
     <string name="kg_login_instructions" msgid="1100551261265506448">"Para desbloquear, faça login usando sua Conta do Google."</string>
@@ -1910,9 +1911,9 @@
     <string name="etws_primary_default_message_test" msgid="2709597093560037455">"Teste de mensagens de emergência"</string>
     <string name="notification_reply_button_accessibility" msgid="3621714652387814344">"Responder"</string>
     <string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
-    <string name="mmcc_authentication_reject" msgid="5767701075994754356">"SIM não autorizado para voz"</string>
-    <string name="mmcc_imsi_unknown_in_hlr" msgid="5316658473301462825">"SIM não aprovisionado para voz"</string>
-    <string name="mmcc_illegal_ms" msgid="807334478177362062">"SIM não autorizado para voz"</string>
+    <string name="mmcc_authentication_reject" msgid="5767701075994754356">"Chip não autorizado para voz"</string>
+    <string name="mmcc_imsi_unknown_in_hlr" msgid="5316658473301462825">"Chip não aprovisionado para voz"</string>
+    <string name="mmcc_illegal_ms" msgid="807334478177362062">"Chip não autorizado para voz"</string>
     <string name="mmcc_illegal_me" msgid="1950705155760872972">"Smartphone não autorizado para voz"</string>
     <string name="mmcc_authentication_reject_msim_template" msgid="1217031195834766479">"SIM <xliff:g id="SIMNUMBER">%d</xliff:g> não permitido"</string>
     <string name="mmcc_imsi_unknown_in_hlr_msim_template" msgid="5636464607596778986">"SIM <xliff:g id="SIMNUMBER">%d</xliff:g> não aprovisionado"</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index efd68ac..1c95559 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -517,6 +517,7 @@
     <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="biometric_error_hw_unavailable" msgid="645781226537551036">"Hardware biometric indisponibil"</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>
@@ -524,7 +525,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Ați mișcat degetul prea lent. Încercați din nou."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Nu este recunoscută"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"Nu este recunoscut"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Amprentă autentificată"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Hardware-ul pentru amprentă nu este disponibil."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Amprenta nu poate fi stocată. Eliminați o amprentă existentă."</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 6cc870c..c14bce4 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -290,7 +290,7 @@
     <string name="permgrouprequest_sms" msgid="7168124215838204719">"Разрешить приложению &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; отправлять и просматривать SMS?"</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Хранилище"</string>
     <string name="permgroupdesc_storage" msgid="637758554581589203">"доступ к фото, мультимедиа и файлам на вашем устройстве"</string>
-    <string name="permgrouprequest_storage" msgid="7885942926944299560">"Разрешить приложению &lt;b&gt;\"<xliff:g id="APP_NAME">%1$s</xliff:g>\"&lt;/b&gt; доступ к фото, мультимедиа и файлам на устройстве?"</string>
+    <string name="permgrouprequest_storage" msgid="7885942926944299560">"Разрешить приложению &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; доступ к фото, мультимедиа и файлам на устройстве?"</string>
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Микрофон"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"записывать аудио"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"Разрешить приложению &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; записывать аудио?"</string>
@@ -305,7 +305,7 @@
     <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="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>
@@ -520,6 +520,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Приложение сможет вносить изменения в вашу фотоколлекцию."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"доступ к геоданным в медиаколлекции"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Приложение получит доступ к геоданным в вашей медиаколлекции."</string>
+    <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"Биометрическое оборудование недоступно"</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,7 +528,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Вы перемещали палец слишком медленно. Повторите попытку."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Не распознано"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"Не распознано"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Отпечаток пальца проверен"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Сканер недоступен"</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Чтобы сохранить новый отпечаток, удалите существующий."</string>
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index c263589..0f353f2 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -514,6 +514,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"ඔබගේ ඡායාරූප එකතුව වෙනස් කිරීමට යෙදුමට ඉඩ දෙයි."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"ඔබගේ මාධ්‍ය එකතුවෙන් ස්ථාන කියවන්න"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"ඔබගේ මාධ්‍ය එකතුවෙන් ස්ථාන කියවීමට යෙදුමට ඉඩ දෙයි."</string>
+    <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"ජීවමිතික දෘඪාංග ලබා ගත නොහැකිය"</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,7 +522,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"ඇඟිල්ල වඩා සෙමෙන් ගෙන යන ලදි. කරුණාකර නැවත උත්සාහ කරන්න."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"අඳුනාගත නොහැක"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"හඳුනා නොගන්නා ලදී"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"ඇඟිලි සලකුණ සත්‍යාපනය කරන ලදී"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"ඇඟිලි සලකුණු දෘඪාංගය ලද නොහැකිය."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"ඇඟිලි සලකුණ ගබඩා කළ නොහැක. දැනට පවතින ඇඟිලි සලකුණක් ඉවත් කරන්න."</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index f3569c9..3109702 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -520,6 +520,7 @@
     <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="biometric_error_hw_unavailable" msgid="645781226537551036">"Biometrický hardvér nie je k dispozícii"</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>
@@ -527,7 +528,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Pohli ste prstom príliš pomaly. Skúste to znova."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Nebol rozpoznaný"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"Nerozpoznané"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Odtlačok bol overený"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Hardvér na snímanie odtlačku prsta nie je k dispozícii"</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Odtlačok prsta nie je možné uložiť. Odstráňte existujúci odtlačok."</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 0f9d038..4575d00 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -520,6 +520,7 @@
     <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="biometric_error_hw_unavailable" msgid="645781226537551036">"Strojna oprema za biometrične podatke ni na voljo"</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>
@@ -527,7 +528,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Prepočasen premik prsta. Poskusite znova."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Ni prepoznano"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"Ni prepoznano"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Pristnost prstnega odtisa je preverjena"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Strojna oprema za prstne odtise ni na voljo."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Prstnega odtisa ni mogoče shraniti. Odstranite obstoječi prstni odtis."</string>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index 17ec70d..1149421 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -284,7 +284,7 @@
     <string name="permgrouprequest_sms" msgid="7168124215838204719">"Të lejohet që &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; të dërgojë dhe të shikojë mesazhet SMS?"</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Hapësira e ruajtjes"</string>
     <string name="permgroupdesc_storage" msgid="637758554581589203">"qasjen te fotografitë, përmbajtjet audio-vizuale dhe skedarët në pajisje"</string>
-    <string name="permgrouprequest_storage" msgid="7885942926944299560">"Të lejohet që &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; të ketë qasje te fotografitë, media dhe skedarët në pajisjen tënde?"</string>
+    <string name="permgrouprequest_storage" msgid="7885942926944299560">"Të lejohet apl. &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; që të ketë qasje te fotografitë, media dhe skedarët në pajisjen tënde?"</string>
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Mikrofoni"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"regjistro audio"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"Të lejohet që &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; të regjistrojë audio?"</string>
@@ -514,6 +514,7 @@
     <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="biometric_error_hw_unavailable" msgid="645781226537551036">"Nuk ofrohet harduer biometrik"</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>
@@ -521,7 +522,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Gishti lëvizi shumë ngadalë. Provo përsëri."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Nuk njihet"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"Nuk njihet"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Gjurma e gishtit u vërtetua"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Hardueri i gjurmës së gishtit nuk mundësohet."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Gjurma e gishtit nuk mund të ruhet. Hiq një gjurmë gishti ekzistuese."</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 517815d..7536531 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -517,6 +517,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Дозвољава апликацији да мења колекцију слика."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"читање локација из медијске колекције"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Дозвољава апликацији да чита локације из медијске колекције."</string>
+    <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"Биометријски хардвер није доступан"</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 +525,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Превише споро сте померили прст. Пробајте поново."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Није препознат"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"Није препознато"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Отисак прста је потврђен"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Хардвер за отиске прстију није доступан."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Није могуће сачувати отисак прста. Уклоните неки од постојећих отисака прстију."</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 835f198..31bb349 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -514,6 +514,7 @@
     <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="biometric_error_hw_unavailable" msgid="645781226537551036">"Biometrisk maskinvara är inte tillgänglig"</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>
@@ -521,7 +522,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Du rörde fingret för långsamt. Försök igen."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Identifierades inte"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"Identifierades inte"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Fingeravtrycket har autentiserats"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Det finns ingen maskinvara för fingeravtryck."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Fingeravtrycket kan inte lagras. Ta bort ett befintligt fingeravtryck."</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index c846f08..3d26224 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -282,7 +282,7 @@
     <string name="permgrouprequest_sms" msgid="7168124215838204719">"Ungependa kuiruhusu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; itume na ione ujumbe wa SMS?"</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Hifadhi"</string>
     <string name="permgroupdesc_storage" msgid="637758554581589203">"ifikie picha, maudhui na faili kwenye kifaa chako"</string>
-    <string name="permgrouprequest_storage" msgid="7885942926944299560">"Ungependa kuiruhusu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ifikie picha, maudhui na faili kwenye kifaa chako?"</string>
+    <string name="permgrouprequest_storage" msgid="7885942926944299560">"Ungependa &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ifikie picha, maudhui na faili kwenye kifaa chako?"</string>
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Kipokea sauti"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"irekodi sauti"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"Ungependa kuiruhusu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; irekodi sauti?"</string>
@@ -512,6 +512,7 @@
     <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="biometric_error_hw_unavailable" msgid="645781226537551036">"Maunzi ya bayometriki hayapatikani"</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>
@@ -519,7 +520,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Kidole kilisogezwa polepole zaidi. Tafadhali jaribu tena."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Haitambuliwi"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"Hayatambuliki"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Imethibitisha alama ya kidole"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Maunzi ya kitambulisho hayapatikani."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Kitambulisho hakiwezi kuhifadhiwa. Tafadhali ondoa kitambulisho kilichopo."</string>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index ba58742..35592a6 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -284,7 +284,7 @@
     <string name="permgrouprequest_sms" msgid="7168124215838204719">"மெசேஜ்களை அனுப்பவும், பார்க்கவும் &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ஆப்ஸை அனுமதிக்கவா?"</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"சேமிப்பிடம்"</string>
     <string name="permgroupdesc_storage" msgid="637758554581589203">"உங்கள் சாதனத்தில் உள்ள படங்கள், மீடியா மற்றும் கோப்புகளை அணுக வேண்டும்"</string>
-    <string name="permgrouprequest_storage" msgid="7885942926944299560">"உங்கள் சாதனத்திலுள்ள படங்கள், மீடியா, ஃபைல்கள் ஆகியவற்றை அணுகுவதற்கு &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; பயன்பாட்டை அனுமதிக்கவா?"</string>
+    <string name="permgrouprequest_storage" msgid="7885942926944299560">"உங்கள் சாதனத்திலுள்ள படங்கள், மீடியா, ஃபைல்கள் ஆகியவற்றை அணுகுவதற்கு &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ஆப்ஸை அனுமதிக்கவா?"</string>
     <string name="permgrouplab_microphone" msgid="171539900250043464">"மைக்ரோஃபோன்"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"ஒலிப் பதிவு செய்யலாம்"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"ஆடியோவைப் பதிவு செய்ய &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; பயன்பாட்டை அனுமதிக்கவா?"</string>
@@ -514,6 +514,8 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"உங்களின் படத் தொகுப்பை மாற்ற ஆப்ஸை அனுமதிக்கும்."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"மீடியா தொகுப்பிலிருந்து இடங்களை அறிதல்"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"உங்களின் மீடியா தொகுப்பிலிருந்து இடங்களை அறிந்துகொள்ள ஆப்ஸை அனுமதிக்கும்."</string>
+    <!-- no translation found for biometric_error_hw_unavailable (645781226537551036) -->
+    <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>
@@ -521,7 +523,8 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"விரலை மிகவும் மெதுவாக நகர்த்திவிட்டீர்கள். மீண்டும் முயற்சிக்கவும்."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"அறியப்படவில்லை"</string>
+    <!-- no translation found for biometric_not_recognized (5770511773560736082) -->
+    <skip />
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"கைரேகை அங்கீகரிக்கப்பட்டது"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"கைரேகை வன்பொருள் இல்லை."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"கைரேகையைச் சேமிக்க முடியவில்லை. ஏற்கனவே உள்ள கைரேகையை அகற்றவும்."</string>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index b0d7a4dc..2027d33 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -514,6 +514,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"మీ ఫోటో సేకరణను సవరించడానికి యాప్‌ను అనుమతిస్తుంది."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"మీ మీడియా సేకరణ నుండి స్థానాలను చదవండి"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"మీ మీడియా సేకరణ నుండి స్థానాలను చదవడానికి యాప్‌ను అనుమతిస్తుంది."</string>
+    <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"బయోమెట్రిక్ హార్డ్‌వేర్‌ అందుబాటులో లేదు"</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,7 +522,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"వేలిని చాలా నెమ్మదిగా కదిలించారు. దయచేసి మళ్లీ ప్రయత్నించండి."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"గుర్తించలేదు"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"గుర్తించలేదు"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"వేలిముద్ర ప్రమాణీకరించబడింది"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"వేలిముద్ర హార్డ్‌వేర్ అందుబాటులో లేదు."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"వేలిముద్రను నిల్వ చేయడం సాధ్యపడదు. దయచేసి ఇప్పటికే ఉన్న వేలిముద్రను తీసివేయండి."</string>
diff --git a/core/res/res/values-television/themes.xml b/core/res/res/values-television/themes.xml
index 377982a..0712cbc 100644
--- a/core/res/res/values-television/themes.xml
+++ b/core/res/res/values-television/themes.xml
@@ -15,7 +15,7 @@
 -->
 <resources>
     <style name="Theme.Dialog.Alert" parent="Theme.Leanback.Light.Dialog.Alert" />
-    <style name="Theme.Dialog.AppError" parent="Theme.Leanback.Dialog.AppError" />
+    <style name="Theme.DeviceDefault.Dialog.AppError" parent="Theme.Leanback.Dialog.AppError" />
     <style name="Theme.Holo.Dialog.Alert" parent="Theme.Leanback.Dialog.Alert" />
     <style name="Theme.Holo.Light.Dialog.Alert" parent="Theme.Leanback.Light.Dialog.Alert" />
     <style name="Theme.Material.Dialog.Alert" parent="Theme.Leanback.Dialog.Alert" />
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 07107cb..84fd018 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -514,6 +514,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"อนุญาตให้แอปแก้ไขคอลเล็กชันรูปภาพของคุณ"</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"อ่านตำแหน่งจากคอลเล็กชันสื่อของคุณ"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"อนุญาตให้แอปอ่านตำแหน่งจากคอลเล็กชันสื่อของคุณ"</string>
+    <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"ฮาร์ดแวร์ไบโอเมตริกไม่พร้อมใช้งาน"</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,7 +522,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"นิ้วเคลื่อนที่ช้าเกินไป โปรดลองอีกครั้ง"</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"ไม่รู้จัก"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"ไม่รู้จัก"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"ตรวจสอบสิทธิ์ลายนิ้วมือแล้ว"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"ฮาร์ดแวร์ลายนิ้วมือไม่พร้อมใช้งาน"</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"ไม่สามารถเก็บลายนิ้วมือได้ โปรดนำลายนิ้วมือที่มีอยู่ออก"</string>
@@ -1509,7 +1510,7 @@
     <string name="data_usage_mobile_limit_snoozed_title" msgid="3171402244827034372">"เกินปริมาณเน็ตมือถือที่กำหนดไว้"</string>
     <string name="data_usage_wifi_limit_snoozed_title" msgid="3547771791046344188">"เกินขีดจำกัดของข้อมูล Wi-Fi"</string>
     <string name="data_usage_limit_snoozed_body" msgid="1671222777207603301">"คุณใช้อินเทอร์เน็ตเกินไป <xliff:g id="SIZE">%s</xliff:g> จากปริมาณที่กำหนดไว้"</string>
-    <string name="data_usage_restricted_title" msgid="5965157361036321914">"จำกัดข้อมูลแบ็กกราวด์"</string>
+    <string name="data_usage_restricted_title" msgid="5965157361036321914">"จำกัดอินเทอร์เน็ตที่ใช้งานอยู่เบื้องหลัง"</string>
     <string name="data_usage_restricted_body" msgid="469866376337242726">"แตะเพื่อนำข้อจำกัดออก"</string>
     <string name="data_usage_rapid_title" msgid="1809795402975261331">"ปริมาณการใช้เน็ตมือถือสูง"</string>
     <string name="data_usage_rapid_body" msgid="6897825788682442715">"แอปของคุณใช้อินเทอร์เน็ตมากกว่าปกติ"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index c4b14f7..49318cf 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -514,6 +514,7 @@
     <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="biometric_error_hw_unavailable" msgid="645781226537551036">"Walang biometric hardware"</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>
@@ -521,7 +522,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Masyadong mabagal ang paggalaw ng daliri. Pakisubukang muli."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Hindi nakilala"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"Hindi nakilala"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Na-authenticate ang fingerprint"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Hindi available ang hardware na ginagamitan ng fingerprint."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Hindi maiimbak ang fingerprint. Mangyaring mag-alis ng umiiral nang fingerprint."</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 67991e1..c6d18ec 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -514,6 +514,7 @@
     <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="biometric_error_hw_unavailable" msgid="645781226537551036">"Biyometrik donanım kullanılamıyor"</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>
@@ -521,7 +522,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Parmak hareketi çok yavaştı. Lütfen tekrar deneyin."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Tanınmadı"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"Tanınmadı"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Parmak izi kimlik doğrulaması yapıldı"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Parmak izi donanımı kullanılamıyor."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Parmak izi depolanamıyor. Lütfen mevcut parmak izlerinden birini kaldırın."</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 45b8dd4..6e6dd9a 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -520,6 +520,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Додаток зможе змінювати вашу колекцію фотографій."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"розпізнавати геодані з колекції медіа-вмісту"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Додаток зможе розпізнавати геодані з вашої колекції медіа-вмісту."</string>
+    <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"Біометричне апаратне забезпечення недоступне"</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,7 +528,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Ви провели пальцем надто повільно. Повторіть спробу."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Не розпізнано"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"Не розпізнано"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Відбиток автентифіковано"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Апаратне забезпечення для сканування відбитка недоступне."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Не вдалося зберегти відбиток. Видаліть наявний відбиток."</string>
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index fffad9b..2a2ca62 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -514,6 +514,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"ایپ کو آپ کی تصویر کے مجموعے میں ترمیم کی اجازت دیتا ہے۔"</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"اپنی میڈيا کے مجموعے سے مقامات پڑھیں"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"ایپ کو آپ کی میڈيا کے مجموعے سے مقامات پڑھنے کی اجازت دیتا ہے۔"</string>
+    <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"بایومیٹرک ہارڈ ویئر دستیاب نہیں ہے"</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,7 +522,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"انگلی کو بہت آہستہ ہٹایا گیا۔ براہ کرم دوبارہ کوشش کریں۔"</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"تسلیم شدہ نہیں ہے"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"تسلیم شدہ نہیں ہے"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"فنگر پرنٹ کی تصدیق ہو گئی"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"فنگر پرنٹ ہارڈ ویئر دستیاب نہیں ہے۔"</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"فنگر پرنٹ اسٹور نہیں کیا جا سکتا ہے۔ براہ کرم ایک موجودہ فنگر پرنٹ ہٹائیں۔"</string>
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index 684e78a..7ffc7e7 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -284,7 +284,7 @@
     <string name="permgrouprequest_sms" msgid="7168124215838204719">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uchun SMS xabarlarni yuborish va ko‘rishga ruxsat berilsinmi?"</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Xotira"</string>
     <string name="permgroupdesc_storage" msgid="637758554581589203">"qurilmangizdagi surat, multimedia va fayllarga kirish"</string>
-    <string name="permgrouprequest_storage" msgid="7885942926944299560">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uchun qurilmangizdagi surat, multimedia va fayllarga ruxsat berilsinmi?"</string>
+    <string name="permgrouprequest_storage" msgid="7885942926944299560">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ilovasiga qurilmangizdagi surat, multimedia va fayllarga kirish uchun ruxsat berilsinmi?"</string>
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Mikrofon"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"ovoz yozib olish"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uchun audio yozib olishga ruxsat berilsinmi?"</string>
@@ -514,6 +514,7 @@
     <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="biometric_error_hw_unavailable" msgid="645781226537551036">"Biometrik sensor ishlamayapti"</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>
@@ -521,7 +522,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Barmoq juda sekin harakatlandi. Qayta urinib ko‘ring."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Aniqlanmadi"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"Aniqlanmadi"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Barmoq izi tekshirildi"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Barmoq izi skaneri ish holatida emas."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Barmoq izini saqlab bo‘lmadi. Mavjud barmoq izlaridan birini o‘chirib tashlang."</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index b106ec5..a5f458b 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -514,6 +514,7 @@
     <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="biometric_error_hw_unavailable" msgid="645781226537551036">"Không có phần cứng sinh trắc học"</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>
@@ -521,7 +522,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Di chuyển ngón tay quá chậm. Vui lòng thử lại."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Không nhận dạng được"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"Không nhận dạng được"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Đã xác thực vân tay"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Phần cứng vân tay không khả dụng."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Không thể lưu vân tay. Vui lòng xóa vân tay hiện có."</string>
diff --git a/core/res/res/values-watch/config.xml b/core/res/res/values-watch/config.xml
index a96a96d..cd809b8 100644
--- a/core/res/res/values-watch/config.xml
+++ b/core/res/res/values-watch/config.xml
@@ -70,4 +70,7 @@
 
      <!-- Default Gravity setting for the system Toast view. Equivalent to: Gravity.CENTER -->
      <integer name="config_toastDefaultGravity">0x00000011</integer>
+
+    <!-- Default hyphenation frequency setting (0=NONE, 1=NORMAL, 2=FULL). -->
+    <item name="config_preferredHyphenationFrequency" format="integer" type="dimen">1</item>
 </resources>
diff --git a/core/res/res/values-watch/themes.xml b/core/res/res/values-watch/themes.xml
index 04df180..1be47ba 100644
--- a/core/res/res/values-watch/themes.xml
+++ b/core/res/res/values-watch/themes.xml
@@ -15,7 +15,7 @@
 -->
 <resources>
     <!-- Theme for the dialog shown when an app crashes or ANRs. Override to make it dark. -->
-    <style name="Theme.Dialog.AppError" parent="Theme.DeviceDefault.Dialog.Alert">
+    <style name="Theme.DeviceDefault.Dialog.AppError" parent="Theme.DeviceDefault.Dialog.Alert">
         <item name="windowContentTransitions">false</item>
         <item name="windowActivityTransitions">false</item>
         <item name="windowCloseOnTouchOutside">false</item>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 5aca3ff..966a5a5 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -272,9 +272,9 @@
     <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">"要允许“<xliff:g id="APP_NAME">%1$s</xliff:g>”获取此设备的位置信息吗?"</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="permgroupbackgroundrequest_location" msgid="8461841153030844390">"一律允许“<xliff:g id="APP_NAME">%1$s</xliff:g>”获取此设备的位置信息吗?"</string>
     <string name="permgroupbackgroundrequestdetail_location" msgid="1715668276378108654">"即使您并未使用该应用,该应用也将始终有权获取位置信息。"</string>
     <string name="permgrouplab_calendar" msgid="5863508437783683902">"日历"</string>
     <string name="permgroupdesc_calendar" msgid="3889615280211184106">"访问您的日历"</string>
@@ -296,7 +296,7 @@
     <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>
@@ -514,6 +514,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"允许该应用修改您的照片收藏。"</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"从您的媒体收藏中读取位置信息"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"允许该应用从您的媒体收藏中读取位置信息。"</string>
+    <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"生物识别硬件无法使用"</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,7 +522,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"手指移动太慢,请重试。"</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"无法识别"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"无法识别"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"已验证指纹"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"指纹硬件无法使用。"</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"无法存储指纹。请移除一个现有的指纹。"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 79c9cc4..87eb41f 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -514,6 +514,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"允許應用程式修改您的相片集。"</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"讀取媒體集的位置"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"允許應用程式讀取媒體集的位置。"</string>
+    <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"無法使用生物識別硬件"</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,7 +522,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"手指移動太慢,請重試。"</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"未能辨別"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"未能識別"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"驗證咗指紋"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"無法使用指紋軟件。"</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"指紋無法儲存。請移除現有指紋。"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 5143718..bd36ed6 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -514,6 +514,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"允許應用程式修改你的相片收藏。"</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"讀取你的媒體收藏的位置資訊"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"允許應用程式讀取你的媒體收藏的位置資訊。"</string>
+    <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"無法使用生物特徵辨識硬體"</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,7 +522,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"手指移動速度過慢,請再試一次。"</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"無法識別"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"無法辨識"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"指紋驗證成功"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"指紋硬體無法使用。"</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"無法儲存指紋,請先移除現有指紋。"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index fbe0dc7..fd6614ce 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -514,6 +514,7 @@
     <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="biometric_error_hw_unavailable" msgid="645781226537551036">"I-Biometric hardware ayitholakali"</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>
@@ -521,7 +522,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Umnwe uhanjiswe kancane kakhulu. Sicela uzame futhi."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Akubonwa"</string>
+    <string name="biometric_not_recognized" msgid="5770511773560736082">"Akwaziwa"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Isingxivizo somunwe sigunyaziwe"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Izingxenyekazi zekhompuyutha zezingxivizo zeminwe azitholakali."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Izigxivizo zeminwe azikwazi ukugcinwa. Sicela ususe izigxivizo zeminwe ezikhona."</string>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 64a9e6d..2de2b9e 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -3573,6 +3573,11 @@
              {@link android.accessibilityservice.AccessibilityService#setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)
              android.accessibilityservice.AccessibilityService.setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)}. -->
         <attr name="notificationTimeout" format="integer" />
+        <!-- The minimum timeout in milliseconds that UI controls need to remain on the screen.
+             This setting can be changed at runtime by calling
+             {@link android.accessibilityservice.AccessibilityService#setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)
+             android.accessibilityservice.AccessibilityService.setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)}. -->
+        <attr name="minimumUiTimeout" format="integer" />
         <!-- Additional flags as specified in
              {@link android.accessibilityservice.AccessibilityServiceInfo}.
              This setting can be changed at runtime by calling
@@ -4574,6 +4579,8 @@
         <attr name="letterSpacing" format="float" />
         <!-- Font feature settings. -->
         <attr name="fontFeatureSettings" format="string" />
+        <!-- Font variation settings. -->
+        <attr name="fontVariationSettings" format="string"/>
     </declare-styleable>
     <declare-styleable name="TextClock">
         <!-- Specifies the formatting pattern used to show the time and/or date
@@ -4922,6 +4929,8 @@
         <attr name="letterSpacing" />
         <!-- Font feature settings. -->
         <attr name="fontFeatureSettings" />
+        <!-- Font variation settings. -->
+        <attr name="fontVariationSettings" />
         <!-- Break strategy (control over paragraph layout). -->
         <attr name="breakStrategy">
             <!-- Line breaking uses simple strategy. -->
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index c8ad31f..293d90e 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -913,7 +913,7 @@
     <!--  Control whether to lock day/night mode change from normal application. When it is
           true, day / night mode change is only allowed to apps with MODIFY_DAY_NIGHT_MODE
           permission. -->
-    <bool name="config_lockDayNightMode">false</bool>
+    <bool name="config_lockDayNightMode">true</bool>
 
     <!-- Control the default night mode to use when there is no other mode override set.
          One of the following values (see UiModeManager.java):
@@ -2116,6 +2116,9 @@
     <!-- Type of the reach sensor. Empty if reach is not supported. -->
     <string name="config_dozeReachSensorType" translatable="false"></string>
 
+    <!-- Type of the wake up sensor. Empty if not supported. -->
+    <string name="config_dozeWakeScreenSensorType" 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. -->
@@ -2793,7 +2796,7 @@
         <item>SUPL_PORT=7275</item>
         <item>SUPL_VER=0x20000</item>
         <item>SUPL_MODE=1</item>
-        <item>SUPL_ES=0</item>
+        <item>SUPL_ES=1</item>
         <item>LPP_PROFILE=0</item>
         <item>USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL=1</item>
         <item>A_GLONASS_POS_PROTOCOL_SELECT=0</item>
@@ -3352,9 +3355,6 @@
          to occur. The expand button will have increased touch boundaries to accomodate this. -->
     <bool name="config_notificationHeaderClickableForExpand">false</bool>
 
-    <!-- Configuration for automotive -->
-    <bool name="enable_pbap_pce_profile">false</bool>
-
     <!-- Default data warning level in mb -->
     <integer name="default_data_warning_level_mb">2048</integer>
 
@@ -3510,6 +3510,9 @@
         <item>"wifi"</item>
     </string-array>
 
+    <!-- Default hyphenation frequency setting (0=NONE, 1=NORMAL, 2=FULL). -->
+    <item name="config_preferredHyphenationFrequency" format="integer" type="dimen">0</item>
+
     <!-- Package name for ManagedProvisioning which is responsible for provisioning work profiles. -->
     <string name="config_managed_provisioning_package" translatable="false">com.android.managedprovisioning</string>
 
diff --git a/core/res/res/values/ids.xml b/core/res/res/values/ids.xml
index bf7e068..8bca211 100644
--- a/core/res/res/values/ids.xml
+++ b/core/res/res/values/ids.xml
@@ -172,4 +172,7 @@
 
     <!-- Accessibility action identifier for {@link android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction#ACTION_HIDE_TOOLTIP}. -->
     <item type="id" name="accessibilityActionHideTooltip" />
+
+  <!-- Accessibility action to notify a window there is an outside touch. -->
+  <item type="id" name="accessibilityActionOutsideTouch" />
 </resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index fa31dce..c751af3 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2914,6 +2914,7 @@
     <public-group type="attr" first-id="0x0101058d">
         <!-- @hide For use by platform and tools only. Developers should not specify this value. -->
         <public name="usesNonSdkApi" />
+        <public name="minimumUiTimeout" />
     </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 e3b90526..365e4a4 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1414,8 +1414,8 @@
     <string-array name="fingerprint_acquired_vendor">
     </string-array>
 
-    <!-- Message shown by the fingerprint dialog when fingerprint is not recognized -->
-    <string name="fingerprint_not_recognized">Not recognized</string>
+    <!-- Message shown by the biometric dialog when biometric is not recognized -->
+    <string name="biometric_not_recognized">Not recognized</string>
     <!-- Accessibility message announced when a fingerprint has been authenticated [CHAR LIMIT=NONE] -->
     <string name="fingerprint_authenticated">Fingerprint authenticated</string>
 
@@ -2881,55 +2881,55 @@
     <!-- Title for EditText context menu [CHAR LIMIT=20] -->
     <string name="editTextMenuTitle">Text actions</string>
 
-    <!-- Label for item in the text selection menu to trigger an Email app [CHAR LIMIT=20] -->
+    <!-- Label for item in the text selection menu to trigger an Email app. Should be a verb. [CHAR LIMIT=20] -->
     <string name="email">Email</string>
 
     <!-- Accessibility description for an item in the text selection menu to trigger an Email app [CHAR LIMIT=NONE] -->
     <string name="email_desc">Email selected address</string>
 
-    <!-- Label for item in the text selection menu to trigger a Dialer app [CHAR LIMIT=20] -->
+    <!-- Label for item in the text selection menu to trigger a Dialer app. Should be a verb. [CHAR LIMIT=20] -->
     <string name="dial">Call</string>
 
     <!-- Accessibility description for an item in the text selection menu to call a phone number [CHAR LIMIT=NONE] -->
     <string name="dial_desc">Call selected phone number</string>
 
-    <!-- Label for item in the text selection menu to trigger a Map app [CHAR LIMIT=20] -->
+    <!-- Label for item in the text selection menu to trigger a Map app. Should be a verb. [CHAR LIMIT=20] -->
     <string name="map">Map</string>
 
     <!-- Accessibility description for an item in the text selection menu to open maps for an address [CHAR LIMIT=NONE] -->
     <string name="map_desc">Locate selected address</string>
 
-    <!-- Label for item in the text selection menu to trigger a Browser app [CHAR LIMIT=20] -->
+    <!-- Label for item in the text selection menu to trigger a Browser app. Should be a verb. [CHAR LIMIT=20] -->
     <string name="browse">Open</string>
 
     <!-- Accessibility description for an item in the text selection menu to open a URL in a browser [CHAR LIMIT=NONE] -->
     <string name="browse_desc">Open selected URL</string>
 
-    <!-- Label for item in the text selection menu to trigger an SMS app [CHAR LIMIT=20] -->
+    <!-- Label for item in the text selection menu to trigger an SMS app. Should be a verb. [CHAR LIMIT=20] -->
     <string name="sms">Message</string>
 
     <!-- Accessibility description for an item in the text selection menu to send an SMS to a phone number [CHAR LIMIT=NONE] -->
     <string name="sms_desc">Message selected phone number</string>
 
-    <!-- Label for item in the text selection menu to trigger adding a contact [CHAR LIMIT=20] -->
+    <!-- Label for item in the text selection menu to trigger adding a contact. Should be a verb. [CHAR LIMIT=20] -->
     <string name="add_contact">Add</string>
 
     <!-- Accessibility description for an item in the text selection menu to add the selected detail to contacts [CHAR LIMIT=NONE] -->
     <string name="add_contact_desc">Add to contacts</string>
 
-    <!-- Label for item in the text selection menu to view the calendar for the selected time/date [CHAR LIMIT=20] -->
+    <!-- Label for item in the text selection menu to view the calendar for the selected time/date. Should be a verb. [CHAR LIMIT=20] -->
     <string name="view_calendar">View</string>
 
     <!-- Accessibility description for an item in the text selection menu to view the calendar for a date [CHAR LIMIT=NONE]-->
     <string name="view_calendar_desc">View selected time in calendar</string>
 
-    <!-- Label for item in the text selection menu to create a calendar event at the selected time/date [CHAR LIMIT=20] -->
+    <!-- Label for item in the text selection menu to create a calendar event at the selected time/date. Should be a verb. [CHAR LIMIT=20] -->
     <string name="add_calendar_event">Schedule</string>
 
     <!-- Accessibility description for an item in the text selection menu to schedule an event for a date [CHAR LIMIT=NONE] -->
     <string name="add_calendar_event_desc">Schedule event for selected time</string>
 
-    <!-- Label for item in the text selection menu to track a selected flight number [CHAR LIMIT=20] -->
+    <!-- Label for item in the text selection menu to track a selected flight number. Should be a verb. [CHAR LIMIT=20] -->
     <string name="view_flight">Track</string>
 
     <!-- Accessibility description for an item in the text selection menu to track a flight [CHAR LIMIT=NONE] -->
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index fafcf93..ef286e2 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">none</item>
+        <item name="hyphenationFrequency">@dimen/config_preferredHyphenationFrequency</item>
     </style>
 
     <style name="Widget.CheckedTextView">
         <item name="textAlignment">viewStart</item>
         <item name="breakStrategy">high_quality</item>
-        <item name="hyphenationFrequency">none</item>
+        <item name="hyphenationFrequency">@dimen/config_preferredHyphenationFrequency</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">none</item>
+        <item name="hyphenationFrequency">@dimen/config_preferredHyphenationFrequency</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
index 339f9c7..e6e0de3 100644
--- a/core/res/res/values/styles_permission_controller.xml
+++ b/core/res/res/values/styles_permission_controller.xml
@@ -15,8 +15,8 @@
   limitations under the License.
   -->
 
-<!-- styles for the permission grant dialog. -->
 <resources>
+    <!-- styles for the permission grant dialog. -->
     <style name="PermissionGrantDialog">
         <item name="background">?attr/windowBackground</item>
         <item name="elevation">?attr/windowElevation</item>
@@ -95,4 +95,37 @@
         <item name="layout_marginEnd">16dp</item>
         <item name="layout_marginBottom">4dp</item>
     </style>
+
+    <!-- styles for the permission review screen. -->
+    <style name="PermissionReviewDescription">
+        <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="PermissionReviewTitleIcon">
+        <item name="layout_marginTop">4dp</item>
+        <item name="layout_width">36dp</item>
+        <item name="layout_height">36dp</item>
+        <item name="scaleType">fitCenter</item>
+    </style>
+
+    <style name="PermissionReviewTitleMessage"
+           parent="@style/TextAppearance.DeviceDefault">
+        <item name="paddingStart">22dp</item>
+        <item name="textSize">20sp</item>
+        <item name="textColor">?attr/textColorPrimary</item>
+    </style>
+
+    <style name="PermissionReviewSettings">
+        <item name="layout_marginStart">8dp</item>
+        <item name="layout_marginEnd">8dp</item>
+    </style>
+
+    <style name="PermissionReviewButtonBar">
+        <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 b82f9e5..7b6e064 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -218,6 +218,7 @@
   <java-symbol type="id" name="selection_end_handle" />
   <java-symbol type="id" name="insertion_handle" />
   <java-symbol type="id" name="accessibilityActionClickOnClickableSpan" />
+  <java-symbol type="id" name="accessibilityActionOutsideTouch" />
   <java-symbol type="id" name="camera" />
   <java-symbol type="id" name="mic" />
   <java-symbol type="id" name="overlay" />
@@ -2099,7 +2100,7 @@
   <java-symbol type="string" name="vpn_lockdown_error" />
   <java-symbol type="string" name="vpn_lockdown_config" />
   <java-symbol type="string" name="wallpaper_binding_label" />
-  <java-symbol type="style" name="Theme.Dialog.AppError" />
+  <java-symbol type="style" name="Theme.DeviceDefault.Dialog.AppError" />
   <java-symbol type="style" name="Theme.Leanback.Dialog.Alert" />
   <java-symbol type="style" name="Theme.Toast" />
   <java-symbol type="xml" name="storage_list" />
@@ -2394,6 +2395,7 @@
 
   <!-- Biometric messages -->
   <java-symbol type="string" name="biometric_error_hw_unavailable" />
+  <java-symbol type="string" name="biometric_not_recognized" />
 
   <!-- Fingerprint messages -->
   <java-symbol type="string" name="fingerprint_error_unable_to_process" />
@@ -2412,7 +2414,6 @@
   <java-symbol type="string" name="fingerprint_error_lockout" />
   <java-symbol type="string" name="fingerprint_error_lockout_permanent" />
   <java-symbol type="string" name="fingerprint_name_template" />
-  <java-symbol type="string" name="fingerprint_not_recognized" />
   <java-symbol type="string" name="fingerprint_authenticated" />
   <java-symbol type="string" name="fingerprint_error_no_fingerprints" />
   <java-symbol type="string" name="fingerprint_error_hw_not_present" />
@@ -3259,8 +3260,6 @@
 
   <java-symbol type="style" name="Theme.DeviceDefault.QuickSettings" />
 
-  <java-symbol type="bool" name="enable_pbap_pce_profile" />
-
   <java-symbol type="integer" name="default_data_warning_level_mb" />
   <java-symbol type="bool" name="config_useVideoPauseWorkaround" />
   <java-symbol type="bool" name="config_sendPackageName" />
@@ -3464,4 +3463,5 @@
 
   <java-symbol type="integer" name="db_wal_truncate_size" />
   <java-symbol type="integer" name="config_wakeUpDelayDoze" />
+  <java-symbol type="string" name="config_dozeWakeScreenSensorType" />
 </resources>
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index 3937af5..a7530ce 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -869,13 +869,6 @@
     <!-- System themes -->
     <eat-comment />
 
-    <!-- Theme for the dialog shown when an app crashes or ANRs. -->
-    <style name="Theme.Dialog.AppError" parent="Theme.DeviceDefault.Light.Dialog.Alert">
-        <item name="windowContentTransitions">false</item>
-        <item name="windowActivityTransitions">false</item>
-        <item name="windowCloseOnTouchOutside">false</item>
-    </style>
-
     <!-- Special theme for the recent apps dialog, to allow customization
          with overlays. -->
     <style name="Theme.Dialog.RecentApplications" parent="Theme.DeviceDefault.Light.Dialog">
diff --git a/core/res/res/values/themes_device_defaults.xml b/core/res/res/values/themes_device_defaults.xml
index 14e5082..92096ab 100644
--- a/core/res/res/values/themes_device_defaults.xml
+++ b/core/res/res/values/themes_device_defaults.xml
@@ -719,6 +719,13 @@
         <item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
     </style>
 
+    <!-- Theme for the dialog shown when an app crashes or ANRs. -->
+    <style name="Theme.DeviceDefault.Dialog.AppError" parent="Theme.DeviceDefault.Light.Dialog.Alert">
+        <item name="windowContentTransitions">false</item>
+        <item name="windowActivityTransitions">false</item>
+        <item name="windowCloseOnTouchOutside">false</item>
+    </style>
+
     <style name="Theme.DeviceDefault.SearchBar" parent="Theme.Material.SearchBar">
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_dark</item>
diff --git a/core/res/res/values/themes_permission_controller.xml b/core/res/res/values/themes_permission_controller.xml
index 3bc93cd..369cee3 100644
--- a/core/res/res/values/themes_permission_controller.xml
+++ b/core/res/res/values/themes_permission_controller.xml
@@ -15,8 +15,8 @@
   limitations under the License.
   -->
 
-<!-- themes for the permission grant dialog. -->
 <resources>
+    <!-- themes for the permission grant dialog. -->
     <style name="Theme.DeviceDefault.PermissionGrantApp"
            parent="@style/Theme.DeviceDefault.Light.Panel">
         <item name="windowIsFloating">false</item>
@@ -32,4 +32,13 @@
         <item name="checkboxStyle">@style/PermissionGrantCheckbox</item>
         <item name="buttonBarStyle">@style/PermissionGrantButtonBar</item>
     </style>
+
+    <!-- themes for the permission review dialog. -->
+    <style name="Theme.DeviceDefault.PermissionReviewApp"
+           parent="@style/Theme.DeviceDefault.Settings">
+        <item name="windowActionBar">false</item>
+        <item name="windowNoTitle">true</item>
+        <item name="titleTextStyle">@style/PermissionReviewTitleMessage</item>
+        <item name="buttonBarStyle">@style/PermissionReviewButtonBar</item>
+    </style>
 </resources>
diff --git a/core/tests/coretests/src/android/content/pm/AndroidHidlUpdaterTest.java b/core/tests/coretests/src/android/content/pm/AndroidHidlUpdaterTest.java
new file mode 100644
index 0000000..7218b3a2
--- /dev/null
+++ b/core/tests/coretests/src/android/content/pm/AndroidHidlUpdaterTest.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.content.pm;
+
+import static android.content.pm.PackageBuilder.builder;
+import static android.content.pm.SharedLibraryNames.ANDROID_HIDL_BASE;
+import static android.content.pm.SharedLibraryNames.ANDROID_HIDL_MANAGER;
+
+import android.os.Build;
+import android.support.test.filters.SmallTest;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Test for {@link AndroidHidlUpdater}
+ */
+@SmallTest
+@RunWith(JUnit4.class)
+public class AndroidHidlUpdaterTest extends PackageSharedLibraryUpdaterTest {
+
+    private static final String OTHER_LIBRARY = "other.library";
+
+    @Test
+    public void targeted_at_O() {
+        PackageBuilder before = builder()
+                .targetSdkVersion(Build.VERSION_CODES.O);
+
+        // Should add both HIDL libraries
+        PackageBuilder after = builder()
+                .targetSdkVersion(Build.VERSION_CODES.O)
+                .requiredLibraries(ANDROID_HIDL_MANAGER, ANDROID_HIDL_BASE);
+
+        checkBackwardsCompatibility(before, after);
+    }
+
+    @Test
+    public void targeted_at_O_not_empty_usesLibraries() {
+        PackageBuilder before = builder()
+                .targetSdkVersion(Build.VERSION_CODES.O)
+                .requiredLibraries(OTHER_LIBRARY);
+
+        // The hidl jars should be added at the start of the list because it
+        // is not on the bootclasspath and the package targets pre-P.
+        PackageBuilder after = builder()
+                .targetSdkVersion(Build.VERSION_CODES.O)
+                .requiredLibraries(ANDROID_HIDL_MANAGER, ANDROID_HIDL_BASE, OTHER_LIBRARY);
+
+        checkBackwardsCompatibility(before, after);
+    }
+
+    @Test
+    public void targeted_at_O_in_usesLibraries() {
+        PackageBuilder before = builder()
+                .targetSdkVersion(Build.VERSION_CODES.O)
+                .requiredLibraries(ANDROID_HIDL_MANAGER, ANDROID_HIDL_BASE);
+
+        // No change is required because although the HIDL libraries has been removed from
+        // the bootclasspath the package explicitly requests it.
+        checkBackwardsCompatibility(before, before);
+    }
+
+    @Test
+    public void in_usesLibraries() {
+        PackageBuilder before = builder().requiredLibraries(ANDROID_HIDL_BASE);
+
+        // No change is required because the package explicitly requests the HIDL libraries
+        // and is targeted at the current version so does not need backwards compatibility.
+        checkBackwardsCompatibility(before, before);
+    }
+
+    @Test
+    public void in_usesOptionalLibraries() {
+        PackageBuilder before = builder().optionalLibraries(ANDROID_HIDL_BASE);
+
+        // No change is required because the package explicitly requests the HIDL libraries
+        // and is targeted at the current version so does not need backwards compatibility.
+        checkBackwardsCompatibility(before, before);
+    }
+
+    private void checkBackwardsCompatibility(PackageBuilder before, PackageBuilder after) {
+        checkBackwardsCompatibility(before, after, AndroidHidlUpdater::new);
+    }
+}
diff --git a/core/tests/coretests/src/android/graphics/TypefaceSystemFallbackTest.java b/core/tests/coretests/src/android/graphics/TypefaceSystemFallbackTest.java
index dd34f1f..3ce2589 100644
--- a/core/tests/coretests/src/android/graphics/TypefaceSystemFallbackTest.java
+++ b/core/tests/coretests/src/android/graphics/TypefaceSystemFallbackTest.java
@@ -23,6 +23,7 @@
 
 import android.content.Context;
 import android.content.res.AssetManager;
+import android.graphics.fonts.Font;
 import android.graphics.fonts.FontFamily;
 import android.graphics.fonts.SystemFonts;
 import android.support.test.InstrumentationRegistry;
@@ -43,6 +44,7 @@
 import java.nio.charset.Charset;
 import java.nio.file.Files;
 import java.nio.file.StandardCopyOption;
+import java.util.ArrayList;
 import java.util.Locale;
 
 @SmallTest
@@ -110,13 +112,14 @@
 
     private static void buildSystemFallback(String xml,
             ArrayMap<String, Typeface> fontMap, ArrayMap<String, FontFamily[]> fallbackMap) {
+        final ArrayList<Font> availableFonts = new ArrayList<>();
         try (FileOutputStream fos = new FileOutputStream(TEST_FONTS_XML)) {
             fos.write(xml.getBytes(Charset.forName("UTF-8")));
         } catch (IOException e) {
             throw new RuntimeException(e);
         }
         final FontConfig.Alias[] aliases = SystemFonts.buildSystemFallback(TEST_FONTS_XML,
-                TEST_FONT_DIR, fallbackMap);
+                TEST_FONT_DIR, fallbackMap, availableFonts);
         Typeface.initSystemDefaultTypefaces(fontMap, fallbackMap, aliases);
     }
 
@@ -124,9 +127,10 @@
     public void testBuildSystemFallback() {
         final ArrayMap<String, Typeface> fontMap = new ArrayMap<>();
         final ArrayMap<String, FontFamily[]> fallbackMap = new ArrayMap<>();
+        final ArrayList<Font> availableFonts = new ArrayList<>();
 
         final FontConfig.Alias[] aliases = SystemFonts.buildSystemFallback(SYSTEM_FONTS_XML,
-                SYSTEM_FONT_DIR, fallbackMap);
+                SYSTEM_FONT_DIR, fallbackMap, availableFonts);
 
         assertNotNull(aliases);
         assertFalse(fallbackMap.isEmpty());
@@ -487,7 +491,7 @@
                 + "  <family lang='de'>"
                 + "    <font weight='400' style='normal'>a3em.ttf</font>"
                 + "  </family>"
-                + "  <family lang='it fr'>"
+                + "  <family lang='it,fr'>"
                 + "    <font weight='400' style='normal'>b3em.ttf</font>"
                 + "  </family>"
                 + "</familyset>";
diff --git a/core/tests/coretests/src/android/hardware/display/BrightnessConfigurationTest.java b/core/tests/coretests/src/android/hardware/display/BrightnessConfigurationTest.java
index 5ef30a8..dcc51e1 100644
--- a/core/tests/coretests/src/android/hardware/display/BrightnessConfigurationTest.java
+++ b/core/tests/coretests/src/android/hardware/display/BrightnessConfigurationTest.java
@@ -48,8 +48,8 @@
 
     @Test
     public void testSetCurveIsUnmodified() {
-        BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder();
-        builder.setCurve(LUX_LEVELS, NITS_LEVELS);
+        BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder(
+                LUX_LEVELS, NITS_LEVELS);
         BrightnessConfiguration config = builder.build();
         Pair<float[], float[]> curve = config.getCurve();
         assertArrayEquals(LUX_LEVELS, curve.first, "lux");
@@ -58,45 +58,33 @@
 
     @Test(expected = IllegalArgumentException.class)
     public void testCurveMustHaveZeroLuxPoint() {
-        BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder();
         float[] lux = Arrays.copyOf(LUX_LEVELS, LUX_LEVELS.length);
         lux[0] = 1f;
-        builder.setCurve(lux, NITS_LEVELS);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void testCurveMustBeSet() {
-        BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder();
-        builder.build();
+        new BrightnessConfiguration.Builder(lux, NITS_LEVELS);
     }
 
     @Test(expected = NullPointerException.class)
     public void testCurveMustNotHaveNullArrays() {
-        BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder();
-        builder.setCurve(null, null);
+        new BrightnessConfiguration.Builder(null, null);
     }
 
     @Test(expected = IllegalArgumentException.class)
     public void testCurveMustNotHaveEmptyArrays() {
-        BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder();
-        builder.setCurve(new float[0], new float[0]);
+        new BrightnessConfiguration.Builder(new float[0], new float[0]);
     }
 
     @Test
     public void testCurveMustNotHaveArraysOfDifferentLengths() {
         assertThrows(IllegalArgumentException.class, () -> {
-            BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder();
             float[] lux = Arrays.copyOf(LUX_LEVELS, LUX_LEVELS.length + 1);
             lux[lux.length - 1] = lux[lux.length - 2] + 1;
-            boolean exceptionThrown = false;
-            builder.setCurve(lux, NITS_LEVELS);
+            new BrightnessConfiguration.Builder(lux, NITS_LEVELS);
         });
 
         assertThrows(IllegalArgumentException.class, () -> {
-            BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder();
             float[] nits = Arrays.copyOf(NITS_LEVELS, NITS_LEVELS.length + 1);
             nits[nits.length - 1] = nits[nits.length - 2] + 1;
-            builder.setCurve(LUX_LEVELS, nits);
+            new BrightnessConfiguration.Builder(LUX_LEVELS, nits);
         });
     }
 
@@ -105,23 +93,21 @@
         assertThrows(IllegalArgumentException.class, () -> {
             float[] lux = Arrays.copyOf(LUX_LEVELS, LUX_LEVELS.length);
             lux[lux.length - 1] = Float.NaN;
-            BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder();
-            builder.setCurve(lux, NITS_LEVELS);
+            new BrightnessConfiguration.Builder(lux, NITS_LEVELS);
         });
 
         assertThrows(IllegalArgumentException.class, () -> {
             float[] nits = Arrays.copyOf(NITS_LEVELS, NITS_LEVELS.length);
             nits[nits.length - 1] = Float.NaN;
-            BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder();
-            builder.setCurve(LUX_LEVELS, nits);
+            new BrightnessConfiguration.Builder(LUX_LEVELS, nits);
         });
     }
 
 
     @Test
     public void testParceledConfigIsEquivalent() {
-        BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder();
-        builder.setCurve(LUX_LEVELS, NITS_LEVELS);
+        BrightnessConfiguration.Builder builder =
+                new BrightnessConfiguration.Builder(LUX_LEVELS, NITS_LEVELS);
         BrightnessConfiguration config = builder.build();
         Parcel p = Parcel.obtain();
         p.writeParcelable(config, 0 /*flags*/);
@@ -133,12 +119,11 @@
 
     @Test
     public void testEquals() {
-        BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder();
-        builder.setCurve(LUX_LEVELS, NITS_LEVELS);
+        BrightnessConfiguration.Builder builder =
+                new BrightnessConfiguration.Builder(LUX_LEVELS, NITS_LEVELS);
         BrightnessConfiguration baseConfig = builder.build();
 
-        builder = new BrightnessConfiguration.Builder();
-        builder.setCurve(LUX_LEVELS, NITS_LEVELS);
+        builder = new BrightnessConfiguration.Builder(LUX_LEVELS, NITS_LEVELS);
         BrightnessConfiguration identicalConfig = builder.build();
         assertEquals(baseConfig, identicalConfig);
         assertEquals("hashCodes must be equal for identical configs",
@@ -146,15 +131,13 @@
 
         float[] lux = Arrays.copyOf(LUX_LEVELS, LUX_LEVELS.length);
         lux[lux.length - 1] = lux[lux.length - 1] * 2;
-        builder = new BrightnessConfiguration.Builder();
-        builder.setCurve(lux, NITS_LEVELS);
+        builder = new BrightnessConfiguration.Builder(lux, NITS_LEVELS);
         BrightnessConfiguration luxDifferConfig = builder.build();
         assertNotEquals(baseConfig, luxDifferConfig);
 
         float[] nits = Arrays.copyOf(NITS_LEVELS, NITS_LEVELS.length);
         nits[nits.length - 1] = nits[nits.length - 1] * 2;
-        builder = new BrightnessConfiguration.Builder();
-        builder.setCurve(LUX_LEVELS, nits);
+        builder = new BrightnessConfiguration.Builder(LUX_LEVELS, nits);
         BrightnessConfiguration nitsDifferConfig = builder.build();
         assertNotEquals(baseConfig, nitsDifferConfig);
     }
diff --git a/core/tests/coretests/src/android/os/FileUtilsTest.java b/core/tests/coretests/src/android/os/FileUtilsTest.java
index 9c9f11b..20fe162 100644
--- a/core/tests/coretests/src/android/os/FileUtilsTest.java
+++ b/core/tests/coretests/src/android/os/FileUtilsTest.java
@@ -17,6 +17,22 @@
 package android.os;
 
 import static android.os.FileUtils.roundStorageSize;
+import static android.os.FileUtils.translateModePfdToPosix;
+import static android.os.FileUtils.translateModePosixToPfd;
+import static android.os.FileUtils.translateModePosixToString;
+import static android.os.FileUtils.translateModeStringToPosix;
+import static android.os.ParcelFileDescriptor.MODE_APPEND;
+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 android.os.ParcelFileDescriptor.MODE_WRITE_ONLY;
+import static android.system.OsConstants.O_APPEND;
+import static android.system.OsConstants.O_CREAT;
+import static android.system.OsConstants.O_RDONLY;
+import static android.system.OsConstants.O_RDWR;
+import static android.system.OsConstants.O_TRUNC;
+import static android.system.OsConstants.O_WRONLY;
 import static android.text.format.DateUtils.DAY_IN_MILLIS;
 import static android.text.format.DateUtils.HOUR_IN_MILLIS;
 import static android.text.format.DateUtils.WEEK_IN_MILLIS;
@@ -476,6 +492,32 @@
         assertEquals(G64, roundStorageSize(G32 + 1));
     }
 
+    @Test
+    public void testTranslateMode() throws Exception {
+        assertTranslate("r", O_RDONLY, MODE_READ_ONLY);
+
+        assertTranslate("rw", O_RDWR | O_CREAT,
+                MODE_READ_WRITE | MODE_CREATE);
+        assertTranslate("rwt", O_RDWR | O_CREAT | O_TRUNC,
+                MODE_READ_WRITE | MODE_CREATE | MODE_TRUNCATE);
+        assertTranslate("rwa", O_RDWR | O_CREAT | O_APPEND,
+                MODE_READ_WRITE | MODE_CREATE | MODE_APPEND);
+
+        assertTranslate("w", O_WRONLY | O_CREAT,
+                MODE_WRITE_ONLY | MODE_CREATE | MODE_CREATE);
+        assertTranslate("wt", O_WRONLY | O_CREAT | O_TRUNC,
+                MODE_WRITE_ONLY | MODE_CREATE | MODE_TRUNCATE);
+        assertTranslate("wa", O_WRONLY | O_CREAT | O_APPEND,
+                MODE_WRITE_ONLY | MODE_CREATE | MODE_APPEND);
+    }
+
+    private static void assertTranslate(String string, int posix, int pfd) {
+        assertEquals(posix, translateModeStringToPosix(string));
+        assertEquals(string, translateModePosixToString(posix));
+        assertEquals(pfd, translateModePosixToPfd(posix));
+        assertEquals(posix, translateModePfdToPosix(pfd));
+    }
+
     private static void assertNameEquals(String expected, File actual) {
         assertEquals(expected, actual.getName());
     }
diff --git a/core/tests/coretests/src/android/os/SetPersistentVrThreadTest.java b/core/tests/coretests/src/android/os/SetPersistentVrThreadTest.java
index 920988b..9e44554 100644
--- a/core/tests/coretests/src/android/os/SetPersistentVrThreadTest.java
+++ b/core/tests/coretests/src/android/os/SetPersistentVrThreadTest.java
@@ -24,7 +24,6 @@
 import android.provider.Settings;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.suitebuilder.annotation.SmallTest;
-import android.util.Log;
 
 /**
  * Tests ActivityManager#setPersistentVrThread and ActivityManager#setVrThread's
@@ -76,9 +75,11 @@
     }
 
     private void setPersistentVrModeEnabled(boolean enable) throws Throwable {
-        mVrManager.setPersistentVrModeEnabled(enable);
-        // Allow the system time to send out callbacks for persistent VR mode.
-        Thread.sleep(200);
+        if (mVrManager != null) {
+            mVrManager.setPersistentVrModeEnabled(enable);
+            // Allow the system time to send out callbacks for persistent VR mode.
+            Thread.sleep(200);
+        }
     }
 
     @SmallTest
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 189a4aa..e84aed1 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -192,6 +192,7 @@
                     Settings.Global.DEFAULT_DNS_SERVER,
                     Settings.Global.DEFAULT_INSTALL_LOCATION,
                     Settings.Global.DEFAULT_RESTRICT_BACKGROUND_DATA,
+                    Settings.Global.DEFAULT_USER_ID_TO_BOOT_INTO,
                     Settings.Global.DESK_DOCK_SOUND,
                     Settings.Global.DESK_UNDOCK_SOUND,
                     Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT,
@@ -273,6 +274,7 @@
                     Settings.Global.KEEP_PROFILE_IN_BACKGROUND,
                     Settings.Global.LANG_ID_UPDATE_CONTENT_URL,
                     Settings.Global.LANG_ID_UPDATE_METADATA_URL,
+                    Settings.Global.LAST_ACTIVE_USER_ID,
                     Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS,
                     Settings.Global.LOCATION_BACKGROUND_THROTTLE_PROXIMITY_ALERT_INTERVAL_MS,
                     Settings.Global.LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST,
@@ -280,6 +282,7 @@
                     Settings.Global.LOCATION_GLOBAL_KILL_SWITCH,
                     Settings.Global.LOCATION_SETTINGS_LINK_TO_PERMISSIONS_ENABLED,
                     Settings.Global.LOCK_SOUND,
+                    Settings.Global.LOOPER_STATS,
                     Settings.Global.LOW_BATTERY_SOUND,
                     Settings.Global.LOW_BATTERY_SOUND_TIMEOUT,
                     Settings.Global.LOW_POWER_MODE,
diff --git a/core/tests/coretests/src/android/text/FontFallbackSetup.java b/core/tests/coretests/src/android/text/FontFallbackSetup.java
index 6c34043..898e78c 100644
--- a/core/tests/coretests/src/android/text/FontFallbackSetup.java
+++ b/core/tests/coretests/src/android/text/FontFallbackSetup.java
@@ -20,6 +20,7 @@
 import android.content.Context;
 import android.content.res.AssetManager;
 import android.graphics.Typeface;
+import android.graphics.fonts.Font;
 import android.graphics.fonts.FontFamily;
 import android.graphics.fonts.SystemFonts;
 import android.support.test.InstrumentationRegistry;
@@ -32,6 +33,7 @@
 import java.nio.charset.Charset;
 import java.nio.file.Files;
 import java.nio.file.StandardCopyOption;
+import java.util.ArrayList;
 
 public class FontFallbackSetup implements AutoCloseable {
     private final String[] mTestFontFiles;
@@ -74,8 +76,9 @@
         }
 
         final ArrayMap<String, FontFamily[]> fallbackMap = new ArrayMap<>();
+        final ArrayList<Font> availableFonts = new ArrayList<>();
         final FontConfig.Alias[] aliases = SystemFonts.buildSystemFallback(testFontsXml,
-                mTestFontsDir, fallbackMap);
+                mTestFontsDir, fallbackMap, availableFonts);
         Typeface.initSystemDefaultTypefaces(mFontMap, fallbackMap, aliases);
     }
 
diff --git a/core/tests/coretests/src/android/view/accessibility/AccessibilityEventTest.java b/core/tests/coretests/src/android/view/accessibility/AccessibilityEventTest.java
index 3c04895..3e03414 100644
--- a/core/tests/coretests/src/android/view/accessibility/AccessibilityEventTest.java
+++ b/core/tests/coretests/src/android/view/accessibility/AccessibilityEventTest.java
@@ -40,7 +40,7 @@
     // and assertAccessibilityEventCleared
 
     /** The number of properties of the {@link AccessibilityEvent} class. */
-    private static final int A11Y_EVENT_NON_STATIC_FIELD_COUNT = 32;
+    private static final int A11Y_EVENT_NON_STATIC_FIELD_COUNT = 33;
 
     // The number of fields tested in the corresponding CTS AccessibilityRecordTest:
     // assertAccessibilityRecordCleared, fullyPopulateAccessibilityRecord,
diff --git a/core/tests/coretests/src/android/view/accessibility/AccessibilityNodeInfoTest.java b/core/tests/coretests/src/android/view/accessibility/AccessibilityNodeInfoTest.java
index 7fa6ce4..922b79a 100644
--- a/core/tests/coretests/src/android/view/accessibility/AccessibilityNodeInfoTest.java
+++ b/core/tests/coretests/src/android/view/accessibility/AccessibilityNodeInfoTest.java
@@ -57,7 +57,7 @@
 
     // The number of flags held in boolean properties. Their values should also be double-checked
     // in the methods above.
-    private static final int NUM_BOOLEAN_PROPERTIES = 22;
+    private static final int NUM_BOOLEAN_PROPERTIES = 17;
 
     @Test
     public void testStandardActions_serializationFlagIsValid() {
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 ace6b2d..364dcfd 100644
--- a/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java
@@ -18,10 +18,7 @@
 
 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;
@@ -34,7 +31,6 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-
 import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.util.ArrayList;
@@ -50,6 +46,7 @@
     private static final int TEST_UID = 1;
     private static final int REQUEST_SIZE = 2;
     private static final int REPLY_SIZE = 3;
+    private final CachedDeviceState mDeviceState = new CachedDeviceState(false, true);
 
     @Test
     public void testDetailedOff() {
@@ -388,43 +385,27 @@
     }
 
     @Test
-    public void testDataResetWhenInitialStateSet() {
+    public void testNoDataCollectedBeforeInitialDeviceStateSet() {
         TestBinderCallsStats bcs = new TestBinderCallsStats();
+        bcs.setDeviceState(null);
         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);
+        bcs.setDeviceState(mDeviceState.getReadonlyClient());
 
         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);
+        mDeviceState.setCharging(true);
+
         Binder binder = new Binder();
         CallSession callSession = bcs.callStarted(binder, 1);
         bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
@@ -436,7 +417,7 @@
     public void testScreenOff() {
         TestBinderCallsStats bcs = new TestBinderCallsStats();
         bcs.setDetailedTracking(true);
-        bcs.getBroadcastReceiver().onReceive(null, new Intent(Intent.ACTION_SCREEN_OFF));
+        mDeviceState.setScreenInteractive(false);
         Binder binder = new Binder();
         CallSession callSession = bcs.callStarted(binder, 1);
         bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
@@ -453,7 +434,7 @@
     public void testScreenOn() {
         TestBinderCallsStats bcs = new TestBinderCallsStats();
         bcs.setDetailedTracking(true);
-        bcs.getBroadcastReceiver().onReceive(null, new Intent(Intent.ACTION_SCREEN_ON));
+        mDeviceState.setScreenInteractive(true);
         Binder binder = new Binder();
         CallSession callSession = bcs.callStarted(binder, 1);
         bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
@@ -470,9 +451,8 @@
     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);
+        mDeviceState.setCharging(true);
+
         Binder binder = new Binder();
         CallSession callSession = bcs.callStarted(binder, 1);
         bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
@@ -484,9 +464,8 @@
     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);
+        mDeviceState.setCharging(false);
+
         Binder binder = new Binder();
         CallSession callSession = bcs.callStarted(binder, 1);
         bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
@@ -522,7 +501,6 @@
     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);
@@ -561,7 +539,7 @@
         assertEquals(0, bcs.getExceptionCounts().size());
     }
 
-    static class TestBinderCallsStats extends BinderCallsStats {
+    class TestBinderCallsStats extends BinderCallsStats {
         int callingUid = TEST_UID;
         long time = 1234;
         long elapsedTime = 0;
@@ -580,6 +558,7 @@
                 }
             });
             setSamplingInterval(1);
+            setDeviceState(mDeviceState.getReadonlyClient());
         }
 
         @Override
diff --git a/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java b/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java
new file mode 100644
index 0000000..0eb3d06
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java
@@ -0,0 +1,402 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.os;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Comparator;
+import java.util.List;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+@Presubmit
+public final class LooperStatsTest {
+    private HandlerThread mThreadFirst;
+    private HandlerThread mThreadSecond;
+    private Handler mHandlerFirst;
+    private Handler mHandlerSecond;
+    private Handler mHandlerAnonymous;
+    private CachedDeviceState mDeviceState;
+
+    @Before
+    public void setUp() {
+        // The tests are all single-threaded. HandlerThreads are created to allow creating Handlers
+        // and to test Thread name collection.
+        mThreadFirst = new HandlerThread("TestThread1");
+        mThreadSecond = new HandlerThread("TestThread2");
+        mThreadFirst.start();
+        mThreadSecond.start();
+
+        mHandlerFirst = new TestHandlerFirst(mThreadFirst.getLooper());
+        mHandlerSecond = new TestHandlerSecond(mThreadSecond.getLooper());
+        mHandlerAnonymous = new Handler(mThreadFirst.getLooper()) {
+            /* To create an anonymous subclass. */
+        };
+        mDeviceState = new CachedDeviceState();
+        mDeviceState.setCharging(false);
+        mDeviceState.setScreenInteractive(true);
+    }
+
+    @After
+    public void tearDown() {
+        mThreadFirst.quit();
+        mThreadSecond.quit();
+    }
+
+    @Test
+    public void testSingleMessageDispatched() {
+        TestableLooperStats looperStats = new TestableLooperStats(1, 100);
+
+        Object token = looperStats.messageDispatchStarting();
+        looperStats.tickRealtime(100);
+        looperStats.tickThreadTime(10);
+        looperStats.messageDispatched(token, mHandlerFirst.obtainMessage(1000));
+
+        List<LooperStats.ExportedEntry> entries = looperStats.getEntries();
+        assertThat(entries).hasSize(1);
+        LooperStats.ExportedEntry entry = entries.get(0);
+        assertThat(entry.threadName).isEqualTo("TestThread1");
+        assertThat(entry.handlerClassName).isEqualTo(
+                "com.android.internal.os.LooperStatsTest$TestHandlerFirst");
+        assertThat(entry.messageName).isEqualTo("0x3e8" /* 1000 in hex */);
+        assertThat(entry.isInteractive).isEqualTo(true);
+        assertThat(entry.messageCount).isEqualTo(1);
+        assertThat(entry.recordedMessageCount).isEqualTo(1);
+        assertThat(entry.exceptionCount).isEqualTo(0);
+        assertThat(entry.totalLatencyMicros).isEqualTo(100);
+        assertThat(entry.maxLatencyMicros).isEqualTo(100);
+        assertThat(entry.cpuUsageMicros).isEqualTo(10);
+        assertThat(entry.maxCpuUsageMicros).isEqualTo(10);
+    }
+
+    @Test
+    public void testThrewException() {
+        TestableLooperStats looperStats = new TestableLooperStats(1, 100);
+
+        Object token = looperStats.messageDispatchStarting();
+        looperStats.tickRealtime(100);
+        looperStats.tickThreadTime(10);
+        looperStats.dispatchingThrewException(token, mHandlerFirst.obtainMessage(7),
+                new ArithmeticException());
+
+        List<LooperStats.ExportedEntry> entries = looperStats.getEntries();
+        assertThat(entries).hasSize(1);
+        LooperStats.ExportedEntry entry = entries.get(0);
+        assertThat(entry.threadName).isEqualTo("TestThread1");
+        assertThat(entry.handlerClassName).isEqualTo(
+                "com.android.internal.os.LooperStatsTest$TestHandlerFirst");
+        assertThat(entry.messageName).isEqualTo("0x7"  /* 7 in hex */);
+        assertThat(entry.isInteractive).isEqualTo(true);
+        assertThat(entry.messageCount).isEqualTo(0);
+        assertThat(entry.recordedMessageCount).isEqualTo(0);
+        assertThat(entry.exceptionCount).isEqualTo(1);
+        assertThat(entry.totalLatencyMicros).isEqualTo(0);
+        assertThat(entry.maxLatencyMicros).isEqualTo(0);
+        assertThat(entry.cpuUsageMicros).isEqualTo(0);
+        assertThat(entry.maxCpuUsageMicros).isEqualTo(0);
+    }
+
+    @Test
+    public void testMultipleMessagesDispatched() {
+        TestableLooperStats looperStats = new TestableLooperStats(2, 100);
+
+        // Contributes to entry2.
+        Object token1 = looperStats.messageDispatchStarting();
+        looperStats.tickRealtime(100);
+        looperStats.tickThreadTime(10);
+        looperStats.messageDispatched(token1, mHandlerFirst.obtainMessage(1000));
+
+        // Contributes to entry2.
+        Object token2 = looperStats.messageDispatchStarting();
+        looperStats.tickRealtime(50);
+        looperStats.tickThreadTime(20);
+        looperStats.messageDispatched(token2, mHandlerFirst.obtainMessage(1000));
+
+        // Contributes to entry3.
+        Object token3 = looperStats.messageDispatchStarting();
+        looperStats.tickRealtime(10);
+        looperStats.tickThreadTime(10);
+        looperStats.messageDispatched(token3, mHandlerSecond.obtainMessage().setCallback(() -> {
+        }));
+
+        // Contributes to entry1.
+        Object token4 = looperStats.messageDispatchStarting();
+        looperStats.tickRealtime(100);
+        looperStats.tickThreadTime(100);
+        looperStats.messageDispatched(token4, mHandlerAnonymous.obtainMessage(1));
+
+        List<LooperStats.ExportedEntry> entries = looperStats.getEntries();
+        assertThat(entries).hasSize(3);
+        entries.sort(Comparator.comparing(e -> e.handlerClassName));
+
+        // Captures data for token4 call.
+        LooperStats.ExportedEntry entry1 = entries.get(0);
+        assertThat(entry1.threadName).isEqualTo("TestThread1");
+        assertThat(entry1.handlerClassName).isEqualTo("com.android.internal.os.LooperStatsTest$1");
+        assertThat(entry1.messageName).isEqualTo("0x1" /* 1 in hex */);
+        assertThat(entry1.messageCount).isEqualTo(1);
+        assertThat(entry1.recordedMessageCount).isEqualTo(0);
+        assertThat(entry1.exceptionCount).isEqualTo(0);
+        assertThat(entry1.totalLatencyMicros).isEqualTo(0);
+        assertThat(entry1.maxLatencyMicros).isEqualTo(0);
+        assertThat(entry1.cpuUsageMicros).isEqualTo(0);
+        assertThat(entry1.maxCpuUsageMicros).isEqualTo(0);
+
+        // Captures data for token1 and token2 calls.
+        LooperStats.ExportedEntry entry2 = entries.get(1);
+        assertThat(entry2.threadName).isEqualTo("TestThread1");
+        assertThat(entry2.handlerClassName).isEqualTo(
+                "com.android.internal.os.LooperStatsTest$TestHandlerFirst");
+        assertThat(entry2.messageName).isEqualTo("0x3e8" /* 1000 in hex */);
+        assertThat(entry2.messageCount).isEqualTo(2);
+        assertThat(entry2.recordedMessageCount).isEqualTo(1);
+        assertThat(entry2.exceptionCount).isEqualTo(0);
+        assertThat(entry2.totalLatencyMicros).isEqualTo(100);
+        assertThat(entry2.maxLatencyMicros).isEqualTo(100);
+        assertThat(entry2.cpuUsageMicros).isEqualTo(10);
+        assertThat(entry2.maxCpuUsageMicros).isEqualTo(10);
+
+        // Captures data for token3 call.
+        LooperStats.ExportedEntry entry3 = entries.get(2);
+        assertThat(entry3.threadName).isEqualTo("TestThread2");
+        assertThat(entry3.handlerClassName).isEqualTo(
+                "com.android.internal.os.LooperStatsTest$TestHandlerSecond");
+        assertThat(entry3.messageName).startsWith(
+                "com.android.internal.os.-$$Lambda$LooperStatsTest$");
+        assertThat(entry3.messageCount).isEqualTo(1);
+        assertThat(entry3.recordedMessageCount).isEqualTo(1);
+        assertThat(entry3.exceptionCount).isEqualTo(0);
+        assertThat(entry3.totalLatencyMicros).isEqualTo(10);
+        assertThat(entry3.maxLatencyMicros).isEqualTo(10);
+        assertThat(entry3.cpuUsageMicros).isEqualTo(10);
+        assertThat(entry3.maxCpuUsageMicros).isEqualTo(10);
+    }
+
+    @Test
+    public void testDataNotCollectedBeforeDeviceStateSet() {
+        TestableLooperStats looperStats = new TestableLooperStats(1, 100);
+        looperStats.setDeviceState(null);
+
+        Object token1 = looperStats.messageDispatchStarting();
+        looperStats.messageDispatched(token1, mHandlerFirst.obtainMessage(1000));
+        Object token2 = looperStats.messageDispatchStarting();
+        looperStats.dispatchingThrewException(token2, mHandlerFirst.obtainMessage(1000),
+                new IllegalArgumentException());
+
+        List<LooperStats.ExportedEntry> entries = looperStats.getEntries();
+        assertThat(entries).hasSize(0);
+    }
+
+    @Test
+    public void testDataNotCollectedOnCharger() {
+        TestableLooperStats looperStats = new TestableLooperStats(1, 100);
+        mDeviceState.setCharging(true);
+
+        Object token1 = looperStats.messageDispatchStarting();
+        looperStats.messageDispatched(token1, mHandlerFirst.obtainMessage(1000));
+        Object token2 = looperStats.messageDispatchStarting();
+        looperStats.dispatchingThrewException(token2, mHandlerFirst.obtainMessage(1000),
+                new IllegalArgumentException());
+
+        List<LooperStats.ExportedEntry> entries = looperStats.getEntries();
+        assertThat(entries).hasSize(0);
+    }
+
+    @Test
+    public void testScreenStateCollected() {
+        TestableLooperStats looperStats = new TestableLooperStats(1, 100);
+
+        mDeviceState.setScreenInteractive(true);
+        Object token1 = looperStats.messageDispatchStarting();
+        looperStats.messageDispatched(token1, mHandlerFirst.obtainMessage(1000));
+        Object token2 = looperStats.messageDispatchStarting();
+        looperStats.dispatchingThrewException(token2, mHandlerFirst.obtainMessage(1000),
+                new IllegalArgumentException());
+
+        Object token3 = looperStats.messageDispatchStarting();
+        // If screen state changed during the call, we take the final state into account.
+        mDeviceState.setScreenInteractive(false);
+        looperStats.messageDispatched(token3, mHandlerFirst.obtainMessage(1000));
+        Object token4 = looperStats.messageDispatchStarting();
+        looperStats.dispatchingThrewException(token4, mHandlerFirst.obtainMessage(1000),
+                new IllegalArgumentException());
+
+        List<LooperStats.ExportedEntry> entries = looperStats.getEntries();
+        assertThat(entries).hasSize(2);
+        entries.sort(Comparator.comparing(e -> e.isInteractive));
+
+        LooperStats.ExportedEntry entry1 = entries.get(0);
+        assertThat(entry1.isInteractive).isEqualTo(false);
+        assertThat(entry1.messageCount).isEqualTo(1);
+        assertThat(entry1.exceptionCount).isEqualTo(1);
+
+        LooperStats.ExportedEntry entry2 = entries.get(1);
+        assertThat(entry2.isInteractive).isEqualTo(true);
+        assertThat(entry2.messageCount).isEqualTo(1);
+        assertThat(entry2.exceptionCount).isEqualTo(1);
+    }
+
+    @Test
+    public void testMessagesOverSizeCap() {
+        TestableLooperStats looperStats = new TestableLooperStats(2, 1 /* sizeCap */);
+
+        Object token1 = looperStats.messageDispatchStarting();
+        looperStats.tickRealtime(100);
+        looperStats.tickThreadTime(10);
+        looperStats.messageDispatched(token1, mHandlerFirst.obtainMessage(1000));
+
+        Object token2 = looperStats.messageDispatchStarting();
+        looperStats.tickRealtime(50);
+        looperStats.tickThreadTime(20);
+        looperStats.messageDispatched(token2, mHandlerFirst.obtainMessage(1001));
+
+        Object token3 = looperStats.messageDispatchStarting();
+        looperStats.tickRealtime(10);
+        looperStats.tickThreadTime(10);
+        looperStats.messageDispatched(token3, mHandlerFirst.obtainMessage(1002));
+
+        Object token4 = looperStats.messageDispatchStarting();
+        looperStats.tickRealtime(10);
+        looperStats.tickThreadTime(10);
+        looperStats.messageDispatched(token4, mHandlerSecond.obtainMessage(1003));
+
+        List<LooperStats.ExportedEntry> entries = looperStats.getEntries();
+        assertThat(entries).hasSize(2);
+        entries.sort(Comparator.comparing(e -> e.handlerClassName));
+
+        LooperStats.ExportedEntry entry1 = entries.get(0);
+        assertThat(entry1.threadName).isEqualTo("");
+        assertThat(entry1.handlerClassName).isEqualTo("");
+        assertThat(entry1.messageName).isEqualTo("OVERFLOW");
+        assertThat(entry1.messageCount).isEqualTo(3);
+        assertThat(entry1.recordedMessageCount).isEqualTo(1);
+        assertThat(entry1.exceptionCount).isEqualTo(0);
+        assertThat(entry1.totalLatencyMicros).isEqualTo(10);
+        assertThat(entry1.maxLatencyMicros).isEqualTo(10);
+        assertThat(entry1.cpuUsageMicros).isEqualTo(10);
+        assertThat(entry1.maxCpuUsageMicros).isEqualTo(10);
+
+        LooperStats.ExportedEntry entry2 = entries.get(1);
+        assertThat(entry2.threadName).isEqualTo("TestThread1");
+        assertThat(entry2.handlerClassName).isEqualTo(
+                "com.android.internal.os.LooperStatsTest$TestHandlerFirst");
+    }
+
+    @Test
+    public void testInvalidTokensCauseException() {
+        TestableLooperStats looperStats = new TestableLooperStats(1, 100);
+        assertThrows(ClassCastException.class,
+                () -> looperStats.dispatchingThrewException(new Object(),
+                        mHandlerFirst.obtainMessage(),
+                        new ArithmeticException()));
+        assertThrows(ClassCastException.class,
+                () -> looperStats.messageDispatched(new Object(), mHandlerFirst.obtainMessage()));
+        assertThrows(ClassCastException.class,
+                () -> looperStats.messageDispatched(123, mHandlerFirst.obtainMessage()));
+        assertThrows(ClassCastException.class,
+                () -> looperStats.messageDispatched(mHandlerFirst.obtainMessage(),
+                        mHandlerFirst.obtainMessage()));
+
+        assertThat(looperStats.getEntries()).hasSize(0);
+    }
+
+    @Test
+    public void testTracksMultipleHandlerInstancesIfSameClass() {
+        TestableLooperStats looperStats = new TestableLooperStats(1, 100);
+        Handler handlerFirstAnother = new TestHandlerFirst(mHandlerFirst.getLooper());
+
+        Object token1 = looperStats.messageDispatchStarting();
+        looperStats.messageDispatched(token1, mHandlerFirst.obtainMessage(1000));
+
+        Object token2 = looperStats.messageDispatchStarting();
+        looperStats.messageDispatched(token2, handlerFirstAnother.obtainMessage(1000));
+
+        assertThat(looperStats.getEntries()).hasSize(1);
+        assertThat(looperStats.getEntries().get(0).messageCount).isEqualTo(2);
+    }
+
+    private static void assertThrows(Class<? extends Exception> exceptionClass, Runnable r) {
+        try {
+            r.run();
+            Assert.fail("Expected " + exceptionClass + " to be thrown.");
+        } catch (Exception exception) {
+            assertThat(exception).isInstanceOf(exceptionClass);
+        }
+    }
+
+    private final class TestableLooperStats extends LooperStats {
+        private static final long INITIAL_MICROS = 10001000123L;
+        private int mCount;
+        private long mRealtimeMicros;
+        private long mThreadTimeMicros;
+        private int mSamplingInterval;
+
+        TestableLooperStats(int samplingInterval, int sizeCap) {
+            super(samplingInterval, sizeCap);
+            this.mSamplingInterval = samplingInterval;
+            this.setDeviceState(mDeviceState.getReadonlyClient());
+        }
+
+        void tickRealtime(long micros) {
+            mRealtimeMicros += micros;
+        }
+
+        void tickThreadTime(long micros) {
+            mThreadTimeMicros += micros;
+        }
+
+        @Override
+        protected long getElapsedRealtimeMicro() {
+            return INITIAL_MICROS + mRealtimeMicros;
+        }
+
+        @Override
+        protected long getThreadTimeMicro() {
+            return INITIAL_MICROS + mThreadTimeMicros;
+        }
+
+        @Override
+        protected boolean shouldCollectDetailedData() {
+            return mCount++ % mSamplingInterval == 0;
+        }
+    }
+
+    private static final class TestHandlerFirst extends Handler {
+        TestHandlerFirst(Looper looper) {
+            super(looper);
+        }
+    }
+
+    private static final class TestHandlerSecond extends Handler {
+        TestHandlerSecond(Looper looper) {
+            super(looper);
+        }
+    }
+}
diff --git a/core/tests/webkit/Android.mk b/core/tests/webkit/Android.mk
deleted file mode 100644
index 45f6957..0000000
--- a/core/tests/webkit/Android.mk
+++ /dev/null
@@ -1,45 +0,0 @@
-# Copyright (C) 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-# We only want this apk build for tests.
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-
-# Include all test java files.
-LOCAL_SRC_FILES := \
-	$(call all-java-files-under, unit_tests_src)
-
-LOCAL_JAVA_LIBRARIES := android.test.runner
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
-	android-support-test
-
-LOCAL_PACKAGE_NAME := WebViewLoadingTests
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_CERTIFICATE := platform
-
-LOCAL_COMPATIBILITY_SUITE := device-tests
-
-LOCAL_REQUIRED_MODULES := \
-	WebViewLoadingOnDiskTestApk \
-	WebViewLoadingFromApkTestApk
-
-include $(BUILD_PACKAGE)
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/core/tests/webkit/OWNERS b/core/tests/webkit/OWNERS
deleted file mode 100644
index 00e540a..0000000
--- a/core/tests/webkit/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-changwan@google.com
-tobiasjs@google.com
-torne@google.com
diff --git a/core/tests/webkit/apk_with_native_libs/Android.mk b/core/tests/webkit/apk_with_native_libs/Android.mk
deleted file mode 100644
index e18a7e0..0000000
--- a/core/tests/webkit/apk_with_native_libs/Android.mk
+++ /dev/null
@@ -1,71 +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)
-MY_PATH := $(LOCAL_PATH)
-
-# Set shared variables
-MY_MODULE_TAGS := optional
-MY_JNI_SHARED_LIBRARIES := libwebviewtest_jni
-MY_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-MY_SRC_FILES := $(call all-java-files-under, src)
-MY_CFLAGS := -Wall -Werror
-MY_SDK_VERSION := system_current
-MY_PROGUARD_ENABLED := disabled
-MY_MULTILIB := both
-
-# Recurse down the file tree.
-include $(call all-subdir-makefiles)
-
-
-
-# Builds an apk containing native libraries that will be unzipped on the device.
-include $(CLEAR_VARS)
-
-LOCAL_PATH := $(MY_PATH)
-LOCAL_PACKAGE_NAME := WebViewLoadingOnDiskTestApk
-LOCAL_MANIFEST_FILE := ondisk/AndroidManifest.xml
-
-LOCAL_MODULE_TAGS := $(MY_MODULE_TAGS)
-LOCAL_JNI_SHARED_LIBRARIES := $(MY_JNI_SHARED_LIBRARIES)
-LOCAL_MODULE_PATH := $(MY_MODULE_PATH)
-LOCAL_SRC_FILES := $(MY_SRC_FILES)
-LOCAL_CFLAGS := $(MY_CFLAGS)
-LOCAL_SDK_VERSION := $(MY_SDK_VERSION)
-LOCAL_PROGUARD_ENABLED := $(MY_PROGUARD_ENABLED)
-LOCAL_MULTILIB := $(MY_MULTILIB)
-LOCAL_COMPATIBILITY_SUITE := device-tests
-
-include $(BUILD_PACKAGE)
-
-
-# Builds an apk containing uncompressed native libraries that have to be
-# accessed through the APK itself on the device.
-include $(CLEAR_VARS)
-
-LOCAL_PATH := $(MY_PATH)
-LOCAL_PACKAGE_NAME := WebViewLoadingFromApkTestApk
-LOCAL_MANIFEST_FILE := inapk/AndroidManifest.xml
-
-LOCAL_MODULE_TAGS := $(MY_MODULE_TAGS)
-LOCAL_JNI_SHARED_LIBRARIES := $(MY_JNI_SHARED_LIBRARIES)
-LOCAL_MODULE_PATH := $(MY_MODULE_PATH)
-LOCAL_SRC_FILES := $(MY_SRC_FILES)
-LOCAL_CFLAGS := $(MY_CFLAGS)
-LOCAL_SDK_VERSION := $(MY_SDK_VERSION)
-LOCAL_PROGUARD_ENABLED := $(MY_PROGUARD_ENABLED)
-LOCAL_MULTILIB := $(MY_MULTILIB)
-LOCAL_COMPATIBILITY_SUITE := device-tests
-
-include $(BUILD_PACKAGE)
diff --git a/core/tests/webkit/apk_with_native_libs/inapk/AndroidManifest.xml b/core/tests/webkit/apk_with_native_libs/inapk/AndroidManifest.xml
deleted file mode 100644
index 868b238..0000000
--- a/core/tests/webkit/apk_with_native_libs/inapk/AndroidManifest.xml
+++ /dev/null
@@ -1,29 +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.
- -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.android.webviewloading_test_from_apk"
-    android:versionCode="1"
-    android:versionName="0.0.0.1">
-
-    <application android:label="WebView Loading Test APK"
-      android:multiArch="true"
-      android:extractNativeLibs="false">
-        <meta-data android:name="com.android.webview.WebViewLibrary"
-            android:value="libwebviewtest_jni.so" />
-    </application>
-</manifest>
diff --git a/core/tests/webkit/apk_with_native_libs/jni/Android.mk b/core/tests/webkit/apk_with_native_libs/jni/Android.mk
deleted file mode 100644
index fd5b5eb..0000000
--- a/core/tests/webkit/apk_with_native_libs/jni/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 := libwebviewtest_jni
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := WebViewTestJniOnLoad.cpp
-
-LOCAL_C_INCLUDES := $(JNI_H_INCLUDE)
-
-LOCAL_SDK_VERSION := current
-
-LOCAL_MULTILIB := both
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/core/tests/webkit/apk_with_native_libs/ondisk/AndroidManifest.xml b/core/tests/webkit/apk_with_native_libs/ondisk/AndroidManifest.xml
deleted file mode 100644
index ffffeb8..0000000
--- a/core/tests/webkit/apk_with_native_libs/ondisk/AndroidManifest.xml
+++ /dev/null
@@ -1,28 +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.
- -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.android.webviewloading_test_on_disk"
-    android:versionCode="1"
-    android:versionName="0.0.0.1">
-
-    <application android:label="WebView Loading Test APK"
-      android:multiArch="true">
-        <meta-data android:name="com.android.webview.WebViewLibrary"
-            android:value="libwebviewtest_jni.so" />
-    </application>
-</manifest>
diff --git a/core/tests/webkit/apk_with_native_libs/src/com/google/android/xts/webview_list/WebViewLoadingTestClass.java b/core/tests/webkit/apk_with_native_libs/src/com/google/android/xts/webview_list/WebViewLoadingTestClass.java
deleted file mode 100644
index 0efa4b4..0000000
--- a/core/tests/webkit/apk_with_native_libs/src/com/google/android/xts/webview_list/WebViewLoadingTestClass.java
+++ /dev/null
@@ -1,24 +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.webview.chromium;
-
-/**
- * An empty class for testing purposes.
- */
-public class WebViewLoadingTestClass {
-}
diff --git a/core/tests/webkit/unit_tests_src/com/android/webkit/WebViewLibraryLoaderTest.java b/core/tests/webkit/unit_tests_src/com/android/webkit/WebViewLibraryLoaderTest.java
deleted file mode 100644
index e2f2d37..0000000
--- a/core/tests/webkit/unit_tests_src/com/android/webkit/WebViewLibraryLoaderTest.java
+++ /dev/null
@@ -1,329 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.webkit;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
-import android.os.Build;
-import android.os.Bundle;
-import android.util.Log;
-
-import android.support.test.filters.MediumTest;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-import android.support.test.InstrumentationRegistry;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipFile;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/**
- * Unit tests for {@link WebViewLibraryLoader}.
- * Use the following command to run these tests:
- * make WebViewLoadingTests \
- * && adb install -r -d \
- * ${ANDROID_PRODUCT_OUT}/data/app/WebViewLoadingTests/WebViewLoadingTests.apk \
- * && adb shell am instrument -e class 'android.webkit.WebViewLibraryLoaderTest' -w \
- * 'com.android.webkit.tests/android.support.test.runner.AndroidJUnitRunner'
- */
-@RunWith(AndroidJUnit4.class)
-public final class WebViewLibraryLoaderTest {
-    private static final String WEBVIEW_LIBS_ON_DISK_TEST_APK =
-            "com.android.webviewloading_test_on_disk";
-    private static final String WEBVIEW_LIBS_IN_APK_TEST_APK =
-            "com.android.webviewloading_test_from_apk";
-    private static final String WEBVIEW_LOADING_TEST_NATIVE_LIB = "libwebviewtest_jni.so";
-
-    private PackageInfo webviewOnDiskPackageInfo;
-    private PackageInfo webviewFromApkPackageInfo;
-
-    @Before public void setUp() throws PackageManager.NameNotFoundException {
-        PackageManager pm = InstrumentationRegistry.getContext().getPackageManager();
-        webviewOnDiskPackageInfo =
-                pm.getPackageInfo(WEBVIEW_LIBS_ON_DISK_TEST_APK, PackageManager.GET_META_DATA);
-        webviewFromApkPackageInfo =
-                pm.getPackageInfo(WEBVIEW_LIBS_IN_APK_TEST_APK, PackageManager.GET_META_DATA);
-    }
-
-    private static boolean is64BitDevice() {
-        return Build.SUPPORTED_64_BIT_ABIS.length > 0;
-    }
-
-    // We test the getWebViewNativeLibraryDirectory method here because it handled several different
-    // cases/combinations and it seems unnecessary to create one test-apk for each such combination
-    // and arch.
-
-    /**
-     * Ensure we fetch the correct native library directories in the multi-arch case where
-     * the primary ABI is 64-bit.
-     */
-    @SmallTest
-    @Test public void testGetWebViewLibDirMultiArchPrimary64bit() {
-        final String nativeLib = "nativeLib";
-        final String secondaryNativeLib = "secondaryNativeLib";
-        PackageInfo packageInfo = new PackageInfo();
-        ApplicationInfo ai = new ApplicationInfoBuilder().
-                // See VMRuntime.ABI_TO_INSTRUCTION_SET_MAP
-                setPrimaryCpuAbi("arm64-v8a").
-                setNativeLibraryDir(nativeLib).
-                setSecondaryCpuAbi("armeabi").
-                setSecondaryNativeLibraryDir(secondaryNativeLib).
-                create();
-        packageInfo.applicationInfo = ai;
-        String actual32Lib =
-                WebViewLibraryLoader.getWebViewNativeLibraryDirectory(ai, false /* is64bit */);
-        String actual64Lib =
-                WebViewLibraryLoader.getWebViewNativeLibraryDirectory(ai, true /* is64bit */);
-        assertEquals(nativeLib, actual64Lib);
-        assertEquals(secondaryNativeLib, actual32Lib);
-    }
-
-    /**
-     * Ensure we fetch the correct native library directory in the 64-bit single-arch case.
-     */
-    @SmallTest
-    @Test public void testGetWebViewLibDirSingleArch64bit() {
-        final String nativeLib = "nativeLib";
-        PackageInfo packageInfo = new PackageInfo();
-        ApplicationInfo ai = new ApplicationInfoBuilder().
-                // See VMRuntime.ABI_TO_INSTRUCTION_SET_MAP
-                setPrimaryCpuAbi("arm64-v8a").
-                setNativeLibraryDir(nativeLib).
-                create();
-        packageInfo.applicationInfo = ai;
-        String actual64Lib =
-                WebViewLibraryLoader.getWebViewNativeLibraryDirectory(ai, true /* is64bit */);
-        assertEquals(nativeLib, actual64Lib);
-    }
-
-    /**
-     * Ensure we fetch the correct native library directory in the 32-bit single-arch case.
-     */
-    @SmallTest
-    @Test public void testGetWebViewLibDirSingleArch32bit() {
-        final String nativeLib = "nativeLib";
-        PackageInfo packageInfo = new PackageInfo();
-        ApplicationInfo ai = new ApplicationInfoBuilder().
-                // See VMRuntime.ABI_TO_INSTRUCTION_SET_MAP
-                setPrimaryCpuAbi("armeabi-v7a").
-                setNativeLibraryDir(nativeLib).
-                create();
-        packageInfo.applicationInfo = ai;
-        String actual32Lib =
-                WebViewLibraryLoader.getWebViewNativeLibraryDirectory(ai, false /* is64bit */);
-        assertEquals(nativeLib, actual32Lib);
-    }
-
-    /**
-     * Ensure we fetch the correct 32-bit library path from an APK with 32-bit and 64-bit
-     * libraries unzipped onto disk.
-     */
-    @MediumTest
-    @Test public void testGetWebViewLibraryPathOnDisk32Bit()
-            throws WebViewFactory.MissingWebViewPackageException {
-        WebViewLibraryLoader.WebViewNativeLibrary actualNativeLib =
-                WebViewLibraryLoader.getWebViewNativeLibrary(
-                        webviewOnDiskPackageInfo, false /* is64bit */);
-        String expectedLibaryDirectory = is64BitDevice() ?
-                webviewOnDiskPackageInfo.applicationInfo.secondaryNativeLibraryDir :
-                webviewOnDiskPackageInfo.applicationInfo.nativeLibraryDir;
-        String lib32Path = expectedLibaryDirectory + "/" + WEBVIEW_LOADING_TEST_NATIVE_LIB;
-        assertEquals("Fetched incorrect 32-bit path from WebView library.",
-                lib32Path, actualNativeLib.path);
-    }
-
-    /**
-     * Ensure we fetch the correct 64-bit library path from an APK with 32-bit and 64-bit
-     * libraries unzipped onto disk.
-     */
-    @MediumTest
-    @Test public void testGetWebViewLibraryPathOnDisk64Bit()
-            throws WebViewFactory.MissingWebViewPackageException {
-        // A 32-bit device will not unpack 64-bit libraries.
-        if (!is64BitDevice()) return;
-
-        WebViewLibraryLoader.WebViewNativeLibrary actualNativeLib =
-                WebViewLibraryLoader.getWebViewNativeLibrary(
-                        webviewOnDiskPackageInfo, true /* is64bit */);
-        String lib64Path = webviewOnDiskPackageInfo.applicationInfo.nativeLibraryDir
-                + "/" + WEBVIEW_LOADING_TEST_NATIVE_LIB;
-        assertEquals("Fetched incorrect 64-bit path from WebView library.",
-                lib64Path, actualNativeLib.path);
-    }
-
-    /**
-     * Check the size of the 32-bit library fetched from an APK with both 32-bit and 64-bit
-     * libraries unzipped onto disk.
-     */
-    @MediumTest
-    @Test public void testGetWebView32BitLibrarySizeOnDiskIsNonZero()
-            throws WebViewFactory.MissingWebViewPackageException {
-        WebViewLibraryLoader.WebViewNativeLibrary actual32BitNativeLib =
-                WebViewLibraryLoader.getWebViewNativeLibrary(
-                        webviewOnDiskPackageInfo, false /* is64bit */);
-        assertTrue(actual32BitNativeLib.size > 0);
-    }
-
-    /**
-     * Check the size of the 64-bit library fetched from an APK with both 32-bit and 64-bit
-     * libraries unzipped onto disk.
-     */
-    @MediumTest
-    @Test public void testGetWebView64BitLibrarySizeOnDiskIsNonZero()
-            throws WebViewFactory.MissingWebViewPackageException {
-        // A 32-bit device will not unpack 64-bit libraries.
-        if (!is64BitDevice()) return;
-        WebViewLibraryLoader.WebViewNativeLibrary actual64BitNativeLib =
-                WebViewLibraryLoader.getWebViewNativeLibrary(
-                        webviewOnDiskPackageInfo, true /* is64bit */);
-        assertTrue(actual64BitNativeLib.size > 0);
-    }
-
-    /**
-     * Ensure we fetch the correct 32-bit library path from an APK with both 32-bit and 64-bit
-     * libraries stored uncompressed in the APK.
-     */
-    @MediumTest
-    @Test public void testGetWebView32BitLibraryPathFromApk()
-            throws WebViewFactory.MissingWebViewPackageException, IOException {
-        WebViewLibraryLoader.WebViewNativeLibrary actualNativeLib =
-                WebViewLibraryLoader.getWebViewNativeLibrary(
-                        webviewFromApkPackageInfo, false /* is64bit */);
-        // The device might have ignored the app's request to not extract native libs, so first
-        // check whether the library paths match those of extracted libraries.
-        String expectedLibaryDirectory = is64BitDevice() ?
-                webviewFromApkPackageInfo.applicationInfo.secondaryNativeLibraryDir :
-                webviewFromApkPackageInfo.applicationInfo.nativeLibraryDir;
-        String lib32Path = expectedLibaryDirectory + "/" + WEBVIEW_LOADING_TEST_NATIVE_LIB;
-        if (lib32Path.equals(actualNativeLib.path)) {
-            // If the libraries were extracted to disk, ensure that they're actually there.
-            assertTrue("The given WebView library doesn't exist.",
-                    new File(actualNativeLib.path).exists());
-        } else { // The libraries were not extracted to disk.
-            assertIsValidZipEntryPath(actualNativeLib.path,
-                    webviewFromApkPackageInfo.applicationInfo.sourceDir);
-        }
-    }
-
-    /**
-     * Ensure we fetch the correct 32-bit library path from an APK with both 32-bit and 64-bit
-     * libraries stored uncompressed in the APK.
-     */
-    @MediumTest
-    @Test public void testGetWebView64BitLibraryPathFromApk()
-            throws WebViewFactory.MissingWebViewPackageException, IOException {
-        // A 32-bit device will not unpack 64-bit libraries.
-        if (!is64BitDevice()) return;
-
-        WebViewLibraryLoader.WebViewNativeLibrary actualNativeLib =
-                WebViewLibraryLoader.getWebViewNativeLibrary(
-                        webviewFromApkPackageInfo, true /* is64bit */);
-        assertIsValidZipEntryPath(actualNativeLib.path,
-                webviewFromApkPackageInfo.applicationInfo.sourceDir);
-    }
-
-    private static void assertIsValidZipEntryPath(String path, String zipFilePath)
-            throws IOException {
-        assertTrue("The path to a zip entry must start with the path to the zip file itself."
-            + "Expected zip path: " + zipFilePath + ", actual zip entry: " + path,
-            path.startsWith(zipFilePath + "!/"));
-        String[] pathSplit = path.split("!/");
-        assertEquals("A zip file path should have two parts, the zip path, and the zip entry path.",
-                2, pathSplit.length);
-        ZipFile zipFile = new ZipFile(pathSplit[0]);
-        assertNotNull("Path doesn't point to a valid zip entry: " + path,
-                zipFile.getEntry(pathSplit[1]));
-    }
-
-
-    /**
-     * Check the size of the 32-bit library fetched from an APK with both 32-bit and 64-bit
-     * libraries stored uncompressed in the APK.
-     */
-    @MediumTest
-    @Test public void testGetWebView32BitLibrarySizeFromApkIsNonZero()
-            throws WebViewFactory.MissingWebViewPackageException {
-        WebViewLibraryLoader.WebViewNativeLibrary actual32BitNativeLib =
-                WebViewLibraryLoader.getWebViewNativeLibrary(
-                        webviewFromApkPackageInfo, false /* is64bit */);
-        assertTrue(actual32BitNativeLib.size > 0);
-    }
-
-    /**
-     * Check the size of the 64-bit library fetched from an APK with both 32-bit and 64-bit
-     * libraries stored uncompressed in the APK.
-     */
-    @MediumTest
-    @Test public void testGetWebView64BitLibrarySizeFromApkIsNonZero()
-            throws WebViewFactory.MissingWebViewPackageException {
-        // A 32-bit device will not unpack 64-bit libraries.
-        if (!is64BitDevice()) return;
-
-        WebViewLibraryLoader.WebViewNativeLibrary actual64BitNativeLib =
-                WebViewLibraryLoader.getWebViewNativeLibrary(
-                        webviewFromApkPackageInfo, true /* is64bit */);
-        assertTrue(actual64BitNativeLib.size > 0);
-    }
-
-    private static class ApplicationInfoBuilder {
-        ApplicationInfo ai;
-
-        public ApplicationInfoBuilder setPrimaryCpuAbi(String primaryCpuAbi) {
-            ai.primaryCpuAbi = primaryCpuAbi;
-            return this;
-        }
-
-        public ApplicationInfoBuilder setSecondaryCpuAbi(String secondaryCpuAbi) {
-            ai.secondaryCpuAbi = secondaryCpuAbi;
-            return this;
-        }
-
-        public ApplicationInfoBuilder setNativeLibraryDir(String nativeLibraryDir) {
-            ai.nativeLibraryDir = nativeLibraryDir;
-            return this;
-        }
-
-        public ApplicationInfoBuilder setSecondaryNativeLibraryDir(
-                String secondaryNativeLibraryDir) {
-            ai.secondaryNativeLibraryDir = secondaryNativeLibraryDir;
-            return this;
-        }
-
-        public ApplicationInfoBuilder setMetaData(Bundle metaData) {
-            ai.metaData = metaData;
-            return this;
-        }
-
-        public ApplicationInfoBuilder() {
-            ai = new android.content.pm.ApplicationInfo();
-        }
-
-        public ApplicationInfo create() {
-            return ai;
-        }
-    }
-}
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index 6f52fbd..c4017d15 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -188,6 +188,12 @@
     <library name="android.test.runner"
             file="/system/framework/android.test.runner.impl.jar" />
 
+    <!-- In BOOT_JARS historically, and now added to legacy applications. -->
+    <library name="android.hidl.base-V1.0-java"
+            file="/system/framework/android.hidl.base-V1.0-java.jar" />
+    <library name="android.hidl.manager-V1.0-java"
+            file="/system/framework/android.hidl.manager-V1.0-java.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. -->
     <allow-in-power-save package="com.android.providers.downloads" />
diff --git a/data/fonts/fonts.xml b/data/fonts/fonts.xml
index be9347a..c84c035 100644
--- a/data/fonts/fonts.xml
+++ b/data/fonts/fonts.xml
@@ -137,7 +137,7 @@
         <font weight="400" style="normal" fallbackFor="serif">NotoSerifArmenian-Regular.otf</font>
         <font weight="700" style="normal" fallbackFor="serif">NotoSerifArmenian-Bold.otf</font>
     </family>
-    <family lang="und-Geor und-Geok">
+    <family lang="und-Geor,und-Geok">
         <font weight="400" style="normal">NotoSansGeorgian-Regular.otf</font>
         <font weight="500" style="normal">NotoSansGeorgian-Medium.otf</font>
         <font weight="700" style="normal">NotoSansGeorgian-Bold.otf</font>
@@ -538,7 +538,7 @@
         <font weight="400" style="normal" index="2">NotoSansCJK-Regular.ttc</font>
         <font weight="400" style="normal" index="2" fallbackFor="serif">NotoSerifCJK-Regular.ttc</font>
     </family>
-    <family lang="zh-Hant zh-Bopo">
+    <family lang="zh-Hant,zh-Bopo">
         <font weight="400" style="normal" index="3">NotoSansCJK-Regular.ttc</font>
         <font weight="400" style="normal" index="3" fallbackFor="serif">NotoSerifCJK-Regular.ttc</font>
     </family>
diff --git a/graphics/java/android/graphics/BitmapRegionDecoder.java b/graphics/java/android/graphics/BitmapRegionDecoder.java
index 9b5027d..43282d3 100644
--- a/graphics/java/android/graphics/BitmapRegionDecoder.java
+++ b/graphics/java/android/graphics/BitmapRegionDecoder.java
@@ -17,6 +17,7 @@
 
 import android.annotation.UnsupportedAppUsage;
 import android.content.res.AssetManager;
+import android.os.Build;
 
 import java.io.FileDescriptor;
 import java.io.FileInputStream;
@@ -166,7 +167,7 @@
 
         This can be called from JNI code.
     */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private BitmapRegionDecoder(long decoder) {
         mNativeBitmapRegionDecoder = decoder;
         mRecycled = false;
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index ef58c8f..36c1c21 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -126,7 +126,7 @@
     }
 
     /** @hide */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     public Canvas(long nativeCanvas) {
         if (nativeCanvas == 0) {
             throw new IllegalStateException();
diff --git a/graphics/java/android/graphics/FontListParser.java b/graphics/java/android/graphics/FontListParser.java
index e3e8380..82435d5 100644
--- a/graphics/java/android/graphics/FontListParser.java
+++ b/graphics/java/android/graphics/FontListParser.java
@@ -74,8 +74,7 @@
     private static FontConfig.Family readFamily(XmlPullParser parser)
             throws XmlPullParserException, IOException {
         final String name = parser.getAttributeValue(null, "name");
-        final String lang = parser.getAttributeValue(null, "lang");
-        final String[] langs = lang == null ? null : lang.split("\\s+");
+        final String lang = parser.getAttributeValue("", "lang");
         final String variant = parser.getAttributeValue(null, "variant");
         final List<FontConfig.Font> fonts = new ArrayList<FontConfig.Font>();
         while (parser.next() != XmlPullParser.END_TAG) {
@@ -95,7 +94,7 @@
                 intVariant = FontConfig.Family.VARIANT_ELEGANT;
             }
         }
-        return new FontConfig.Family(name, fonts.toArray(new FontConfig.Font[fonts.size()]), langs,
+        return new FontConfig.Family(name, fonts.toArray(new FontConfig.Font[fonts.size()]), lang,
                 intVariant);
     }
 
@@ -126,8 +125,8 @@
             }
         }
         String sanitizedName = FILENAME_WHITESPACE_PATTERN.matcher(filename).replaceAll("");
-        return new FontConfig.Font(sanitizedName, index,
-                axes.toArray(new FontVariationAxis[axes.size()]), weight, isItalic, fallbackFor);
+        return new FontConfig.Font(sanitizedName, index, axes.toArray(
+                new FontVariationAxis[axes.size()]), weight, isItalic, fallbackFor);
     }
 
     private static FontVariationAxis readAxis(XmlPullParser parser)
diff --git a/graphics/java/android/graphics/Insets.java b/graphics/java/android/graphics/Insets.java
index 5a78530..c3449dd 100644
--- a/graphics/java/android/graphics/Insets.java
+++ b/graphics/java/android/graphics/Insets.java
@@ -16,6 +16,9 @@
 
 package android.graphics;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
 /**
  * An Insets instance holds four integer offsets which describe changes to the four
  * edges of a Rectangle. By convention, positive values move edges towards the
@@ -24,7 +27,7 @@
  * Insets are immutable so may be treated as values.
  *
  */
-public class Insets {
+public final class Insets {
     public static final Insets NONE = new Insets(0, 0, 0, 0);
 
     public final int left;
@@ -51,7 +54,7 @@
      *
      * @return Insets instance with the appropriate values
      */
-    public static Insets of(int left, int top, int right, int bottom) {
+    public static @NonNull Insets of(int left, int top, int right, int bottom) {
         if (left == 0 && top == 0 && right == 0 && bottom == 0) {
             return NONE;
         }
@@ -65,7 +68,7 @@
      *
      * @return an Insets instance with the appropriate values
      */
-    public static Insets of(Rect r) {
+    public static @NonNull Insets of(@Nullable Rect r) {
         return (r == null) ? NONE : of(r.left, r.top, r.right, r.bottom);
     }
 
diff --git a/graphics/java/android/graphics/Movie.java b/graphics/java/android/graphics/Movie.java
index 8162544..6f030ff 100644
--- a/graphics/java/android/graphics/Movie.java
+++ b/graphics/java/android/graphics/Movie.java
@@ -18,6 +18,7 @@
 
 import android.annotation.UnsupportedAppUsage;
 import android.content.res.AssetManager;
+import android.os.Build;
 
 import java.io.FileInputStream;
 import java.io.InputStream;
@@ -30,7 +31,7 @@
     @UnsupportedAppUsage
     private long mNativeMovie;
 
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private Movie(long nativeMovie) {
         if (nativeMovie == 0) {
             throw new RuntimeException("native movie creation failed");
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index 9dab536..6f30653 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -18,6 +18,7 @@
 
 import android.annotation.ColorInt;
 import android.annotation.NonNull;
+import android.annotation.Px;
 import android.annotation.Size;
 import android.annotation.UnsupportedAppUsage;
 import android.graphics.fonts.FontVariationAxis;
@@ -805,25 +806,39 @@
      * Helper for getFlags(), returning true if UNDERLINE_TEXT_FLAG bit is set
      *
      * @return true if the underlineText bit is set in the paint's flags.
+     * @see #getUnderlinePosition()
+     * @see #getUnderlineThickness()
+     * @see #setUnderlineText(boolean)
      */
     public final boolean isUnderlineText() {
         return (getFlags() & UNDERLINE_TEXT_FLAG) != 0;
     }
 
     /**
-     * Distance from top of the underline to the baseline. Positive values mean below the baseline.
-     * This method returns where the underline should be drawn independent of if the underlineText
-     * bit is set at the moment.
-     * @hide
+     * Returns the distance from top of the underline to the baseline in pixels.
+     *
+     * The result is positive for positions that are below the baseline.
+     * This method returns where the underline should be drawn independent of if the {@link
+     * #UNDERLINE_TEXT_FLAG} bit is set.
+     *
+     * @return the position of the underline in pixels
+     * @see #isUnderlineText()
+     * @see #getUnderlineThickness()
+     * @see #setUnderlineText(boolean)
      */
-    public float getUnderlinePosition() {
+    public @Px float getUnderlinePosition() {
         return nGetUnderlinePosition(mNativePaint);
     }
 
     /**
-     * @hide
+     * Returns the thickness of the underline in pixels.
+     *
+     * @return the thickness of the underline in pixels
+     * @see #isUnderlineText()
+     * @see #getUnderlinePosition()
+     * @see #setUnderlineText(boolean)
      */
-    public float getUnderlineThickness() {
+    public @Px float getUnderlineThickness() {
         return nGetUnderlineThickness(mNativePaint);
     }
 
@@ -832,6 +847,9 @@
      *
      * @param underlineText true to set the underlineText bit in the paint's
      *                      flags, false to clear it.
+     * @see #isUnderlineText()
+     * @see #getUnderlinePosition()
+     * @see #getUnderlineThickness()
      */
     public void setUnderlineText(boolean underlineText) {
         nSetUnderlineText(mNativePaint, underlineText);
@@ -840,26 +858,40 @@
     /**
      * Helper for getFlags(), returning true if STRIKE_THRU_TEXT_FLAG bit is set
      *
-     * @return true if the strikeThruText bit is set in the paint's flags.
+     * @return true if the {@link #STRIKE_THRU_TEXT_FLAG} bit is set in the paint's flags.
+     * @see #getStrikeThruPosition()
+     * @see #getStrikeThruThickness()
+     * @see #setStrikeThruText(boolean)
      */
     public final boolean isStrikeThruText() {
         return (getFlags() & STRIKE_THRU_TEXT_FLAG) != 0;
     }
 
     /**
-     * Distance from top of the strike-through line to the baseline. Negative values mean above the
-     * baseline. This method returns where the strike-through line should be drawn independent of if
-     * the strikeThruText bit is set at the moment.
-     * @hide
+     * Distance from top of the strike-through line to the baseline in pixels.
+     *
+     * The result is negative for positions that are above the baseline.
+     * This method returns where the strike-through line should be drawn independent of if the
+     * {@link #STRIKE_THRU_TEXT_FLAG} bit is set.
+     *
+     * @return the position of the strike-through line in pixels
+     * @see #getStrikeThruThickness()
+     * @see #setStrikeThruText(boolean)
+     * @see #isStrikeThruText()
      */
-    public float getStrikeThruPosition() {
+    public @Px float getStrikeThruPosition() {
         return nGetStrikeThruPosition(mNativePaint);
     }
 
     /**
-     * @hide
+     * Returns the thickness of the strike-through line in pixels.
+     *
+     * @return the position of the strike-through line in pixels
+     * @see #getStrikeThruPosition()
+     * @see #setStrikeThruText(boolean)
+     * @see #isStrikeThruText()
      */
-    public float getStrikeThruThickness() {
+    public @Px float getStrikeThruThickness() {
         return nGetStrikeThruThickness(mNativePaint);
     }
 
@@ -868,6 +900,9 @@
      *
      * @param strikeThruText true to set the strikeThruText bit in the paint's
      *                       flags, false to clear it.
+     * @see #getStrikeThruPosition()
+     * @see #getStrikeThruThickness()
+     * @see #isStrikeThruText()
      */
     public void setStrikeThruText(boolean strikeThruText) {
         nSetStrikeThruText(mNativePaint, strikeThruText);
@@ -1560,22 +1595,25 @@
     }
 
     /**
-     * Return the paint's word-spacing for text. The default value is 0.
+     * Return the paint's extra word-spacing for text.
      *
-     * @return the paint's word-spacing for drawing text.
-     * @hide
+     * The default value is 0.
+     *
+     * @return the paint's extra word-spacing for drawing text in pixels.
+     * @see #setWordSpacing(float)
      */
     public float getWordSpacing() {
         return nGetWordSpacing(mNativePaint);
     }
 
     /**
-     * Set the paint's word-spacing for text. The default value is 0.
-     * The value is in pixels (note the units are not the same as for
-     * letter-spacing).
+     * Set the paint's extra word-spacing for text.
      *
-     * @param wordSpacing set the paint's word-spacing for drawing text.
-     * @hide
+     * Increases the white space width between words with the given amount of pixels.
+     * The default value is 0.
+     *
+     * @param wordSpacing set the paint's extra word-spacing for drawing text in pixels.
+     * @see #getWordSpacing()
      */
     public void setWordSpacing(float wordSpacing) {
         nSetWordSpacing(mNativePaint, wordSpacing);
@@ -1704,26 +1742,52 @@
     }
 
     /**
-     * Get the current value of hyphen edit.
+     * Get the current value of packed hyphen edit.
+     *
+     * You can extract start hyphen edit and end hyphen edit by using
+     * {@link android.text.Hyphenator#unpackStartHyphenEdit(int)} and
+     * {@link android.text.Hyphenator#unpackEndHyphenEdit(int)}.
+     *
+     * The default value is 0 which is equivalent to packed value of
+     * {@link android.text.Hyphenator#START_HYPHEN_EDIT_NO_EDIT} and
+     * {@link android.text.Hyphenator#END_HYPHEN_EDIT_NO_EDIT}.
      *
      * @return the current hyphen edit value
-     *
-     * @hide
+     * @see #setHyphenEdit(int)
      */
     public int getHyphenEdit() {
         return nGetHyphenEdit(mNativePaint);
     }
 
     /**
-     * Set a hyphen edit on the paint (causes a hyphen to be added to text when
-     * measured or drawn).
+     * Set a packed hyphen edit on the paint.
      *
-     * @param hyphen 0 for no edit, 1 for adding a hyphen at the end, etc.
-     *        Definition of various values are in the HyphenEdit class in Minikin's Hyphenator.h.
+     * By setting hyphen edit, the measurement and drawing is performed with modifying hyphenation
+     * at the start of line and end of line. For example, by passing
+     * {@link android.text.Hyphenator#END_HYPHEN_EDIT_INSERT_HYPHEN} like as follows, HYPHEN(U+2010)
+     * character is appended at the end of line.
      *
-     * @hide
+     * <pre>
+     * <code>
+     *   Paint paint = new Paint();
+     *   paint.setHyphenEdit(Hyphenator.packHyphenEdit(
+     *       Hyphenator.START_HYPHEN_EDIT_NO_EDIT,
+     *       Hyphenator.END_HYPHEN_EDIT_INSERT_HYPHEN));
+     *   paint.measureText("abc", 0, 3);  // Returns the width of "abc‐"
+     *   Canvas.drawText("abc", 0, 3, 0f, 0f, paint);  // Draws "abc‐"
+     * </code>
+     * </pre>
+     *
+     * You can pack start hyphen edit and end hyphen edit by
+     * {@link android.text.Hyphenator#packHyphenEdit(int,int)}
+     *
+     * The default value is 0 which is equivalent to packed value of
+     * {@link android.text.Hyphenator#START_HYPHEN_EDIT_NO_EDIT} and
+     * {@link android.text.Hyphenator#END_HYPHEN_EDIT_NO_EDIT}.
+     *
+     * @param hyphen a packed hyphen edit value.
+     * @see #getHyphenEdit()
      */
-    @UnsupportedAppUsage
     public void setHyphenEdit(int hyphen) {
         nSetHyphenEdit(mNativePaint, hyphen);
     }
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index 5280642..492c236 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -30,6 +30,7 @@
 import android.graphics.fonts.FontVariationAxis;
 import android.graphics.fonts.SystemFonts;
 import android.net.Uri;
+import android.os.Build;
 import android.provider.FontRequest;
 import android.provider.FontsContract;
 import android.text.FontConfig;
@@ -148,13 +149,7 @@
     @UnsupportedAppUsage
     private @Style int mStyle = 0;
 
-    /**
-     * A maximum value for the weight value.
-     * @hide
-     */
-    public static final int MAX_WEIGHT = 1000;
-
-    private @IntRange(from = 0, to = MAX_WEIGHT) int mWeight = 0;
+    private @IntRange(from = 0, to = android.graphics.fonts.Font.FONT_WEIGHT_MAX) int mWeight = 0;
 
     // Value for weight and italic. Indicates the value is resolved by font metadata.
     // Must be the same as the C++ constant in core/jni/android/graphics/FontFamily.cpp
@@ -673,6 +668,128 @@
     }
 
     /**
+     * A builder class for creating new Typeface instance.
+     *
+     * <p>
+     * Examples,
+     * 1) Create Typeface from single ttf file.
+     * <pre>
+     * <code>
+     * Font font = new Font.Builder("your_font_file.ttf").build();
+     * FontFamily family = new FontFamily.Builder(font).build();
+     * Typeface typeface = new Typeface.CustomFallbackBuilder(family).build();
+     * </code>
+     * </pre>
+     *
+     * 2) Create Typeface from multiple font files and select bold style by default.
+     * <pre>
+     * <code>
+     * Font regularFont = new Font.Builder("regular.ttf").build();
+     * Font boldFont = new Font.Builder("bold.ttf").build();
+     * FontFamily family = new FontFamily.Builder(regularFont)
+     *     .addFont(boldFont).build();
+     * Typeface typeface = new Typeface.CustomFallbackBuilder(family)
+     *     .setWeight(Font.FONT_WEIGHT_BOLD)  // Set bold style as the default style.
+     *                                        // If the font family doesn't have bold style font,
+     *                                        // system will select the closest font.
+     *     .build();
+     * </code>
+     * </pre>
+     *
+     * 3) Create Typeface from single ttf file and if that font does not have glyph for the
+     * characters, use "serif" font family instead.
+     * <pre>
+     * <code>
+     * Font font = new Font.Builder("your_font_file.ttf").build();
+     * FontFamily family = new FontFamily.Builder(font).build();
+     * Typeface typeface = new Typeface.CustomFallbackBuilder(family)
+     *     .setFallback("serif")  // Set serif font family as the fallback.
+     *     .build();
+     * </code>
+     * </pre>
+     * </p>
+     */
+    public static class CustomFallbackBuilder {
+        // TODO: Remove package modifier once android.graphics.FontFamily is deprecated.
+        private final android.graphics.fonts.FontFamily mFamily;
+        private String mFallbackName = null;
+        private @IntRange(from = 0, to = 1000) int mWeight = 400;
+        private boolean mItalic = false;
+
+        /**
+         * Constructs a builder with a font family.
+         *
+         * @param family a family object
+         */
+        // TODO: Remove package modifier once android.graphics.FontFamily is deprecated.
+        public CustomFallbackBuilder(@NonNull android.graphics.fonts.FontFamily family) {
+            Preconditions.checkNotNull(family);
+            mFamily = family;
+        }
+
+        /**
+         * Sets a system fallback by name.
+         *
+         * @param familyName a family name to be used for fallback if the provided fonts can not be
+         *                   used
+         */
+        public CustomFallbackBuilder setFallback(@NonNull String familyName) {
+            Preconditions.checkNotNull(familyName);
+            mFallbackName = familyName;
+            return this;
+        }
+
+        /**
+         * Sets a weight of the Typeface.
+         *
+         * If the font family doesn't have a font of given weight, system will select the closest
+         * font from font family. For example, if a font family has fonts of 300 weight and 700
+         * weight then setWeight(400) is called, system will select the font of 300 weight.
+         *
+         * @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
+         */
+        public CustomFallbackBuilder setWeight(@IntRange(from = 0, to = 1000) int weight) {
+            mWeight = weight;
+            return this;
+        }
+
+        /**
+         * Sets a italic style of the Typeface.
+         *
+         * @param italic true if italic, otherwise false
+         */
+        public CustomFallbackBuilder setItalic(boolean italic) {
+            mItalic = italic;
+            return this;
+        }
+
+        /**
+         * Create the Typeface based on the configured values.
+         *
+         * @return the Typeface object
+         */
+        public Typeface build() {
+            final android.graphics.fonts.FontFamily[] fallback =
+                    SystemFonts.getSystemFallback(mFallbackName);
+            final long[] ptrArray = new long[fallback.length + 1];
+            ptrArray[0] = mFamily.getNativePtr();
+            for (int i = 0; i < fallback.length; ++i) {
+                ptrArray[i + 1] = fallback[i].getNativePtr();
+            }
+            return new Typeface(nativeCreateFromArray(ptrArray, mWeight, mItalic ? 1 : 0));
+        }
+    }
+
+    /**
      * Create a typeface object given a family name, and option style information.
      * If null is passed for the name, then the "default" font will be chosen.
      * The resulting typeface object can be queried (getStyle()) to discover what
@@ -960,7 +1077,7 @@
     }
 
     // don't allow clients to call this directly
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private Typeface(long ni) {
         if (ni == 0) {
             throw new RuntimeException("native typeface cannot be made");
diff --git a/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java b/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java
index 00380c5..11a46c4 100644
--- a/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java
@@ -24,6 +24,7 @@
 import android.content.res.Resources;
 import android.content.res.Resources.Theme;
 import android.content.res.TypedArray;
+import android.os.Build;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.util.LongSparseLongArray;
@@ -67,7 +68,7 @@
     private static final String ELEMENT_TRANSITION = "transition";
     private static final String ELEMENT_ITEM = "item";
 
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private AnimatedStateListState mState;
 
     /** The currently running transition, if any. */
diff --git a/graphics/java/android/graphics/drawable/Icon.java b/graphics/java/android/graphics/drawable/Icon.java
index accc081..7efe522 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.SystemApi;
 import android.annotation.UnsupportedAppUsage;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -33,6 +34,7 @@
 import android.graphics.PorterDuff;
 import android.net.Uri;
 import android.os.AsyncTask;
+import android.os.Build;
 import android.os.Handler;
 import android.os.Message;
 import android.os.Parcel;
@@ -100,7 +102,7 @@
 
     private static final int VERSION_STREAM_SERIALIZER = 1;
 
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private final int mType;
 
     private ColorStateList mTintList;
@@ -117,7 +119,7 @@
 
     // TYPE_RESOURCE: package name
     // TYPE_URI: uri string
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private String          mString1;
 
     // TYPE_RESOURCE: resId
@@ -173,7 +175,7 @@
      * valid compressed bitmap data is found.
      * @hide
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     public int getDataOffset() {
         if (mType != TYPE_DATA) {
             throw new IllegalStateException("called getDataOffset() on " + this);
@@ -188,7 +190,7 @@
      * bitmap data.
      * @hide
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     public byte[] getDataBytes() {
         if (mType != TYPE_DATA) {
             throw new IllegalStateException("called getDataBytes() on " + this);
@@ -202,7 +204,7 @@
      * @return The {@link android.content.res.Resources} for this {@link #TYPE_RESOURCE} Icon.
      * @hide
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     public Resources getResources() {
         if (mType != TYPE_RESOURCE) {
             throw new IllegalStateException("called getResources() on " + this);
@@ -568,7 +570,7 @@
      * Version of createWithResource that takes Resources. Do not use.
      * @hide
      */
-    @UnsupportedAppUsage
+    @SystemApi
     public static Icon createWithResource(Resources res, @DrawableRes int resId) {
         if (res == null) {
             throw new IllegalArgumentException("Resource must not be null.");
diff --git a/graphics/java/android/graphics/drawable/StateListDrawable.java b/graphics/java/android/graphics/drawable/StateListDrawable.java
index 8de8f81..2855227 100644
--- a/graphics/java/android/graphics/drawable/StateListDrawable.java
+++ b/graphics/java/android/graphics/drawable/StateListDrawable.java
@@ -280,7 +280,7 @@
      * @see #getStateDrawable(int)
      * @see #getStateSet(int)
      */
-    public int getStateDrawableIndex(int[] stateSet) {
+    public int findStateDrawableIndex(int[] stateSet) {
         return mStateListState.indexOfStateSet(stateSet);
     }
 
diff --git a/graphics/java/android/graphics/fonts/Font.java b/graphics/java/android/graphics/fonts/Font.java
index f0c5199..1458c66 100644
--- a/graphics/java/android/graphics/fonts/Font.java
+++ b/graphics/java/android/graphics/fonts/Font.java
@@ -21,6 +21,7 @@
 import android.annotation.Nullable;
 import android.content.res.AssetManager;
 import android.content.res.Resources;
+import android.os.LocaleList;
 import android.util.TypedValue;
 
 import com.android.internal.util.Preconditions;
@@ -50,6 +51,11 @@
     private static final int STYLE_NORMAL = 0;
 
     /**
+     * A minimum weight value for the font
+     */
+    public static final int FONT_WEIGHT_MIN = 1;
+
+    /**
      * A font weight value for the thin weight
      */
     public static final int FONT_WEIGHT_THIN = 100;
@@ -95,6 +101,11 @@
     public static final int FONT_WEIGHT_BLACK = 900;
 
     /**
+     * A maximum weight value for the font
+     */
+    public static final int FONT_WEIGHT_MAX = 1000;
+
+    /**
      * A builder class for creating new Font.
      */
     public static class Builder {
@@ -107,6 +118,8 @@
                     nGetReleaseNativeFont(), 64);
 
         private @Nullable ByteBuffer mBuffer;
+        private @Nullable File mFile;
+        private @NonNull String mLocaleList = "";
         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;
@@ -131,6 +144,19 @@
         }
 
         /**
+         * Construct a builder with a byte buffer and file path.
+         *
+         * This method is intended to be called only from SystemFonts.
+         * @hide
+         */
+        public Builder(@NonNull ByteBuffer buffer, @NonNull File path,
+                @NonNull String localeList) {
+            this(buffer);
+            mFile = path;
+            mLocaleList = localeList;
+        }
+
+        /**
          * Constructs a builder with a file path.
          *
          * @param path a file path to the font file
@@ -143,6 +169,7 @@
             } catch (IOException e) {
                 mException = e;
             }
+            mFile = path;
         }
 
         /**
@@ -305,8 +332,9 @@
          * @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);
+        public @NonNull Builder setWeight(
+                @IntRange(from = FONT_WEIGHT_MIN, to = FONT_WEIGHT_MAX) int weight) {
+            Preconditions.checkArgument(FONT_WEIGHT_MIN <= weight && weight <= FONT_WEIGHT_MAX);
             mWeight = weight;
             return this;
         }
@@ -386,6 +414,7 @@
                     mItalic = STYLE_NORMAL;
                 }
             }
+            mWeight = Math.max(FONT_WEIGHT_MIN, Math.min(FONT_WEIGHT_MAX, mWeight));
             final boolean italic = (mItalic == STYLE_ITALIC);
             final long builderPtr = nInitBuilder();
             if (mAxes != null) {
@@ -394,7 +423,8 @@
                 }
             }
             final long ptr = nBuild(builderPtr, mBuffer, mWeight, italic, mTtcIndex);
-            final Font font = new Font(ptr, mBuffer, mWeight, italic, mTtcIndex, mAxes);
+            final Font font = new Font(ptr, mBuffer, mFile, mWeight, italic, mTtcIndex, mAxes,
+                    mLocaleList);
             sFontRegistory.registerNativeAllocation(font, ptr);
             return font;
         }
@@ -422,23 +452,48 @@
 
     private final long mNativePtr;  // address of the shared ptr of minikin::Font
     private final @NonNull ByteBuffer mBuffer;
+    private final @Nullable File mFile;
     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;
+    private final @NonNull String mLocaleList;
 
     /**
      * Use Builder instead
      */
-    private Font(long nativePtr, @NonNull ByteBuffer buffer,
+    private Font(long nativePtr, @NonNull ByteBuffer buffer, @Nullable File file,
             @IntRange(from = 0, to = 1000) int weight, boolean italic,
-            @IntRange(from = 0) int ttcIndex, @Nullable FontVariationAxis[] axes) {
+            @IntRange(from = 0) int ttcIndex, @Nullable FontVariationAxis[] axes,
+            @NonNull String localeList) {
         mBuffer = buffer;
+        mFile = file;
         mWeight = weight;
         mItalic = italic;
         mNativePtr = nativePtr;
         mTtcIndex = ttcIndex;
         mAxes = axes;
+        mLocaleList = localeList;
+    }
+
+    /**
+     * Retuns a font file buffer.
+     *
+     * @return a font buffer
+     */
+    public @NonNull ByteBuffer getBuffer() {
+        return mBuffer;
+    }
+
+    /**
+     * Returns a file path of this font.
+     *
+     * This returns null if this font is not created from regular file.
+     *
+     * @return a file path of the font
+     */
+    public @Nullable File getFile() {
+        return mFile;
     }
 
     /**
@@ -484,6 +539,16 @@
         return mAxes == null ? null : mAxes.clone();
     }
 
+    /**
+     * Get a locale list of this font.
+     *
+     * This is always empty if this font is not a system font.
+     * @return a locale list
+     */
+    public @NonNull LocaleList getLocaleList() {
+        return LocaleList.forLanguageTags(mLocaleList);
+    }
+
     /** @hide */
     public long getNativePtr() {
         return mNativePtr;
@@ -504,11 +569,19 @@
 
     @Override
     public int hashCode() {
-        return Objects.hash(mWeight, mItalic, mTtcIndex, mAxes, mBuffer);
+        return Objects.hash(mWeight, mItalic, mTtcIndex, Arrays.hashCode(mAxes), mBuffer);
     }
 
     @Override
     public String toString() {
-        return "Font {weight=" + mWeight + ", italic=" + mItalic + "}";
+        return "Font {"
+            + "path=" + mFile
+            + ", weight=" + mWeight
+            + ", italic=" + mItalic
+            + ", ttcIndex=" + mTtcIndex
+            + ", axes=" + FontVariationAxis.toFontVariationSettings(mAxes)
+            + ", localeList=" + mLocaleList
+            + ", buffer=" + mBuffer
+            + "}";
     }
 }
diff --git a/graphics/java/android/graphics/fonts/FontFamily.java b/graphics/java/android/graphics/fonts/FontFamily.java
index c914ece..3bcdc31 100644
--- a/graphics/java/android/graphics/fonts/FontFamily.java
+++ b/graphics/java/android/graphics/fonts/FontFamily.java
@@ -18,9 +18,7 @@
 
 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;
 
@@ -110,25 +108,16 @@
          * @return a font family
          */
         public @NonNull FontFamily build() {
-            return build(null, FontConfig.Family.VARIANT_DEFAULT);
+            return build("", FontConfig.Family.VARIANT_DEFAULT);
         }
 
         /** @hide */
-        public @NonNull FontFamily build(@Nullable String[] langTags, int variant) {
+        public @NonNull FontFamily build(@NonNull 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 long ptr = nBuild(builderPtr, langTags, variant);
             final FontFamily family = new FontFamily(mFonts, ptr);
             sFamilyRegistory.registerNativeAllocation(family, ptr);
             return family;
diff --git a/graphics/java/android/graphics/fonts/FontVariationAxis.java b/graphics/java/android/graphics/fonts/FontVariationAxis.java
index 242cbb8..bcee559 100644
--- a/graphics/java/android/graphics/fonts/FontVariationAxis.java
+++ b/graphics/java/android/graphics/fonts/FontVariationAxis.java
@@ -19,6 +19,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.UnsupportedAppUsage;
+import android.os.Build;
 import android.text.TextUtils;
 
 import java.util.ArrayList;
@@ -29,7 +30,7 @@
  * Class that holds information about single font variation axis.
  */
 public final class FontVariationAxis {
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private final int mTag;
     private final String mTagString;
     @UnsupportedAppUsage
diff --git a/graphics/java/android/graphics/fonts/SystemFonts.java b/graphics/java/android/graphics/fonts/SystemFonts.java
index 26b4ec5..f4a2199 100644
--- a/graphics/java/android/graphics/fonts/SystemFonts.java
+++ b/graphics/java/android/graphics/fonts/SystemFonts.java
@@ -28,6 +28,7 @@
 
 import org.xmlpull.v1.XmlPullParserException;
 
+import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.nio.ByteBuffer;
@@ -36,12 +37,13 @@
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 /**
  * Provides the system font configurations.
- * @hide
  */
 public class SystemFonts {
     private static final String TAG = "SystemFonts";
@@ -49,8 +51,21 @@
 
     private SystemFonts() {}  // Do not instansiate.
 
-    static final Map<String, FontFamily[]> sSystemFallbackMap;
-    static final FontConfig.Alias[] sAliases;
+    private static final Map<String, FontFamily[]> sSystemFallbackMap;
+    private static final FontConfig.Alias[] sAliases;
+    private static final List<Font> sAvailableFonts;
+
+    /**
+     * Returns all available font files in the system.
+     *
+     * Note: The order of this font doesn't indicates anything.
+     * @return an array of system fonts
+     */
+    public static @NonNull Set<Font> getAvailableFonts() {
+        HashSet<Font> set = new HashSet<>();
+        set.addAll(sAvailableFonts);
+        return set;
+    }
 
     /**
      * Returns fallback list for the given family name.
@@ -58,6 +73,7 @@
      * If no fallback found for the given family name, returns fallback for the default family.
      *
      * @param familyName family name, e.g. "serif"
+     * @hide
      */
     public static @NonNull FontFamily[] getSystemFallback(@Nullable String familyName) {
         final FontFamily[] families = sSystemFallbackMap.get(familyName);
@@ -68,6 +84,7 @@
      * Returns raw system fallback map.
      *
      * This method is intended to be used only by Typeface static initializer.
+     * @hide
      */
     public static @NonNull Map<String, FontFamily[]> getRawSystemFallbackMap() {
         return sSystemFallbackMap;
@@ -77,6 +94,7 @@
      * Returns a list of aliases.
      *
      * This method is intended to be used only by Typeface static initializer.
+     * @hide
      */
     public static @NonNull FontConfig.Alias[] getAliases() {
         return sAliases;
@@ -96,9 +114,10 @@
     private static void pushFamilyToFallback(@NonNull FontConfig.Family xmlFamily,
             @NonNull ArrayMap<String, ArrayList<FontFamily>> fallbackMap,
             @NonNull Map<String, ByteBuffer> cache,
-            @NonNull String fontDir) {
+            @NonNull String fontDir,
+            @NonNull ArrayList<Font> availableFonts) {
 
-        final String[] languageTags = xmlFamily.getLanguages();
+        final String languageTags = xmlFamily.getLanguages();
         final int variant = xmlFamily.getVariant();
 
         final ArrayList<FontConfig.Font> defaultFonts = new ArrayList<>();
@@ -120,7 +139,8 @@
         }
 
         final FontFamily defaultFamily = defaultFonts.isEmpty() ? null : createFontFamily(
-                xmlFamily.getName(), defaultFonts, languageTags, variant, cache, fontDir);
+                xmlFamily.getName(), defaultFonts, languageTags, variant, cache, fontDir,
+                availableFonts);
 
         // Insert family into fallback map.
         for (int i = 0; i < fallbackMap.size(); i++) {
@@ -132,7 +152,8 @@
                 }
             } else {
                 final FontFamily family = createFontFamily(
-                        xmlFamily.getName(), fallback, languageTags, variant, cache, fontDir);
+                        xmlFamily.getName(), fallback, languageTags, variant, cache, fontDir,
+                        availableFonts);
                 if (family != null) {
                     fallbackMap.valueAt(i).add(family);
                 } else if (defaultFamily != null) {
@@ -146,10 +167,11 @@
 
     private static @Nullable FontFamily createFontFamily(@NonNull String familyName,
             @NonNull List<FontConfig.Font> fonts,
-            @NonNull String[] languageTags,
+            @NonNull String languageTags,
             @FontConfig.Family.Variant int variant,
             @NonNull Map<String, ByteBuffer> cache,
-            @NonNull String fontDir) {
+            @NonNull String fontDir,
+            @NonNull ArrayList<Font> availableFonts) {
         if (fonts.size() == 0) {
             return null;
         }
@@ -172,7 +194,7 @@
 
             final Font font;
             try {
-                font = new Font.Builder(buffer)
+                font = new Font.Builder(buffer, new File(fullPath), languageTags)
                         .setWeight(fontConfig.getWeight())
                         .setItalic(fontConfig.isItalic())
                         .setTtcIndex(fontConfig.getTtcIndex())
@@ -182,6 +204,7 @@
                 throw new RuntimeException(e);  // Never reaches here
             }
 
+            availableFonts.add(font);
             if (b == null) {
                 b = new FontFamily.Builder(font);
             } else {
@@ -204,7 +227,8 @@
     @VisibleForTesting
     public static FontConfig.Alias[] buildSystemFallback(@NonNull String xmlPath,
             @NonNull String fontDir,
-            @NonNull ArrayMap<String, FontFamily[]> fallbackMap) {
+            @NonNull ArrayMap<String, FontFamily[]> fallbackMap,
+            @NonNull ArrayList<Font> availableFonts) {
         try {
             final FileInputStream fontsIn = new FileInputStream(xmlPath);
             final FontConfig fontConfig = FontListParser.parse(fontsIn);
@@ -221,7 +245,8 @@
                 }
                 final FontFamily family = createFontFamily(
                         xmlFamily.getName(), Arrays.asList(xmlFamily.getFonts()),
-                        xmlFamily.getLanguages(), xmlFamily.getVariant(), bufferCache, fontDir);
+                        xmlFamily.getLanguages(), xmlFamily.getVariant(), bufferCache, fontDir,
+                        availableFonts);
                 if (family == null) {
                     continue;
                 }
@@ -236,7 +261,8 @@
                 // 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);
+                    pushFamilyToFallback(xmlFamily, fallbackListMap, bufferCache, fontDir,
+                            availableFonts);
                 }
             }
 
@@ -258,9 +284,11 @@
 
     static {
         final ArrayMap<String, FontFamily[]> systemFallbackMap = new ArrayMap<>();
+        final ArrayList<Font> availableFonts = new ArrayList<>();
         sAliases = buildSystemFallback("/system/etc/fonts.xml", "/system/fonts/",
-                systemFallbackMap);
+                systemFallbackMap, availableFonts);
         sSystemFallbackMap = Collections.unmodifiableMap(systemFallbackMap);
+        sAvailableFonts = Collections.unmodifiableList(availableFonts);
     }
 
 }
diff --git a/keystore/java/android/security/KeyChain.java b/keystore/java/android/security/KeyChain.java
index 78dbb6a..5d5e40f 100644
--- a/keystore/java/android/security/KeyChain.java
+++ b/keystore/java/android/security/KeyChain.java
@@ -40,6 +40,7 @@
 
 import java.io.ByteArrayInputStream;
 import java.io.Closeable;
+import java.io.Serializable;
 import java.security.KeyPair;
 import java.security.Principal;
 import java.security.PrivateKey;
@@ -55,6 +56,8 @@
 import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.LinkedBlockingQueue;
 
+import javax.security.auth.x500.X500Principal;
+
 import com.android.org.conscrypt.TrustedCertificateStore;
 
 /**
@@ -142,6 +145,18 @@
     public static final String EXTRA_SENDER = "sender";
 
     /**
+     * Extra for use with {@link #ACTION_CHOOSER}
+     * @hide Also used by KeyChainActivity implementation
+     */
+    public static final String EXTRA_KEY_TYPES = "key_types";
+
+    /**
+     * Extra for use with {@link #ACTION_CHOOSER}
+     * @hide Also used by KeyChainActivity implementation
+     */
+    public static final String EXTRA_ISSUERS = "issuers";
+
+    /**
      * Action to bring up the CertInstaller.
      */
     private static final String ACTION_INSTALL = "android.credentials.INSTALL";
@@ -365,9 +380,10 @@
      * onChoosePrivateKeyAlias}.
      *
      * <p>{@code keyTypes} and {@code issuers} may be used to
-     * highlight suggested choices to the user, although to cope with
-     * sometimes erroneous values provided by servers, the user may be
-     * able to override these suggestions.
+     * narrow down suggested choices to the user. If either {@code keyTypes}
+     * or {@code issuers} is specified and non-empty, and there are no
+     * matching certificates in the KeyChain, then the certificate
+     * selection prompt would be suppressed entirely.
      *
      * <p>{@code host} and {@code port} may be used to give the user
      * more context about the server requesting the credentials.
@@ -382,7 +398,7 @@
      * @param response Callback to invoke when the request completes;
      *     must not be null.
      * @param keyTypes The acceptable types of asymmetric keys such as
-     *     "RSA" or "DSA", or null.
+     *     "RSA", "EC" or null.
      * @param issuers The acceptable certificate issuers for the
      *     certificate matching the private key, or null.
      * @param host The host name of the server requesting the
@@ -419,9 +435,10 @@
      * onChoosePrivateKeyAlias}.
      *
      * <p>{@code keyTypes} and {@code issuers} may be used to
-     * highlight suggested choices to the user, although to cope with
-     * sometimes erroneous values provided by servers, the user may be
-     * able to override these suggestions.
+     * narrow down suggested choices to the user. If either {@code keyTypes}
+     * or {@code issuers} is specified and non-empty, and there are no
+     * matching certificates in the KeyChain, then the certificate
+     * selection prompt would be suppressed entirely.
      *
      * <p>{@code uri} may be used to give the user more context about
      * the server requesting the credentials.
@@ -436,13 +453,15 @@
      * @param response Callback to invoke when the request completes;
      *     must not be null.
      * @param keyTypes The acceptable types of asymmetric keys such as
-     *     "EC" or "RSA", or null.
+     *     "RSA", "EC" or null.
      * @param issuers The acceptable certificate issuers for the
      *     certificate matching the private key, or null.
      * @param uri The full URI the server is requesting the certificate
      *     for, or null if unavailable.
      * @param alias The alias to preselect if available, or null if
      *     unavailable.
+     * @throws IllegalArgumentException if the specified issuers are not
+     *     of type {@code X500Principal}.
      */
     public static void choosePrivateKeyAlias(@NonNull Activity activity,
             @NonNull KeyChainAliasCallback response,
@@ -450,20 +469,21 @@
             @Nullable Principal[] issuers,
             @Nullable Uri uri, @Nullable String alias) {
         /*
-         * TODO currently keyTypes, issuers are unused. They are meant
-         * to follow the semantics and purpose of X509KeyManager
-         * method arguments.
+         * Specifying keyTypes excludes certificates with different key types
+         * from the list of certificates presented to the user.
+         * In practice today, most servers would require RSA or EC
+         * certificates.
          *
-         * keyTypes would allow the list to be filtered and typically
-         * will be set correctly by the server. In practice today,
-         * most all users will want only RSA or EC, and usually
-         * only a small number of certs will be available.
-         *
-         * issuers is typically not useful. Some servers historically
-         * will send the entire list of public CAs known to the
-         * server. Others will send none. If this is used, if there
-         * are no matches after applying the constraint, it should be
-         * ignored.
+         * Specifying issuers narrows down the list by filtering out
+         * certificates with issuers which are not matching the provided ones.
+         * This has been reported to Chrome several times (crbug.com/731769).
+         * There's no concrete description on what to do when the client has no
+         * certificates that match the provided issuers.
+         * To be conservative, Android will not present the user with any
+         * certificates to choose from.
+         * If the list of issuers is empty then the client may send any
+         * certificate, see:
+         * https://tools.ietf.org/html/rfc5246#section-7.4.4
          */
         if (activity == null) {
             throw new NullPointerException("activity == null");
@@ -476,6 +496,26 @@
         intent.putExtra(EXTRA_RESPONSE, new AliasResponse(response));
         intent.putExtra(EXTRA_URI, uri);
         intent.putExtra(EXTRA_ALIAS, alias);
+        intent.putExtra(EXTRA_KEY_TYPES, keyTypes);
+        ArrayList<byte[]> issuersList = new ArrayList();
+        if (issuers != null) {
+            for (Principal issuer: issuers) {
+                // In a TLS client context (like Chrome), issuers would only
+                // be specified as X500Principals. No other use cases for
+                // specifying principals have been brought up. Under these
+                // circumstances, only allow issuers specified as
+                // X500Principals.
+                if (!(issuer instanceof X500Principal)) {
+                    throw new IllegalArgumentException(String.format(
+                            "Issuer %s is of type %s, not X500Principal",
+                            issuer.toString(), issuer.getClass()));
+                }
+                // Pass the DER-encoded issuer as that's the most accurate
+                // representation and what is sent over the wire.
+                issuersList.add(((X500Principal) issuer).getEncoded());
+            }
+        }
+        intent.putExtra(EXTRA_ISSUERS, (Serializable) issuersList);
         // the PendingIntent is used to get calling package name
         intent.putExtra(EXTRA_SENDER, PendingIntent.getActivity(activity, 0, new Intent(), 0));
         activity.startActivity(intent);
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index 402e390..dc4a0a7 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -3205,20 +3205,6 @@
                 break;
         }
     }
-    if ((colorMode&MASK_HDR) != 0) {
-        if (res.size() > 0) res.append("-");
-        switch (colorMode&MASK_HDR) {
-            case ResTable_config::HDR_NO:
-                res.append("lowdr");
-                break;
-            case ResTable_config::HDR_YES:
-                res.append("highdr");
-                break;
-            default:
-                res.appendFormat("hdr=%d", dtohs(colorMode&MASK_HDR));
-                break;
-        }
-    }
     if ((colorMode&MASK_WIDE_COLOR_GAMUT) != 0) {
         if (res.size() > 0) res.append("-");
         switch (colorMode&MASK_WIDE_COLOR_GAMUT) {
@@ -3233,6 +3219,20 @@
                 break;
         }
     }
+    if ((colorMode&MASK_HDR) != 0) {
+        if (res.size() > 0) res.append("-");
+        switch (colorMode&MASK_HDR) {
+            case ResTable_config::HDR_NO:
+                res.append("lowdr");
+                break;
+            case ResTable_config::HDR_YES:
+                res.append("highdr");
+                break;
+            default:
+                res.appendFormat("hdr=%d", dtohs(colorMode&MASK_HDR));
+                break;
+        }
+    }
     if (orientation != ORIENTATION_ANY) {
         if (res.size() > 0) res.append("-");
         switch (orientation) {
diff --git a/libs/androidfw/include/androidfw/ByteBucketArray.h b/libs/androidfw/include/androidfw/ByteBucketArray.h
index d84a207..949c9445 100644
--- a/libs/androidfw/include/androidfw/ByteBucketArray.h
+++ b/libs/androidfw/include/androidfw/ByteBucketArray.h
@@ -60,7 +60,7 @@
   }
 
   T& editItemAt(size_t index) {
-    CHECK(index < size()) << "ByteBucketArray.getOrCreate(index=" << index
+    CHECK(index < size()) << "ByteBucketArray.editItemAt(index=" << index
                           << ") with size=" << size();
 
     uint8_t bucket_index = static_cast<uint8_t>(index) >> 4;
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index d582983..04bbe24 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -72,6 +72,7 @@
         "libft2",
         "libminikin",
         "libandroidfw",
+        "libcrypto",
     ],
     static_libs: [
         "libEGL_blobCache",
@@ -169,15 +170,12 @@
         "pipeline/skia/SkiaDisplayList.cpp",
         "pipeline/skia/SkiaMemoryTracer.cpp",
         "pipeline/skia/SkiaOpenGLPipeline.cpp",
-        "pipeline/skia/SkiaOpenGLReadback.cpp",
         "pipeline/skia/SkiaPipeline.cpp",
         "pipeline/skia/SkiaProfileRenderer.cpp",
         "pipeline/skia/SkiaRecordingCanvas.cpp",
         "pipeline/skia/SkiaVulkanPipeline.cpp",
         "pipeline/skia/VectorDrawableAtlas.cpp",
-        "renderstate/PixelBufferState.cpp",
         "renderstate/RenderState.cpp",
-        "renderstate/TextureState.cpp",
         "renderthread/CacheManager.cpp",
         "renderthread/CanvasContext.cpp",
         "renderthread/DrawFrameTask.cpp",
@@ -189,18 +187,19 @@
         "renderthread/TimeLord.cpp",
         "renderthread/Frame.cpp",
         "service/GraphicsStatsService.cpp",
+        "surfacetexture/EGLConsumer.cpp",
+        "surfacetexture/ImageConsumer.cpp",
+        "surfacetexture/SurfaceTexture.cpp",
         "thread/TaskManager.cpp",
         "utils/Blur.cpp",
         "utils/Color.cpp",
         "utils/GLUtils.cpp",
         "utils/LinearAllocator.cpp",
         "utils/StringUtils.cpp",
-        "utils/TestWindowContext.cpp",
         "utils/VectorDrawableUtils.cpp",
         "AnimationContext.cpp",
         "Animator.cpp",
         "AnimatorManager.cpp",
-        "Caches.cpp",
         "CanvasState.cpp",
         "CanvasTransform.cpp",
         "ClipArea.cpp",
@@ -209,7 +208,6 @@
         "DeviceInfo.cpp",
         "FrameInfo.cpp",
         "FrameInfoVisualizer.cpp",
-        "GlLayer.cpp",
         "GpuMemoryTracker.cpp",
         "HardwareBitmapUploader.cpp",
         "Interpolator.cpp",
@@ -217,23 +215,20 @@
         "Layer.cpp",
         "LayerUpdateQueue.cpp",
         "Matrix.cpp",
-        "EglReadback.cpp",
         "PathParser.cpp",
-        "PixelBuffer.cpp",
         "ProfileData.cpp",
         "ProfileDataContainer.cpp",
         "Properties.cpp",
         "PropertyValuesAnimatorSet.cpp",
         "PropertyValuesHolder.cpp",
+        "Readback.cpp",
         "RecordingCanvas.cpp",
         "RenderNode.cpp",
         "RenderProperties.cpp",
         "ResourceCache.cpp",
         "SkiaCanvas.cpp",
         "Snapshot.cpp",
-        "Texture.cpp",
         "VectorDrawable.cpp",
-        "VkLayer.cpp",
         "protos/graphicsstats.proto",
     ],
 
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
deleted file mode 100644
index 2541444..0000000
--- a/libs/hwui/Caches.cpp
+++ /dev/null
@@ -1,103 +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.
- */
-
-#include "Caches.h"
-
-#include "GlLayer.h"
-#include "Properties.h"
-#include "renderstate/RenderState.h"
-#include "utils/GLUtils.h"
-
-#include <cutils/properties.h>
-#include <utils/Log.h>
-#include <utils/String8.h>
-
-namespace android {
-namespace uirenderer {
-
-Caches* Caches::sInstance = nullptr;
-
-///////////////////////////////////////////////////////////////////////////////
-// Macros
-///////////////////////////////////////////////////////////////////////////////
-
-#if DEBUG_CACHE_FLUSH
-#define FLUSH_LOGD(...) ALOGD(__VA_ARGS__)
-#else
-#define FLUSH_LOGD(...)
-#endif
-
-///////////////////////////////////////////////////////////////////////////////
-// Constructors/destructor
-///////////////////////////////////////////////////////////////////////////////
-
-Caches::Caches(RenderState& renderState) : mInitialized(false) {
-    INIT_LOGD("Creating OpenGL renderer caches");
-    init();
-    initStaticProperties();
-}
-
-bool Caches::init() {
-    if (mInitialized) return false;
-
-    ATRACE_NAME("Caches::init");
-
-    mRegionMesh = nullptr;
-
-    mInitialized = true;
-
-    mPixelBufferState = new PixelBufferState();
-    mTextureState = new TextureState();
-    mTextureState->constructTexture(*this);
-
-    return true;
-}
-
-void Caches::initStaticProperties() {
-    // OpenGL ES 3.0+ specific features
-    gpuPixelBuffersEnabled = extensions().hasPixelBufferObjects() &&
-                             property_get_bool(PROPERTY_ENABLE_GPU_PIXEL_BUFFERS, true);
-}
-
-void Caches::terminate() {
-    if (!mInitialized) return;
-    mRegionMesh.reset(nullptr);
-
-    clearGarbage();
-
-    delete mPixelBufferState;
-    mPixelBufferState = nullptr;
-    delete mTextureState;
-    mTextureState = nullptr;
-    mInitialized = false;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Memory management
-///////////////////////////////////////////////////////////////////////////////
-
-void Caches::clearGarbage() {}
-
-void Caches::flush(FlushMode mode) {
-    clearGarbage();
-    glFinish();
-    // Errors during cleanup should be considered non-fatal, dump them and
-    // and move on. TODO: All errors or just errors like bad surface?
-    GLUtils::dumpGLErrors();
-}
-
-};  // namespace uirenderer
-};  // namespace android
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
deleted file mode 100644
index 642f9dc..0000000
--- a/libs/hwui/Caches.h
+++ /dev/null
@@ -1,135 +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.
- */
-
-#pragma once
-
-#include "DeviceInfo.h"
-#include "Extensions.h"
-#include "ResourceCache.h"
-#include "renderstate/PixelBufferState.h"
-#include "renderstate/TextureState.h"
-#include "thread/TaskManager.h"
-#include "thread/TaskProcessor.h"
-
-#include <memory>
-#include <vector>
-
-#include <GLES3/gl3.h>
-
-#include <utils/KeyedVector.h>
-
-#include <cutils/compiler.h>
-
-#include <SkPath.h>
-
-#include <vector>
-
-namespace android {
-namespace uirenderer {
-
-///////////////////////////////////////////////////////////////////////////////
-// Caches
-///////////////////////////////////////////////////////////////////////////////
-
-class RenderNode;
-class RenderState;
-
-class ANDROID_API Caches {
-public:
-    static Caches& createInstance(RenderState& renderState) {
-        LOG_ALWAYS_FATAL_IF(sInstance, "double create of Caches attempted");
-        sInstance = new Caches(renderState);
-        return *sInstance;
-    }
-
-    static Caches& getInstance() {
-        LOG_ALWAYS_FATAL_IF(!sInstance, "instance not yet created");
-        return *sInstance;
-    }
-
-    static bool hasInstance() { return sInstance != nullptr; }
-
-private:
-    explicit Caches(RenderState& renderState);
-    static Caches* sInstance;
-
-public:
-    enum class FlushMode { Layers = 0, Moderate, Full };
-
-    /**
-     * Initialize caches.
-     */
-    bool init();
-
-    bool isInitialized() { return mInitialized; }
-
-    /**
-     * Flush the cache.
-     *
-     * @param mode Indicates how much of the cache should be flushed
-     */
-    void flush(FlushMode mode);
-
-    /**
-     * Destroys all resources associated with this cache. This should
-     * be called after a flush(FlushMode::Full).
-     */
-    void terminate();
-
-    /**
-     * Call this on each frame to ensure that garbage is deleted from
-     * GPU memory.
-     */
-    void clearGarbage();
-
-    /**
-     * Returns the GL RGBA internal format to use for the current device
-     * If the device supports linear blending and needSRGB is true,
-     * this function returns GL_SRGB8_ALPHA8, otherwise it returns GL_RGBA
-     */
-    constexpr GLint rgbaInternalFormat(bool needSRGB = true) const {
-        return extensions().hasLinearBlending() && needSRGB ? GL_SRGB8_ALPHA8 : GL_RGBA;
-    }
-
-public:
-    TaskManager tasks;
-
-    bool gpuPixelBuffersEnabled;
-
-    const Extensions& extensions() const { return DeviceInfo::get()->extensions(); }
-    PixelBufferState& pixelBufferState() { return *mPixelBufferState; }
-    TextureState& textureState() { return *mTextureState; }
-
-private:
-    void initStaticProperties();
-
-    static void eventMarkNull(GLsizei length, const GLchar* marker) {}
-    static void startMarkNull(GLsizei length, const GLchar* marker) {}
-    static void endMarkNull() {}
-
-    // Used to render layers
-    std::unique_ptr<TextureVertex[]> mRegionMesh;
-
-    bool mInitialized;
-
-    // TODO: move below to RenderState
-    PixelBufferState* mPixelBufferState = nullptr;
-    TextureState* mTextureState = nullptr;
-
-};  // class Caches
-
-};  // namespace uirenderer
-};  // namespace android
diff --git a/libs/hwui/DeferredLayerUpdater.cpp b/libs/hwui/DeferredLayerUpdater.cpp
index 569de76..837d546 100644
--- a/libs/hwui/DeferredLayerUpdater.cpp
+++ b/libs/hwui/DeferredLayerUpdater.cpp
@@ -15,27 +15,20 @@
  */
 #include "DeferredLayerUpdater.h"
 
-#include "GlLayer.h"
-#include "VkLayer.h"
 #include "renderstate/RenderState.h"
-#include "renderthread/EglManager.h"
-#include "renderthread/RenderTask.h"
 #include "utils/PaintUtils.h"
 
 namespace android {
 namespace uirenderer {
 
-DeferredLayerUpdater::DeferredLayerUpdater(RenderState& renderState, CreateLayerFn createLayerFn,
-                                           Layer::Api layerApi)
+DeferredLayerUpdater::DeferredLayerUpdater(RenderState& renderState)
         : mRenderState(renderState)
         , mBlend(false)
         , mSurfaceTexture(nullptr)
         , mTransform(nullptr)
         , mGLContextAttached(false)
         , mUpdateTexImage(false)
-        , mLayer(nullptr)
-        , mLayerApi(layerApi)
-        , mCreateLayerFn(createLayerFn) {
+        , mLayer(nullptr) {
     renderState.registerDeferredLayerUpdater(this);
 }
 
@@ -50,16 +43,13 @@
         return;
     }
 
-    if (mSurfaceTexture.get() && mLayerApi == Layer::Api::OpenGL && mGLContextAttached) {
-        status_t err = mSurfaceTexture->detachFromContext();
+    if (mSurfaceTexture.get() && mGLContextAttached) {
+        mSurfaceTexture->detachFromView();
         mGLContextAttached = false;
-        if (err != 0) {
-            // TODO: Elevate to fatal exception
-            ALOGE("Failed to detach SurfaceTexture from context %d", err);
-        }
     }
 
     mLayer->postDecStrong();
+
     mLayer = nullptr;
 }
 
@@ -75,99 +65,53 @@
 
 void DeferredLayerUpdater::apply() {
     if (!mLayer) {
-        mLayer = mCreateLayerFn(mRenderState, mWidth, mHeight, mColorFilter, mAlpha, mMode, mBlend);
+        mLayer = new Layer(mRenderState, mColorFilter, mAlpha, mMode);
     }
 
     mLayer->setColorFilter(mColorFilter);
     mLayer->setAlpha(mAlpha, mMode);
 
     if (mSurfaceTexture.get()) {
-        if (mLayer->getApi() == Layer::Api::Vulkan) {
-            if (mUpdateTexImage) {
-                mUpdateTexImage = false;
-                doUpdateVkTexImage();
-            }
-        } else {
-            LOG_ALWAYS_FATAL_IF(mLayer->getApi() != Layer::Api::OpenGL,
-                                "apply surfaceTexture with non GL backend %x, GL %x, VK %x",
-                                mLayer->getApi(), Layer::Api::OpenGL, Layer::Api::Vulkan);
-            if (!mGLContextAttached) {
-                mGLContextAttached = true;
-                mUpdateTexImage = true;
-                mSurfaceTexture->attachToContext(static_cast<GlLayer*>(mLayer)->getTextureId());
-            }
-            if (mUpdateTexImage) {
-                mUpdateTexImage = false;
-                doUpdateTexImage();
-            }
-            GLenum renderTarget = mSurfaceTexture->getCurrentTextureTarget();
-            static_cast<GlLayer*>(mLayer)->setRenderTarget(renderTarget);
+        if (!mGLContextAttached) {
+            mGLContextAttached = true;
+            mUpdateTexImage = true;
+            mSurfaceTexture->attachToView();
         }
+        if (mUpdateTexImage) {
+            mUpdateTexImage = false;
+            sk_sp<SkImage> layerImage;
+            SkMatrix textureTransform;
+            android_dataspace dataSpace;
+            bool queueEmpty = true;
+            // If the SurfaceTexture queue is in synchronous mode, need to discard all
+            // but latest frame. Since we can't tell which mode it is in,
+            // do this unconditionally.
+            do {
+                layerImage = mSurfaceTexture->dequeueImage(textureTransform, dataSpace, &queueEmpty,
+                        mRenderState);
+            } while (layerImage.get() && (!queueEmpty));
+            if (layerImage.get()) {
+                // force filtration if buffer size != layer size
+                bool forceFilter = mWidth != layerImage->width() || mHeight != layerImage->height();
+                updateLayer(forceFilter, textureTransform, dataSpace, layerImage);
+            }
+        }
+
         if (mTransform) {
-            mLayer->getTransform().load(*mTransform);
+            mLayer->getTransform() = *mTransform;
             setTransform(nullptr);
         }
     }
 }
 
-void DeferredLayerUpdater::doUpdateTexImage() {
-    LOG_ALWAYS_FATAL_IF(mLayer->getApi() != Layer::Api::OpenGL,
-                        "doUpdateTexImage non GL backend %x, GL %x, VK %x", mLayer->getApi(),
-                        Layer::Api::OpenGL, Layer::Api::Vulkan);
-    if (mSurfaceTexture->updateTexImage() == NO_ERROR) {
-        float transform[16];
-
-        int64_t frameNumber = mSurfaceTexture->getFrameNumber();
-        // If the GLConsumer queue is in synchronous mode, need to discard all
-        // but latest frame, using the frame number to tell when we no longer
-        // have newer frames to target. Since we can't tell which mode it is in,
-        // do this unconditionally.
-        int dropCounter = 0;
-        while (mSurfaceTexture->updateTexImage() == NO_ERROR) {
-            int64_t newFrameNumber = mSurfaceTexture->getFrameNumber();
-            if (newFrameNumber == frameNumber) break;
-            frameNumber = newFrameNumber;
-            dropCounter++;
-        }
-
-        bool forceFilter = false;
-        sp<GraphicBuffer> buffer = mSurfaceTexture->getCurrentBuffer();
-        if (buffer != nullptr) {
-            // force filtration if buffer size != layer size
-            forceFilter = mWidth != static_cast<int>(buffer->getWidth()) ||
-                          mHeight != static_cast<int>(buffer->getHeight());
-        }
-
-#if DEBUG_RENDERER
-        if (dropCounter > 0) {
-            RENDERER_LOGD("Dropped %d frames on texture layer update", dropCounter);
-        }
-#endif
-        mSurfaceTexture->getTransformMatrix(transform);
-
-        updateLayer(forceFilter, transform, mSurfaceTexture->getCurrentDataSpace());
-    }
-}
-
-void DeferredLayerUpdater::doUpdateVkTexImage() {
-    LOG_ALWAYS_FATAL_IF(mLayer->getApi() != Layer::Api::Vulkan,
-                        "updateLayer non Vulkan backend %x, GL %x, VK %x", mLayer->getApi(),
-                        Layer::Api::OpenGL, Layer::Api::Vulkan);
-
-    static const mat4 identityMatrix;
-    updateLayer(false, identityMatrix.data, HAL_DATASPACE_UNKNOWN);
-
-    VkLayer* vkLayer = static_cast<VkLayer*>(mLayer);
-    vkLayer->updateTexture();
-}
-
-void DeferredLayerUpdater::updateLayer(bool forceFilter, const float* textureTransform,
-                                       android_dataspace dataspace) {
+void DeferredLayerUpdater::updateLayer(bool forceFilter, const SkMatrix& textureTransform,
+        android_dataspace dataspace, const sk_sp<SkImage>& layerImage) {
     mLayer->setBlend(mBlend);
     mLayer->setForceFilter(forceFilter);
     mLayer->setSize(mWidth, mHeight);
-    mLayer->getTexTransform().load(textureTransform);
+    mLayer->getTexTransform() = textureTransform;
     mLayer->setDataSpace(dataspace);
+    mLayer->setImage(layerImage);
 }
 
 void DeferredLayerUpdater::detachSurfaceTexture() {
diff --git a/libs/hwui/DeferredLayerUpdater.h b/libs/hwui/DeferredLayerUpdater.h
index fe3ee7a..4c323b8 100644
--- a/libs/hwui/DeferredLayerUpdater.h
+++ b/libs/hwui/DeferredLayerUpdater.h
@@ -17,18 +17,19 @@
 #pragma once
 
 #include <SkColorFilter.h>
+#include <SkImage.h>
 #include <SkMatrix.h>
 #include <cutils/compiler.h>
-#include <gui/GLConsumer.h>
+#include <map>
 #include <system/graphics.h>
 #include <utils/StrongPointer.h>
 
 #include <GLES2/gl2.h>
 #include <GLES2/gl2ext.h>
 
+#include "surfacetexture/SurfaceTexture.h"
 #include "Layer.h"
 #include "Rect.h"
-#include "renderthread/RenderThread.h"
 
 namespace android {
 namespace uirenderer {
@@ -41,12 +42,7 @@
 public:
     // Note that DeferredLayerUpdater assumes it is taking ownership of the layer
     // and will not call incrementRef on it as a result.
-    typedef std::function<Layer*(RenderState& renderState, uint32_t layerWidth,
-                                 uint32_t layerHeight, sk_sp<SkColorFilter> colorFilter, int alpha,
-                                 SkBlendMode mode, bool blend)>
-            CreateLayerFn;
-    ANDROID_API explicit DeferredLayerUpdater(RenderState& renderState, CreateLayerFn createLayerFn,
-                                              Layer::Api layerApi);
+    ANDROID_API explicit DeferredLayerUpdater(RenderState& renderState);
 
     ANDROID_API ~DeferredLayerUpdater();
 
@@ -70,13 +66,13 @@
         return false;
     }
 
-    ANDROID_API void setSurfaceTexture(const sp<GLConsumer>& texture) {
-        if (texture.get() != mSurfaceTexture.get()) {
-            mSurfaceTexture = texture;
+    ANDROID_API void setSurfaceTexture(const sp<SurfaceTexture>& consumer) {
+        if (consumer.get() != mSurfaceTexture.get()) {
+            mSurfaceTexture = consumer;
 
-            GLenum target = texture->getCurrentTextureTarget();
+            GLenum target = consumer->getCurrentTextureTarget();
             LOG_ALWAYS_FATAL_IF(target != GL_TEXTURE_2D && target != GL_TEXTURE_EXTERNAL_OES,
-                                "set unsupported GLConsumer with target %x", target);
+                                "set unsupported SurfaceTexture with target %x", target);
         }
     }
 
@@ -97,12 +93,11 @@
 
     void detachSurfaceTexture();
 
-    void updateLayer(bool forceFilter, const float* textureTransform, android_dataspace dataspace);
+    void updateLayer(bool forceFilter, const SkMatrix& textureTransform,
+            android_dataspace dataspace, const sk_sp<SkImage>& layerImage);
 
     void destroyLayer();
 
-    Layer::Api getBackingLayerApi() { return mLayerApi; }
-
 private:
     RenderState& mRenderState;
 
@@ -113,17 +108,12 @@
     sk_sp<SkColorFilter> mColorFilter;
     int mAlpha = 255;
     SkBlendMode mMode = SkBlendMode::kSrcOver;
-    sp<GLConsumer> mSurfaceTexture;
+    sp<SurfaceTexture> mSurfaceTexture;
     SkMatrix* mTransform;
     bool mGLContextAttached;
     bool mUpdateTexImage;
 
     Layer* mLayer;
-    Layer::Api mLayerApi;
-    CreateLayerFn mCreateLayerFn;
-
-    void doUpdateTexImage();
-    void doUpdateVkTexImage();
 };
 
 } /* namespace uirenderer */
diff --git a/libs/hwui/DeviceInfo.cpp b/libs/hwui/DeviceInfo.cpp
index a43f58c..b5b87d5 100644
--- a/libs/hwui/DeviceInfo.cpp
+++ b/libs/hwui/DeviceInfo.cpp
@@ -66,12 +66,16 @@
         sDeviceInfo = new DeviceInfo();
         sDeviceInfo->mDisplayInfo = DeviceInfo::queryDisplayInfo();
         sDeviceInfo->mMaxTextureSize = maxTextureSize;
+        sDeviceInfo->queryCompositionPreference(&sDeviceInfo->mTargetDataSpace,
+                                                &sDeviceInfo->mTargetPixelFormat);
     });
 }
 
 void DeviceInfo::load() {
     mDisplayInfo = queryDisplayInfo();
     glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
+    sDeviceInfo->queryCompositionPreference(&sDeviceInfo->mTargetDataSpace,
+                                            &sDeviceInfo->mTargetPixelFormat);
 }
 
 DisplayInfo DeviceInfo::queryDisplayInfo() {
@@ -86,5 +90,17 @@
     return displayInfo;
 }
 
+void DeviceInfo::queryCompositionPreference(ui::Dataspace* dataSpace,
+                                            ui::PixelFormat* pixelFormat) {
+    if (Properties::isolatedProcess) {
+        *dataSpace = ui::Dataspace::V0_SRGB;
+        *pixelFormat = ui::PixelFormat::RGBA_8888;
+    }
+
+    status_t status =
+        SurfaceComposerClient::getCompositionPreference(dataSpace, pixelFormat);
+    LOG_ALWAYS_FATAL_IF(status, "Failed to get composition preference, error %d", status);
+}
+
 } /* namespace uirenderer */
 } /* namespace android */
diff --git a/libs/hwui/DeviceInfo.h b/libs/hwui/DeviceInfo.h
index 297b266..416af17 100644
--- a/libs/hwui/DeviceInfo.h
+++ b/libs/hwui/DeviceInfo.h
@@ -17,6 +17,7 @@
 #define DEVICEINFO_H
 
 #include <ui/DisplayInfo.h>
+#include <ui/GraphicTypes.h>
 
 #include "Extensions.h"
 #include "utils/Macros.h"
@@ -39,6 +40,8 @@
     static void initialize(int maxTextureSize);
 
     int maxTextureSize() const { return mMaxTextureSize; }
+    ui::Dataspace getTargetDataSpace() const { return mTargetDataSpace; }
+    ui::PixelFormat getTargetPixelFormat() const { return mTargetPixelFormat; }
     const DisplayInfo& displayInfo() const { return mDisplayInfo; }
     const Extensions& extensions() const { return mExtensions; }
 
@@ -50,6 +53,9 @@
     static DisplayInfo queryDisplayInfo();
 
 private:
+    static void queryCompositionPreference(ui::Dataspace* dataSpace,
+                                           ui::PixelFormat* pixelFormat);
+
     DeviceInfo() {}
     ~DeviceInfo() {}
 
@@ -58,6 +64,9 @@
     int mMaxTextureSize;
     DisplayInfo mDisplayInfo;
     Extensions mExtensions;
+    // TODO(lpy) Replace below with android_ prefix types.
+    ui::Dataspace mTargetDataSpace;
+    ui::PixelFormat mTargetPixelFormat;
 };
 
 } /* namespace uirenderer */
diff --git a/libs/hwui/EglReadback.cpp b/libs/hwui/EglReadback.cpp
deleted file mode 100644
index 65becf8..0000000
--- a/libs/hwui/EglReadback.cpp
+++ /dev/null
@@ -1,95 +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.
- */
-
-#include "EglReadback.h"
-
-#include "renderthread/EglManager.h"
-
-#include <gui/Surface.h>
-#include <ui/Fence.h>
-#include <ui/GraphicBuffer.h>
-
-namespace android {
-namespace uirenderer {
-
-CopyResult EglReadback::copySurfaceInto(Surface& surface, const Rect& srcRect, SkBitmap* bitmap) {
-    ATRACE_CALL();
-    // Setup the source
-    sp<GraphicBuffer> sourceBuffer;
-    sp<Fence> sourceFence;
-    Matrix4 texTransform;
-    status_t err = surface.getLastQueuedBuffer(&sourceBuffer, &sourceFence, texTransform.data);
-    texTransform.invalidateType();
-    if (err != NO_ERROR) {
-        ALOGW("Failed to get last queued buffer, error = %d", err);
-        return CopyResult::UnknownError;
-    }
-    if (!sourceBuffer.get()) {
-        ALOGW("Surface doesn't have any previously queued frames, nothing to readback from");
-        return CopyResult::SourceEmpty;
-    }
-    if (sourceBuffer->getUsage() & GRALLOC_USAGE_PROTECTED) {
-        ALOGW("Surface is protected, unable to copy from it");
-        return CopyResult::SourceInvalid;
-    }
-    err = sourceFence->wait(500 /* ms */);
-    if (err != NO_ERROR) {
-        ALOGE("Timeout (500ms) exceeded waiting for buffer fence, abandoning readback attempt");
-        return CopyResult::Timeout;
-    }
-
-    return copyGraphicBufferInto(sourceBuffer.get(), texTransform, srcRect, bitmap);
-}
-
-CopyResult EglReadback::copyGraphicBufferInto(GraphicBuffer* graphicBuffer, Matrix4& texTransform,
-                                              const Rect& srcRect, SkBitmap* bitmap) {
-    mRenderThread.requireGlContext();
-    // TODO: Can't use Image helper since it forces GL_TEXTURE_2D usage via
-    // GL_OES_EGL_image, which doesn't work since we need samplerExternalOES
-    // to be able to properly sample from the buffer.
-
-    // Create the EGLImage object that maps the GraphicBuffer
-    EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
-    EGLClientBuffer clientBuffer = (EGLClientBuffer)graphicBuffer->getNativeBuffer();
-    EGLint attrs[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE};
-
-    EGLImageKHR sourceImage = eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
-                                                clientBuffer, attrs);
-
-    if (sourceImage == EGL_NO_IMAGE_KHR) {
-        ALOGW("eglCreateImageKHR failed (%#x)", eglGetError());
-        return CopyResult::UnknownError;
-    }
-
-    uint32_t width = graphicBuffer->getWidth();
-    uint32_t height = graphicBuffer->getHeight();
-    CopyResult copyResult =
-            copyImageInto(sourceImage, texTransform, width, height, srcRect, bitmap);
-
-    eglDestroyImageKHR(display, sourceImage);
-    return copyResult;
-}
-
-CopyResult EglReadback::copyGraphicBufferInto(GraphicBuffer* graphicBuffer, SkBitmap* bitmap) {
-    Rect srcRect;
-    Matrix4 transform;
-    transform.loadScale(1, -1, 1);
-    transform.translate(0, -1);
-    return copyGraphicBufferInto(graphicBuffer, transform, srcRect, bitmap);
-}
-
-}  // namespace uirenderer
-}  // namespace android
diff --git a/libs/hwui/EglReadback.h b/libs/hwui/EglReadback.h
deleted file mode 100644
index e723169..0000000
--- a/libs/hwui/EglReadback.h
+++ /dev/null
@@ -1,50 +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.
- */
-
-#pragma once
-
-#include "Readback.h"
-
-#include "Matrix.h"
-
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-
-namespace android {
-namespace uirenderer {
-
-class EglReadback : public Readback {
-public:
-    virtual CopyResult copySurfaceInto(Surface& surface, const Rect& srcRect,
-                                       SkBitmap* bitmap) override;
-    virtual CopyResult copyGraphicBufferInto(GraphicBuffer* graphicBuffer,
-                                             SkBitmap* bitmap) override;
-
-protected:
-    explicit EglReadback(renderthread::RenderThread& thread) : Readback(thread) {}
-    virtual ~EglReadback() {}
-
-    virtual CopyResult copyImageInto(EGLImageKHR eglImage, const Matrix4& imgTransform,
-                                     int imgWidth, int imgHeight, const Rect& srcRect,
-                                     SkBitmap* bitmap) = 0;
-
-private:
-    CopyResult copyGraphicBufferInto(GraphicBuffer* graphicBuffer, Matrix4& texTransform,
-                                     const Rect& srcRect, SkBitmap* bitmap);
-};
-
-}  // namespace uirenderer
-}  // namespace android
diff --git a/libs/hwui/GlLayer.cpp b/libs/hwui/GlLayer.cpp
deleted file mode 100644
index 432bb85..0000000
--- a/libs/hwui/GlLayer.cpp
+++ /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.
- */
-
-#include "GlLayer.h"
-
-#include "Caches.h"
-#include "RenderNode.h"
-#include "renderstate/RenderState.h"
-
-namespace android {
-namespace uirenderer {
-
-GlLayer::GlLayer(RenderState& renderState, uint32_t layerWidth, uint32_t layerHeight,
-                 sk_sp<SkColorFilter> colorFilter, int alpha, SkBlendMode mode, bool blend)
-        : Layer(renderState, Api::OpenGL, colorFilter, alpha, mode)
-        , caches(Caches::getInstance())
-        , texture(caches) {
-    texture.mWidth = layerWidth;
-    texture.mHeight = layerHeight;
-    texture.blend = blend;
-}
-
-GlLayer::~GlLayer() {
-    // There's a rare possibility that Caches could have been destroyed already
-    // since this method is queued up as a task.
-    // Since this is a reset method, treat this as non-fatal.
-    if (caches.isInitialized() && texture.mId) {
-        texture.deleteTexture();
-    }
-}
-
-void GlLayer::onGlContextLost() {
-    texture.deleteTexture();
-}
-
-void GlLayer::setRenderTarget(GLenum renderTarget) {
-    if (renderTarget != getRenderTarget()) {
-        // new render target: bind with new target, and update filter/wrap
-        texture.mTarget = renderTarget;
-        if (texture.mId) {
-            caches.textureState().bindTexture(texture.target(), texture.mId);
-        }
-        texture.setFilter(GL_NEAREST, false, true);
-        texture.setWrap(GL_CLAMP_TO_EDGE, false, true);
-    }
-}
-
-void GlLayer::generateTexture() {
-    if (!texture.mId) {
-        glGenTextures(1, &texture.mId);
-    }
-}
-
-};  // namespace uirenderer
-};  // namespace android
diff --git a/libs/hwui/GlLayer.h b/libs/hwui/GlLayer.h
deleted file mode 100644
index 9f70fda..0000000
--- a/libs/hwui/GlLayer.h
+++ /dev/null
@@ -1,75 +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.
- */
-
-#pragma once
-
-#include "Layer.h"
-
-#include "Texture.h"
-
-namespace android {
-namespace uirenderer {
-
-// Forward declarations
-class Caches;
-
-/**
- * A layer has dimensions and is backed by an OpenGL texture or FBO.
- */
-class GlLayer : public Layer {
-public:
-    GlLayer(RenderState& renderState, uint32_t layerWidth, uint32_t layerHeight,
-            sk_sp<SkColorFilter> colorFilter, int alpha, SkBlendMode mode, bool blend);
-    virtual ~GlLayer();
-
-    uint32_t getWidth() const override { return texture.mWidth; }
-
-    uint32_t getHeight() const override { return texture.mHeight; }
-
-    void setSize(uint32_t width, uint32_t height) override {
-        texture.updateLayout(width, height, texture.internalFormat(), texture.format(),
-                             texture.target());
-    }
-
-    void setBlend(bool blend) override { texture.blend = blend; }
-
-    bool isBlend() const override { return texture.blend; }
-
-    inline GLuint getTextureId() const { return texture.id(); }
-
-    inline GLenum getRenderTarget() const { return texture.target(); }
-
-    void setRenderTarget(GLenum renderTarget);
-
-    void generateTexture();
-
-    /**
-     * Lost the GL context but the layer is still around, mark it invalid internally
-     * so the dtor knows not to do any GL work
-     */
-    void onGlContextLost();
-
-private:
-    Caches& caches;
-
-    /**
-     * The texture backing this layer.
-     */
-    Texture texture;
-};  // struct GlLayer
-
-};  // namespace uirenderer
-};  // namespace android
diff --git a/libs/hwui/GpuMemoryTracker.cpp b/libs/hwui/GpuMemoryTracker.cpp
index 612bfde..a9a7af8 100644
--- a/libs/hwui/GpuMemoryTracker.cpp
+++ b/libs/hwui/GpuMemoryTracker.cpp
@@ -14,7 +14,6 @@
  * limitations under the License.
  */
 
-#include "Texture.h"
 #include "utils/StringUtils.h"
 
 #include <GpuMemoryTracker.h>
@@ -117,22 +116,6 @@
             ATRACE_INT(buf, stats.count);
         }
     }
-
-    std::vector<const Texture*> freeList;
-    for (const auto& obj : gObjectSet) {
-        if (obj->objectType() == GpuObjectType::Texture) {
-            const Texture* texture = static_cast<Texture*>(obj);
-            if (texture->cleanup) {
-                ALOGE("Leaked texture marked for cleanup! id=%u, size %ux%u", texture->id(),
-                      texture->width(), texture->height());
-                freeList.push_back(texture);
-            }
-        }
-    }
-    for (auto& texture : freeList) {
-        const_cast<Texture*>(texture)->deleteTexture();
-        delete texture;
-    }
 }
 
 }  // namespace uirenderer
diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp
index fb8f033..cc95051 100644
--- a/libs/hwui/Layer.cpp
+++ b/libs/hwui/Layer.cpp
@@ -17,17 +17,16 @@
 #include "Layer.h"
 
 #include "renderstate/RenderState.h"
+#include "utils/Color.h"
 
 #include <SkToSRGBColorFilter.h>
 
 namespace android {
 namespace uirenderer {
 
-Layer::Layer(RenderState& renderState, Api api, sk_sp<SkColorFilter> colorFilter, int alpha,
-             SkBlendMode mode)
-        : GpuMemoryTracker(GpuObjectType::Layer)
-        , mRenderState(renderState)
-        , mApi(api)
+Layer::Layer(RenderState& renderState, sk_sp<SkColorFilter> colorFilter, int alpha,
+        SkBlendMode mode)
+        : mRenderState(renderState)
         , mColorFilter(colorFilter)
         , alpha(alpha)
         , mode(mode) {
@@ -36,6 +35,8 @@
     incStrong(nullptr);
     buildColorSpaceWithFilter();
     renderState.registerLayer(this);
+    texTransform.setIdentity();
+    transform.setIdentity();
 }
 
 Layer::~Layer() {
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index 31878ac..6f07a43 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -16,15 +16,15 @@
 
 #pragma once
 
-#include <GpuMemoryTracker.h>
 #include <utils/RefBase.h>
 
 #include <SkBlendMode.h>
 #include <SkColorFilter.h>
 #include <SkColorSpace.h>
 #include <SkPaint.h>
-
-#include "Matrix.h"
+#include <SkImage.h>
+#include <SkMatrix.h>
+#include <system/graphics.h>
 
 namespace android {
 namespace uirenderer {
@@ -38,26 +38,21 @@
 /**
  * A layer has dimensions and is backed by a backend specific texture or framebuffer.
  */
-class Layer : public VirtualLightRefBase, GpuMemoryTracker {
+class Layer : public VirtualLightRefBase {
 public:
-    enum class Api {
-        OpenGL = 0,
-        Vulkan = 1,
-    };
-
-    Api getApi() const { return mApi; }
+    Layer(RenderState& renderState, sk_sp<SkColorFilter>, int alpha, SkBlendMode mode);
 
     ~Layer();
 
-    virtual uint32_t getWidth() const = 0;
+    uint32_t getWidth() const { return mWidth; }
 
-    virtual uint32_t getHeight() const = 0;
+    uint32_t getHeight() const { return mHeight; }
 
-    virtual void setSize(uint32_t width, uint32_t height) = 0;
+    void setSize(uint32_t width, uint32_t height) { mWidth = width; mHeight = height; }
 
-    virtual void setBlend(bool blend) = 0;
+    void setBlend(bool blend) { mBlend = blend; }
 
-    virtual bool isBlend() const = 0;
+    bool isBlend() const { return mBlend; }
 
     inline void setForceFilter(bool forceFilter) { this->forceFilter = forceFilter; }
 
@@ -84,9 +79,9 @@
 
     inline sk_sp<SkColorFilter> getColorSpaceWithFilter() const { return mColorSpaceWithFilter; }
 
-    inline mat4& getTexTransform() { return texTransform; }
+    inline SkMatrix& getTexTransform() { return texTransform; }
 
-    inline mat4& getTransform() { return transform; }
+    inline SkMatrix& getTransform() { return transform; }
 
     /**
      * Posts a decStrong call to the appropriate thread.
@@ -94,16 +89,17 @@
      */
     void postDecStrong();
 
+    inline void setImage(const sk_sp<SkImage>& image) { this->layerImage = image; }
+
+    inline sk_sp<SkImage> getImage() const { return this->layerImage; }
+
 protected:
-    Layer(RenderState& renderState, Api api, sk_sp<SkColorFilter>, int alpha, SkBlendMode mode);
 
     RenderState& mRenderState;
 
 private:
     void buildColorSpaceWithFilter();
 
-    Api mApi;
-
     /**
      * Color filter used to draw this layer. Optional.
      */
@@ -137,12 +133,32 @@
     /**
      * Optional texture coordinates transform.
      */
-    mat4 texTransform;
+    SkMatrix texTransform;
 
     /**
      * Optional transform.
      */
-    mat4 transform;
+    SkMatrix transform;
+
+    /**
+     * An image backing the layer.
+     */
+    sk_sp<SkImage> layerImage;
+
+    /**
+     * layer width.
+     */
+    uint32_t mWidth = 0;
+
+    /**
+     * layer height.
+     */
+    uint32_t mHeight = 0;
+
+    /**
+     * enable blending
+     */
+    bool mBlend = false;
 
 };  // struct Layer
 
diff --git a/libs/hwui/LayerUpdateQueue.h b/libs/hwui/LayerUpdateQueue.h
index b14b80c..6857999 100644
--- a/libs/hwui/LayerUpdateQueue.h
+++ b/libs/hwui/LayerUpdateQueue.h
@@ -19,6 +19,7 @@
 
 #include <utils/StrongPointer.h>
 #include "Rect.h"
+#include "RenderNode.h"
 #include "utils/Macros.h"
 
 #include <unordered_map>
diff --git a/libs/hwui/PixelBuffer.cpp b/libs/hwui/PixelBuffer.cpp
deleted file mode 100644
index 910a988..0000000
--- a/libs/hwui/PixelBuffer.cpp
+++ /dev/null
@@ -1,156 +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.
- */
-
-#include "PixelBuffer.h"
-
-#include "Debug.h"
-#include "Extensions.h"
-#include "Properties.h"
-#include "renderstate/RenderState.h"
-#include "utils/GLUtils.h"
-
-#include <utils/Log.h>
-
-namespace android {
-namespace uirenderer {
-
-///////////////////////////////////////////////////////////////////////////////
-// CPU pixel buffer
-///////////////////////////////////////////////////////////////////////////////
-
-class CpuPixelBuffer : public PixelBuffer {
-public:
-    CpuPixelBuffer(GLenum format, uint32_t width, uint32_t height);
-
-    uint8_t* map(AccessMode mode = kAccessMode_ReadWrite) override;
-
-    void upload(uint32_t x, uint32_t y, uint32_t width, uint32_t height, int offset) override;
-
-protected:
-    void unmap() override;
-
-private:
-    std::unique_ptr<uint8_t[]> mBuffer;
-};
-
-CpuPixelBuffer::CpuPixelBuffer(GLenum format, uint32_t width, uint32_t height)
-        : PixelBuffer(format, width, height)
-        , mBuffer(new uint8_t[width * height * formatSize(format)]) {}
-
-uint8_t* CpuPixelBuffer::map(AccessMode mode) {
-    if (mAccessMode == kAccessMode_None) {
-        mAccessMode = mode;
-    }
-    return mBuffer.get();
-}
-
-void CpuPixelBuffer::unmap() {
-    mAccessMode = kAccessMode_None;
-}
-
-void CpuPixelBuffer::upload(uint32_t x, uint32_t y, uint32_t width, uint32_t height, int offset) {
-    glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, mFormat, GL_UNSIGNED_BYTE,
-                    &mBuffer[offset]);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// GPU pixel buffer
-///////////////////////////////////////////////////////////////////////////////
-
-class GpuPixelBuffer : public PixelBuffer {
-public:
-    GpuPixelBuffer(GLenum format, uint32_t width, uint32_t height);
-    ~GpuPixelBuffer();
-
-    uint8_t* map(AccessMode mode = kAccessMode_ReadWrite) override;
-
-    void upload(uint32_t x, uint32_t y, uint32_t width, uint32_t height, int offset) override;
-
-protected:
-    void unmap() override;
-
-private:
-    GLuint mBuffer;
-    uint8_t* mMappedPointer;
-    Caches& mCaches;
-};
-
-GpuPixelBuffer::GpuPixelBuffer(GLenum format, uint32_t width, uint32_t height)
-        : PixelBuffer(format, width, height)
-        , mMappedPointer(nullptr)
-        , mCaches(Caches::getInstance()) {
-    glGenBuffers(1, &mBuffer);
-
-    mCaches.pixelBufferState().bind(mBuffer);
-    glBufferData(GL_PIXEL_UNPACK_BUFFER, getSize(), nullptr, GL_DYNAMIC_DRAW);
-    mCaches.pixelBufferState().unbind();
-}
-
-GpuPixelBuffer::~GpuPixelBuffer() {
-    glDeleteBuffers(1, &mBuffer);
-}
-
-uint8_t* GpuPixelBuffer::map(AccessMode mode) {
-    if (mAccessMode == kAccessMode_None) {
-        mCaches.pixelBufferState().bind(mBuffer);
-        mMappedPointer = (uint8_t*)glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, getSize(), mode);
-        if (CC_UNLIKELY(!mMappedPointer)) {
-            GLUtils::dumpGLErrors();
-            LOG_ALWAYS_FATAL("Failed to map PBO");
-        }
-        mAccessMode = mode;
-        mCaches.pixelBufferState().unbind();
-    }
-
-    return mMappedPointer;
-}
-
-void GpuPixelBuffer::unmap() {
-    if (mAccessMode != kAccessMode_None) {
-        if (mMappedPointer) {
-            mCaches.pixelBufferState().bind(mBuffer);
-            GLboolean status = glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
-            if (status == GL_FALSE) {
-                ALOGE("Corrupted GPU pixel buffer");
-            }
-        }
-        mAccessMode = kAccessMode_None;
-        mMappedPointer = nullptr;
-    }
-}
-
-void GpuPixelBuffer::upload(uint32_t x, uint32_t y, uint32_t width, uint32_t height, int offset) {
-    // If the buffer is not mapped, unmap() will not bind it
-    mCaches.pixelBufferState().bind(mBuffer);
-    unmap();
-    glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, mFormat, GL_UNSIGNED_BYTE,
-                    reinterpret_cast<void*>(offset));
-    mCaches.pixelBufferState().unbind();
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Factory
-///////////////////////////////////////////////////////////////////////////////
-
-PixelBuffer* PixelBuffer::create(GLenum format, uint32_t width, uint32_t height, BufferType type) {
-    if (type == kBufferType_Auto && Caches::getInstance().gpuPixelBuffersEnabled) {
-        return new GpuPixelBuffer(format, width, height);
-    }
-    return new CpuPixelBuffer(format, width, height);
-}
-
-};  // namespace uirenderer
-};  // namespace android
diff --git a/libs/hwui/PixelBuffer.h b/libs/hwui/PixelBuffer.h
deleted file mode 100644
index e7e341b..0000000
--- a/libs/hwui/PixelBuffer.h
+++ /dev/null
@@ -1,198 +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.
- */
-
-#ifndef ANDROID_HWUI_PIXEL_BUFFER_H
-#define ANDROID_HWUI_PIXEL_BUFFER_H
-
-#include <GLES3/gl3.h>
-
-#include <log/log.h>
-
-namespace android {
-namespace uirenderer {
-
-/**
- * Represents a pixel buffer. A pixel buffer will be backed either by a
- * PBO on OpenGL ES 3.0 and higher or by an array of uint8_t on other
- * versions. If the buffer is backed by a PBO it will of type
- * GL_PIXEL_UNPACK_BUFFER.
- *
- * To read from or write into a PixelBuffer you must first map the
- * buffer using the map(AccessMode) method. This method returns a
- * pointer to the beginning of the buffer.
- *
- * Before the buffer can be used by the GPU, for instance to upload
- * a texture, you must first unmap the buffer. To do so, call the
- * unmap() method.
- *
- * Mapping and unmapping a PixelBuffer can have the side effect of
- * changing the currently active GL_PIXEL_UNPACK_BUFFER. It is
- * therefore recommended to call Caches::unbindPixelbuffer() after
- * using a PixelBuffer to upload to a texture.
- */
-class PixelBuffer {
-public:
-    enum BufferType { kBufferType_Auto, kBufferType_CPU };
-
-    enum AccessMode {
-        kAccessMode_None = 0,
-        kAccessMode_Read = GL_MAP_READ_BIT,
-        kAccessMode_Write = GL_MAP_WRITE_BIT,
-        kAccessMode_ReadWrite = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT
-    };
-
-    /**
-     * Creates a new PixelBuffer object with the specified format and
-     * dimensions. The buffer is immediately allocated.
-     *
-     * The buffer type specifies how the buffer should be allocated.
-     * By default this method will automatically choose whether to allocate
-     * a CPU or GPU buffer.
-     */
-    static PixelBuffer* create(GLenum format, uint32_t width, uint32_t height,
-                               BufferType type = kBufferType_Auto);
-
-    virtual ~PixelBuffer() {}
-
-    /**
-     * Returns the format of this render buffer.
-     */
-    GLenum getFormat() const { return mFormat; }
-
-    /**
-     * Maps this before with the specified access mode. This method
-     * returns a pointer to the region of memory where the buffer was
-     * mapped.
-     *
-     * If the buffer is already mapped when this method is invoked,
-     * this method will return the previously mapped pointer. The
-     * access mode can only be changed by calling unmap() first.
-     *
-     * The specified access mode cannot be kAccessMode_None.
-     */
-    virtual uint8_t* map(AccessMode mode = kAccessMode_ReadWrite) = 0;
-
-    /**
-     * Returns the current access mode for this buffer. If the buffer
-     * is not mapped, this method returns kAccessMode_None.
-     */
-    AccessMode getAccessMode() const { return mAccessMode; }
-
-    /**
-     * Upload the specified rectangle of this pixel buffer as a
-     * GL_TEXTURE_2D texture. Calling this method will trigger
-     * an unmap() if necessary.
-     */
-    virtual void upload(uint32_t x, uint32_t y, uint32_t width, uint32_t height, int offset) = 0;
-
-    /**
-     * Upload the specified rectangle of this pixel buffer as a
-     * GL_TEXTURE_2D texture. Calling this method will trigger
-     * an unmap() if necessary.
-     *
-     * This is a convenience function provided to save callers the
-     * trouble of computing the offset parameter.
-     */
-    void upload(uint32_t x, uint32_t y, uint32_t width, uint32_t height) {
-        upload(x, y, width, height, getOffset(x, y));
-    }
-
-    /**
-     * Returns the width of the render buffer in pixels.
-     */
-    uint32_t getWidth() const { return mWidth; }
-
-    /**
-     * Returns the height of the render buffer in pixels.
-     */
-    uint32_t getHeight() const { return mHeight; }
-
-    /**
-     * Returns the size of this pixel buffer in bytes.
-     */
-    uint32_t getSize() const { return mWidth * mHeight * formatSize(mFormat); }
-
-    /**
-     * Returns the offset of a pixel in this pixel buffer, in bytes.
-     */
-    uint32_t getOffset(uint32_t x, uint32_t y) const {
-        return (y * mWidth + x) * formatSize(mFormat);
-    }
-
-    /**
-     * Returns the number of bytes per pixel in the specified format.
-     *
-     * Supported formats:
-     *      GL_ALPHA
-     *      GL_RGBA
-     */
-    static uint32_t formatSize(GLenum format) {
-        switch (format) {
-            case GL_ALPHA:
-                return 1;
-            case GL_RGBA:
-                return 4;
-        }
-        return 0;
-    }
-
-    /**
-     * Returns the alpha channel offset in the specified format.
-     *
-     * Supported formats:
-     *      GL_ALPHA
-     *      GL_RGBA
-     */
-    static uint32_t formatAlphaOffset(GLenum format) {
-        switch (format) {
-            case GL_ALPHA:
-                return 0;
-            case GL_RGBA:
-                return 3;
-        }
-
-        ALOGE("unsupported format: %d", format);
-        return 0;
-    }
-
-protected:
-    /**
-     * Creates a new render buffer in the specified format and dimensions.
-     * The format must be GL_ALPHA or GL_RGBA.
-     */
-    PixelBuffer(GLenum format, uint32_t width, uint32_t height)
-            : mFormat(format), mWidth(width), mHeight(height), mAccessMode(kAccessMode_None) {}
-
-    /**
-     * Unmaps this buffer, if needed. After the buffer is unmapped,
-     * the pointer previously returned by map() becomes invalid and
-     * should not be used.
-     */
-    virtual void unmap() = 0;
-
-    GLenum mFormat;
-
-    uint32_t mWidth;
-    uint32_t mHeight;
-
-    AccessMode mAccessMode;
-
-};  // class PixelBuffer
-
-};  // namespace uirenderer
-};  // namespace android
-
-#endif  // ANDROID_HWUI_PIXEL_BUFFER_H
diff --git a/libs/hwui/Readback.cpp b/libs/hwui/Readback.cpp
new file mode 100644
index 0000000..80f2b57
--- /dev/null
+++ b/libs/hwui/Readback.cpp
@@ -0,0 +1,287 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "Readback.h"
+
+#include "pipeline/skia/LayerDrawable.h"
+#include "renderthread/EglManager.h"
+#include "renderthread/VulkanManager.h"
+
+#include <SkToSRGBColorFilter.h>
+#include <gui/Surface.h>
+#include <ui/Fence.h>
+#include <ui/GraphicBuffer.h>
+#include "DeferredLayerUpdater.h"
+#include "Properties.h"
+#include "hwui/Bitmap.h"
+#include "utils/Color.h"
+#include "utils/MathUtils.h"
+
+using namespace android::uirenderer::renderthread;
+
+namespace android {
+namespace uirenderer {
+
+CopyResult Readback::copySurfaceInto(Surface& surface, const Rect& srcRect, SkBitmap* bitmap) {
+    ATRACE_CALL();
+    // Setup the source
+    sp<GraphicBuffer> sourceBuffer;
+    sp<Fence> sourceFence;
+    Matrix4 texTransform;
+    status_t err = surface.getLastQueuedBuffer(&sourceBuffer, &sourceFence, texTransform.data);
+    texTransform.invalidateType();
+    if (err != NO_ERROR) {
+        ALOGW("Failed to get last queued buffer, error = %d", err);
+        return CopyResult::UnknownError;
+    }
+    if (!sourceBuffer.get()) {
+        ALOGW("Surface doesn't have any previously queued frames, nothing to readback from");
+        return CopyResult::SourceEmpty;
+    }
+    if (sourceBuffer->getUsage() & GRALLOC_USAGE_PROTECTED) {
+        ALOGW("Surface is protected, unable to copy from it");
+        return CopyResult::SourceInvalid;
+    }
+    err = sourceFence->wait(500 /* ms */);
+    if (err != NO_ERROR) {
+        ALOGE("Timeout (500ms) exceeded waiting for buffer fence, abandoning readback attempt");
+        return CopyResult::Timeout;
+    }
+    if (!sourceBuffer.get()) {
+        return CopyResult::UnknownError;
+    }
+
+    sk_sp<SkColorSpace> colorSpace =
+            DataSpaceToColorSpace(static_cast<android_dataspace>(surface.getBuffersDataSpace()));
+    sk_sp<SkColorFilter> colorSpaceFilter;
+    if (colorSpace && !colorSpace->isSRGB()) {
+        colorSpaceFilter = SkToSRGBColorFilter::Make(colorSpace);
+    }
+    sk_sp<SkImage> image = SkImage::MakeFromAHardwareBuffer(
+            reinterpret_cast<AHardwareBuffer*>(sourceBuffer.get()), kPremul_SkAlphaType);
+    return copyImageInto(image, colorSpaceFilter, texTransform, srcRect, bitmap);
+}
+
+CopyResult Readback::copyHWBitmapInto(Bitmap* hwBitmap, SkBitmap* bitmap) {
+    LOG_ALWAYS_FATAL_IF(!hwBitmap->isHardware());
+
+    Rect srcRect;
+    Matrix4 transform;
+    transform.loadScale(1, -1, 1);
+    transform.translate(0, -1);
+
+    // TODO: Try to take and reuse the image inside HW bitmap with "hwBitmap->makeImage".
+    // TODO: When this was attempted, it resulted in instability.
+    sk_sp<SkColorFilter> colorSpaceFilter;
+    sk_sp<SkColorSpace> colorSpace = hwBitmap->info().refColorSpace();
+    if (colorSpace && !colorSpace->isSRGB()) {
+        colorSpaceFilter = SkToSRGBColorFilter::Make(colorSpace);
+    }
+    sk_sp<SkImage> image = SkImage::MakeFromAHardwareBuffer(
+            reinterpret_cast<AHardwareBuffer*>(hwBitmap->graphicBuffer()), kPremul_SkAlphaType);
+
+    // HW Bitmap currently can only attach to a GraphicBuffer with PIXEL_FORMAT_RGBA_8888 format
+    // and SRGB color space. ImageDecoder can create a new HW Bitmap with non-SRGB color space: for
+    // example see android.graphics.cts.BitmapColorSpaceTest#testEncodeP3hardware test.
+    return copyImageInto(image, colorSpaceFilter, transform, srcRect, bitmap);
+}
+
+CopyResult Readback::copyLayerInto(DeferredLayerUpdater* deferredLayer, SkBitmap* bitmap) {
+    if (!mRenderThread.getGrContext()) {
+        return CopyResult::UnknownError;
+    }
+
+    // acquire most recent buffer for drawing
+    deferredLayer->updateTexImage();
+    deferredLayer->apply();
+    const SkRect dstRect = SkRect::MakeIWH(bitmap->width(), bitmap->height());
+    CopyResult copyResult = CopyResult::UnknownError;
+    Layer* layer = deferredLayer->backingLayer();
+    if (layer) {
+        if (copyLayerInto(layer, nullptr, &dstRect, bitmap)) {
+            copyResult = CopyResult::Success;
+        }
+    }
+    return copyResult;
+}
+
+CopyResult Readback::copyImageInto(const sk_sp<SkImage>& image,
+                                   sk_sp<SkColorFilter>& colorSpaceFilter, Matrix4& texTransform,
+                                   const Rect& srcRect, SkBitmap* bitmap) {
+    if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaGL) {
+        mRenderThread.requireGlContext();
+    } else {
+        mRenderThread.vulkanManager().initialize();
+    }
+    if (!image.get()) {
+        return CopyResult::UnknownError;
+    }
+    int imgWidth = image->width();
+    int imgHeight = image->height();
+    sk_sp<GrContext> grContext = sk_ref_sp(mRenderThread.getGrContext());
+
+    if (bitmap->colorType() == kRGBA_F16_SkColorType &&
+        !grContext->colorTypeSupportedAsSurface(bitmap->colorType())) {
+        ALOGW("Can't copy surface into bitmap, RGBA_F16 config is not supported");
+        return CopyResult::DestinationInvalid;
+    }
+
+    CopyResult copyResult = CopyResult::UnknownError;
+
+    int displayedWidth = imgWidth, displayedHeight = imgHeight;
+    // If this is a 90 or 270 degree rotation we need to swap width/height to get the device
+    // size.
+    if (texTransform[Matrix4::kSkewX] >= 0.5f || texTransform[Matrix4::kSkewX] <= -0.5f) {
+        std::swap(displayedWidth, displayedHeight);
+    }
+    SkRect skiaDestRect = SkRect::MakeWH(bitmap->width(), bitmap->height());
+    SkRect skiaSrcRect = srcRect.toSkRect();
+    if (skiaSrcRect.isEmpty()) {
+        skiaSrcRect = SkRect::MakeIWH(displayedWidth, displayedHeight);
+    }
+    bool srcNotEmpty = skiaSrcRect.intersect(SkRect::MakeIWH(displayedWidth, displayedHeight));
+    if (!srcNotEmpty) {
+        return copyResult;
+    }
+
+    // See Readback::copyLayerInto for an overview of color space conversion.
+    // HW Bitmap are allowed to be in a non-SRGB color space (for example coming from ImageDecoder).
+    // For Surface and HW Bitmap readback flows we pass colorSpaceFilter, which does the conversion.
+    // TextureView readback is using Layer::setDataSpace, which creates a SkColorFilter internally.
+    Layer layer(mRenderThread.renderState(), colorSpaceFilter, 255, SkBlendMode::kSrc);
+    bool disableFilter = MathUtils::areEqual(skiaSrcRect.width(), skiaDestRect.width()) &&
+                         MathUtils::areEqual(skiaSrcRect.height(), skiaDestRect.height());
+    layer.setForceFilter(!disableFilter);
+    layer.setSize(displayedWidth, displayedHeight);
+    texTransform.copyTo(layer.getTexTransform());
+    layer.setImage(image);
+    if (copyLayerInto(&layer, &skiaSrcRect, &skiaDestRect, bitmap)) {
+        copyResult = CopyResult::Success;
+    }
+
+    return copyResult;
+}
+
+bool Readback::copyLayerInto(Layer* layer, const SkRect* srcRect, const SkRect* dstRect,
+                             SkBitmap* bitmap) {
+    /*
+     * In the past only TextureView readback was setting the temporary surface color space to null.
+     * Now all 3 readback flows are drawing into a SkSurface with null color space.
+     * At readback there are 3 options to convert the source image color space to the destination
+     * color space requested in "bitmap->info().colorSpace()":
+     * 1. Set color space for temporary surface render target to null (disables color management),
+     *    colorspace tag from source SkImage is ignored by Skia,
+     *    convert SkImage to SRGB at draw time with SkColorFilter/SkToSRGBColorFilter,
+     *    do a readback from temporary SkSurface to a temporary SRGB SkBitmap "bitmap2",
+     *    read back from SRGB "bitmap2" into non-SRGB "bitmap" which will do a CPU color conversion.
+     *
+     * 2. Set color space for temporary surface render target to SRGB (not nullptr),
+     *    colorspace tag on the source SkImage is used by Skia to enable conversion,
+     *    convert SkImage to SRGB at draw time with drawImage (no filters),
+     *    do a readback from temporary SkSurface, which will do a color conversion from SRGB to
+     *    bitmap->info().colorSpace() on the CPU.
+     *
+     * 3. Set color space for temporary surface render target to bitmap->info().colorSpace(),
+     *    colorspace tag on the source SkImage is used by Skia to enable conversion,
+     *    convert SkImage to bitmap->info().colorSpace() at draw time with drawImage (no filters),
+     *    do a readback from SkSurface, which will not do any color conversion, because
+     *    surface was created with the same color space as the "bitmap".
+     *
+     * Option 1 is used for all readback flows.
+     * Options 2 and 3 are new, because skia added support for non-SRGB render targets without
+     * linear blending.
+     * TODO: evaluate if options 2 or 3 for color space conversion are better.
+     */
+
+    // drop the colorSpace from the temporary surface.
+    SkImageInfo surfaceInfo = bitmap->info().makeColorSpace(nullptr);
+
+    /* This intermediate surface is present to work around a bug in SwiftShader that
+     * prevents us from reading the contents of the layer's texture directly. The
+     * workaround involves first rendering that texture into an intermediate buffer and
+     * then reading from the intermediate buffer into the bitmap.
+     * Another reason to render in an offscreen buffer is to scale and to avoid an issue b/62262733
+     * with reading incorrect data from EGLImage backed SkImage (likely a driver bug).
+     */
+    sk_sp<SkSurface> tmpSurface = SkSurface::MakeRenderTarget(mRenderThread.getGrContext(),
+                                                              SkBudgeted::kYes, surfaceInfo);
+
+    if (!tmpSurface.get()) {
+        surfaceInfo = surfaceInfo.makeColorType(SkColorType::kN32_SkColorType);
+        tmpSurface = SkSurface::MakeRenderTarget(mRenderThread.getGrContext(), SkBudgeted::kYes,
+                                                 surfaceInfo);
+        if (!tmpSurface.get()) {
+            ALOGW("Unable to readback GPU contents into the provided bitmap");
+            return false;
+        }
+    }
+
+    if (skiapipeline::LayerDrawable::DrawLayer(mRenderThread.getGrContext(),
+                                               tmpSurface->getCanvas(), layer, srcRect, dstRect,
+                                               false)) {
+        // If bitmap->info().colorSpace() is non-SRGB, convert the data from SRGB to non-SRGB on
+        // CPU. We can't just pass bitmap->info() to SkSurface::readPixels, because "tmpSurface" has
+        // disabled color conversion.
+        SkColorSpace* destColorSpace = bitmap->info().colorSpace();
+        SkBitmap tempSRGBBitmap;
+        SkBitmap tmpN32Bitmap;
+        SkBitmap* bitmapInSRGB;
+        if (destColorSpace && !destColorSpace->isSRGB()) {
+            tempSRGBBitmap.allocPixels(bitmap->info().makeColorSpace(SkColorSpace::MakeSRGB()));
+            bitmapInSRGB = &tempSRGBBitmap;  // Need to convert latter from SRGB to non-SRGB.
+        } else {
+            bitmapInSRGB = bitmap;  // No need for color conversion - write directly into output.
+        }
+        bool success = false;
+
+        // TODO: does any of the readbacks below clamp F16 exSRGB?
+        // Readback into a SRGB SkBitmap.
+        if (tmpSurface->readPixels(bitmapInSRGB->info(), bitmapInSRGB->getPixels(),
+                                   bitmapInSRGB->rowBytes(), 0, 0)) {
+            success = true;
+        } else {
+            // if we fail to readback from the GPU directly (e.g. 565) then we attempt to read into
+            // 8888 and then convert that into the destination format before giving up.
+            SkImageInfo bitmapInfo =
+                    SkImageInfo::MakeN32(bitmap->width(), bitmap->height(), bitmap->alphaType(),
+                                         SkColorSpace::MakeSRGB());
+            if (tmpN32Bitmap.tryAllocPixels(bitmapInfo) &&
+                tmpSurface->readPixels(bitmapInfo, tmpN32Bitmap.getPixels(),
+                                       tmpN32Bitmap.rowBytes(), 0, 0)) {
+                success = true;
+                bitmapInSRGB = &tmpN32Bitmap;
+            }
+        }
+
+        if (success) {
+            if (bitmapInSRGB != bitmap) {
+                // Convert from SRGB to non-SRGB color space if needed. Convert from N32 to
+                // destination bitmap color format if needed.
+                if (!bitmapInSRGB->readPixels(bitmap->info(), bitmap->getPixels(),
+                                              bitmap->rowBytes(), 0, 0)) {
+                    return false;
+                }
+            }
+            bitmap->notifyPixelsChanged();
+            return true;
+        }
+    }
+
+    return false;
+}
+
+} /* namespace uirenderer */
+} /* namespace android */
diff --git a/libs/hwui/Readback.h b/libs/hwui/Readback.h
index ad3a8b6..d9e10ce 100644
--- a/libs/hwui/Readback.h
+++ b/libs/hwui/Readback.h
@@ -16,16 +16,21 @@
 
 #pragma once
 
+#include "Matrix.h"
 #include "Rect.h"
 #include "renderthread/RenderThread.h"
 
 #include <SkBitmap.h>
 
 namespace android {
+class Bitmap;
 class GraphicBuffer;
 class Surface;
 namespace uirenderer {
 
+class DeferredLayerUpdater;
+class Layer;
+
 // Keep in sync with PixelCopy.java codes
 enum class CopyResult {
     Success = 0,
@@ -38,15 +43,22 @@
 
 class Readback {
 public:
+    explicit Readback(renderthread::RenderThread& thread) : mRenderThread(thread) {}
     /**
      * Copies the surface's most recently queued buffer into the provided bitmap.
      */
-    virtual CopyResult copySurfaceInto(Surface& surface, const Rect& srcRect, SkBitmap* bitmap) = 0;
-    virtual CopyResult copyGraphicBufferInto(GraphicBuffer* graphicBuffer, SkBitmap* bitmap) = 0;
+    CopyResult copySurfaceInto(Surface& surface, const Rect& srcRect, SkBitmap* bitmap);
 
-protected:
-    explicit Readback(renderthread::RenderThread& thread) : mRenderThread(thread) {}
-    virtual ~Readback() {}
+    CopyResult copyHWBitmapInto(Bitmap* hwBitmap, SkBitmap* bitmap);
+
+    CopyResult copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap);
+
+private:
+    CopyResult copyImageInto(const sk_sp<SkImage>& image, sk_sp<SkColorFilter>& colorSpaceFilter,
+                             Matrix4& texTransform, const Rect& srcRect, SkBitmap* bitmap);
+
+    bool copyLayerInto(Layer* layer, const SkRect* srcRect, const SkRect* dstRect,
+                       SkBitmap* bitmap);
 
     renderthread::RenderThread& mRenderThread;
 };
diff --git a/libs/hwui/RenderProperties.h b/libs/hwui/RenderProperties.h
index 0766e3b..7966845 100644
--- a/libs/hwui/RenderProperties.h
+++ b/libs/hwui/RenderProperties.h
@@ -16,7 +16,6 @@
 
 #pragma once
 
-#include "Caches.h"
 #include "DeviceInfo.h"
 #include "Outline.h"
 #include "Rect.h"
diff --git a/libs/hwui/ResourceCache.cpp b/libs/hwui/ResourceCache.cpp
index 464a58d..65bee47 100644
--- a/libs/hwui/ResourceCache.cpp
+++ b/libs/hwui/ResourceCache.cpp
@@ -15,7 +15,6 @@
  */
 
 #include "ResourceCache.h"
-#include "Caches.h"
 
 namespace android {
 
@@ -112,13 +111,9 @@
     ResourceReference* ref = index >= 0 ? mCache->valueAt(index) : nullptr;
     if (ref == nullptr) {
         // If we're not tracking this resource, just delete it
-        if (Caches::hasInstance()) {
-            // DEAD CODE
-        } else {
-            // A Res_png_9patch is actually an array of byte that's larger
-            // than sizeof(Res_png_9patch). It must be freed as an array.
-            delete[](int8_t*) resource;
-        }
+        // A Res_png_9patch is actually an array of byte that's larger
+        // than sizeof(Res_png_9patch). It must be freed as an array.
+        delete[](int8_t*) resource;
         return;
     }
     ref->destroyed = true;
@@ -135,14 +130,10 @@
     if (ref->destroyed) {
         switch (ref->resourceType) {
             case kNinePatch: {
-                if (Caches::hasInstance()) {
-                    // DEAD CODE
-                } else {
-                    // A Res_png_9patch is actually an array of byte that's larger
-                    // than sizeof(Res_png_9patch). It must be freed as an array.
-                    int8_t* patch = (int8_t*)resource;
-                    delete[] patch;
-                }
+                // A Res_png_9patch is actually an array of byte that's larger
+                // than sizeof(Res_png_9patch). It must be freed as an array.
+                int8_t* patch = (int8_t*)resource;
+                delete[] patch;
             } break;
         }
     }
diff --git a/libs/hwui/Texture.cpp b/libs/hwui/Texture.cpp
deleted file mode 100644
index 1e90eeb..0000000
--- a/libs/hwui/Texture.cpp
+++ /dev/null
@@ -1,413 +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.
- */
-
-#include "Texture.h"
-#include "Caches.h"
-#include "utils/GLUtils.h"
-#include "utils/MathUtils.h"
-#include "utils/TraceUtils.h"
-
-#include <utils/Log.h>
-
-#include <math/mat4.h>
-
-#include <SkCanvas.h>
-
-namespace android {
-namespace uirenderer {
-
-// Number of bytes used by a texture in the given format
-static int bytesPerPixel(GLint glFormat) {
-    switch (glFormat) {
-        // The wrapped-texture case, usually means a SurfaceTexture
-        case 0:
-            return 0;
-        case GL_LUMINANCE:
-        case GL_ALPHA:
-            return 1;
-        case GL_SRGB8:
-        case GL_RGB:
-            return 3;
-        case GL_SRGB8_ALPHA8:
-        case GL_RGBA:
-            return 4;
-        case GL_RGBA16F:
-            return 8;
-        default:
-            LOG_ALWAYS_FATAL("UNKNOWN FORMAT 0x%x", glFormat);
-    }
-}
-
-void Texture::setWrapST(GLenum wrapS, GLenum wrapT, bool bindTexture, bool force) {
-    if (force || wrapS != mWrapS || wrapT != mWrapT) {
-        mWrapS = wrapS;
-        mWrapT = wrapT;
-
-        if (bindTexture) {
-            mCaches.textureState().bindTexture(mTarget, mId);
-        }
-
-        glTexParameteri(mTarget, GL_TEXTURE_WRAP_S, wrapS);
-        glTexParameteri(mTarget, GL_TEXTURE_WRAP_T, wrapT);
-    }
-}
-
-void Texture::setFilterMinMag(GLenum min, GLenum mag, bool bindTexture, bool force) {
-    if (force || min != mMinFilter || mag != mMagFilter) {
-        mMinFilter = min;
-        mMagFilter = mag;
-
-        if (bindTexture) {
-            mCaches.textureState().bindTexture(mTarget, mId);
-        }
-
-        if (mipMap && min == GL_LINEAR) min = GL_LINEAR_MIPMAP_LINEAR;
-
-        glTexParameteri(mTarget, GL_TEXTURE_MIN_FILTER, min);
-        glTexParameteri(mTarget, GL_TEXTURE_MAG_FILTER, mag);
-    }
-}
-
-void Texture::deleteTexture() {
-    mCaches.textureState().deleteTexture(mId);
-    mId = 0;
-    mTarget = GL_NONE;
-    if (mEglImageHandle != EGL_NO_IMAGE_KHR) {
-        EGLDisplay eglDisplayHandle = eglGetCurrentDisplay();
-        eglDestroyImageKHR(eglDisplayHandle, mEglImageHandle);
-        mEglImageHandle = EGL_NO_IMAGE_KHR;
-    }
-}
-
-bool Texture::updateLayout(uint32_t width, uint32_t height, GLint internalFormat, GLint format,
-                           GLenum target) {
-    if (mWidth == width && mHeight == height && mFormat == format &&
-        mInternalFormat == internalFormat && mTarget == target) {
-        return false;
-    }
-    mWidth = width;
-    mHeight = height;
-    mFormat = format;
-    mInternalFormat = internalFormat;
-    mTarget = target;
-    notifySizeChanged(mWidth * mHeight * bytesPerPixel(internalFormat));
-    return true;
-}
-
-void Texture::resetCachedParams() {
-    mWrapS = GL_REPEAT;
-    mWrapT = GL_REPEAT;
-    mMinFilter = GL_NEAREST_MIPMAP_LINEAR;
-    mMagFilter = GL_LINEAR;
-}
-
-void Texture::upload(GLint internalFormat, uint32_t width, uint32_t height, GLenum format,
-                     GLenum type, const void* pixels) {
-    GL_CHECKPOINT(MODERATE);
-
-    // We don't have color space information, we assume the data is gamma encoded
-    mIsLinear = false;
-
-    bool needsAlloc = updateLayout(width, height, internalFormat, format, GL_TEXTURE_2D);
-    if (!mId) {
-        glGenTextures(1, &mId);
-        needsAlloc = true;
-        resetCachedParams();
-    }
-    mCaches.textureState().bindTexture(GL_TEXTURE_2D, mId);
-    if (needsAlloc) {
-        glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, mWidth, mHeight, 0, format, type, pixels);
-    } else if (pixels) {
-        glTexSubImage2D(GL_TEXTURE_2D, 0, internalFormat, mWidth, mHeight, 0, format, type, pixels);
-    }
-    GL_CHECKPOINT(MODERATE);
-}
-
-void Texture::uploadHardwareBitmapToTexture(GraphicBuffer* buffer) {
-    EGLDisplay eglDisplayHandle = eglGetCurrentDisplay();
-    if (mEglImageHandle != EGL_NO_IMAGE_KHR) {
-        eglDestroyImageKHR(eglDisplayHandle, mEglImageHandle);
-        mEglImageHandle = EGL_NO_IMAGE_KHR;
-    }
-    mEglImageHandle = eglCreateImageKHR(eglDisplayHandle, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
-                                        buffer->getNativeBuffer(), 0);
-    glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, mEglImageHandle);
-}
-
-static void uploadToTexture(bool resize, GLint internalFormat, GLenum format, GLenum type,
-                            GLsizei stride, GLsizei bpp, GLsizei width, GLsizei height,
-                            const GLvoid* data) {
-    const bool useStride =
-            stride != width && Caches::getInstance().extensions().hasUnpackRowLength();
-    if ((stride == width) || useStride) {
-        if (useStride) {
-            glPixelStorei(GL_UNPACK_ROW_LENGTH, stride);
-        }
-
-        if (resize) {
-            glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 0, format, type, data);
-        } else {
-            glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, format, type, data);
-        }
-
-        if (useStride) {
-            glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
-        }
-    } else {
-        //  With OpenGL ES 2.0 we need to copy the bitmap in a temporary buffer
-        //  if the stride doesn't match the width
-
-        GLvoid* temp = (GLvoid*)malloc(width * height * bpp);
-        if (!temp) return;
-
-        uint8_t* pDst = (uint8_t*)temp;
-        uint8_t* pSrc = (uint8_t*)data;
-        for (GLsizei i = 0; i < height; i++) {
-            memcpy(pDst, pSrc, width * bpp);
-            pDst += width * bpp;
-            pSrc += stride * bpp;
-        }
-
-        if (resize) {
-            glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 0, format, type, temp);
-        } else {
-            glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, format, type, temp);
-        }
-
-        free(temp);
-    }
-}
-
-void Texture::colorTypeToGlFormatAndType(const Caches& caches, SkColorType colorType, bool needSRGB,
-                                         GLint* outInternalFormat, GLint* outFormat,
-                                         GLint* outType) {
-    switch (colorType) {
-        case kAlpha_8_SkColorType:
-            *outFormat = GL_ALPHA;
-            *outInternalFormat = GL_ALPHA;
-            *outType = GL_UNSIGNED_BYTE;
-            break;
-        case kRGB_565_SkColorType:
-            if (needSRGB) {
-                // We would ideally use a GL_RGB/GL_SRGB8 texture but the
-                // intermediate Skia bitmap needs to be ARGB_8888
-                *outFormat = GL_RGBA;
-                *outInternalFormat = caches.rgbaInternalFormat();
-                *outType = GL_UNSIGNED_BYTE;
-            } else {
-                *outFormat = GL_RGB;
-                *outInternalFormat = GL_RGB;
-                *outType = GL_UNSIGNED_SHORT_5_6_5;
-            }
-            break;
-        // ARGB_4444 is upconverted to RGBA_8888
-        case kARGB_4444_SkColorType:
-        case kN32_SkColorType:
-            *outFormat = GL_RGBA;
-            *outInternalFormat = caches.rgbaInternalFormat(needSRGB);
-            *outType = GL_UNSIGNED_BYTE;
-            break;
-        case kGray_8_SkColorType:
-            *outFormat = GL_LUMINANCE;
-            *outInternalFormat = GL_LUMINANCE;
-            *outType = GL_UNSIGNED_BYTE;
-            break;
-        case kRGBA_F16_SkColorType:
-            if (caches.extensions().getMajorGlVersion() >= 3) {
-                // This format is always linear
-                *outFormat = GL_RGBA;
-                *outInternalFormat = GL_RGBA16F;
-                *outType = GL_HALF_FLOAT;
-            } else {
-                *outFormat = GL_RGBA;
-                *outInternalFormat = caches.rgbaInternalFormat(true);
-                *outType = GL_UNSIGNED_BYTE;
-            }
-            break;
-        default:
-            LOG_ALWAYS_FATAL("Unsupported bitmap colorType: %d", colorType);
-            break;
-    }
-}
-
-SkBitmap Texture::uploadToN32(const SkBitmap& bitmap, bool hasLinearBlending,
-                              sk_sp<SkColorSpace> sRGB) {
-    SkBitmap rgbaBitmap;
-    rgbaBitmap.allocPixels(SkImageInfo::MakeN32(bitmap.width(), bitmap.height(),
-                                                bitmap.info().alphaType(),
-                                                hasLinearBlending ? sRGB : nullptr));
-    rgbaBitmap.eraseColor(0);
-
-    if (bitmap.colorType() == kRGBA_F16_SkColorType) {
-        // Drawing RGBA_F16 onto ARGB_8888 is not supported
-        bitmap.readPixels(rgbaBitmap.info().makeColorSpace(SkColorSpace::MakeSRGB()),
-                          rgbaBitmap.getPixels(), rgbaBitmap.rowBytes(), 0, 0);
-    } else {
-        SkCanvas canvas(rgbaBitmap);
-        canvas.drawBitmap(bitmap, 0.0f, 0.0f, nullptr);
-    }
-
-    return rgbaBitmap;
-}
-
-bool Texture::hasUnsupportedColorType(const SkImageInfo& info, bool hasLinearBlending) {
-    return info.colorType() == kARGB_4444_SkColorType ||
-           (info.colorType() == kRGB_565_SkColorType && hasLinearBlending &&
-            info.colorSpace()->isSRGB()) ||
-           (info.colorType() == kRGBA_F16_SkColorType &&
-            Caches::getInstance().extensions().getMajorGlVersion() < 3);
-}
-
-void Texture::upload(Bitmap& bitmap) {
-    ATRACE_FORMAT("Upload %ux%u Texture", bitmap.width(), bitmap.height());
-
-    // We could also enable mipmapping if both bitmap dimensions are powers
-    // of 2 but we'd have to deal with size changes. Let's keep this simple
-    const bool canMipMap = mCaches.extensions().hasNPot();
-
-    // If the texture had mipmap enabled but not anymore,
-    // force a glTexImage2D to discard the mipmap levels
-    bool needsAlloc = canMipMap && mipMap && !bitmap.hasHardwareMipMap();
-    bool setDefaultParams = false;
-
-    if (!mId) {
-        glGenTextures(1, &mId);
-        needsAlloc = true;
-        setDefaultParams = true;
-    }
-
-    bool hasLinearBlending = mCaches.extensions().hasLinearBlending();
-    bool needSRGB = transferFunctionCloseToSRGB(bitmap.info().colorSpace());
-
-    GLint internalFormat, format, type;
-    colorTypeToGlFormatAndType(mCaches, bitmap.colorType(), needSRGB && hasLinearBlending,
-                               &internalFormat, &format, &type);
-
-    // Some devices don't support GL_RGBA16F, so we need to compare the color type
-    // and internal GL format to decide what to do with 16 bit bitmaps
-    bool rgba16fNeedsConversion =
-            bitmap.colorType() == kRGBA_F16_SkColorType && internalFormat != GL_RGBA16F;
-
-    // RGBA16F is always linear extended sRGB
-    if (internalFormat == GL_RGBA16F) {
-        mIsLinear = true;
-    }
-
-    mConnector.reset();
-
-    // Alpha masks don't have color profiles
-    // If an RGBA16F bitmap needs conversion, we know the target will be sRGB
-    if (!mIsLinear && internalFormat != GL_ALPHA && !rgba16fNeedsConversion) {
-        SkColorSpace* colorSpace = bitmap.info().colorSpace();
-        // If the bitmap is sRGB we don't need conversion
-        if (colorSpace != nullptr && !colorSpace->isSRGB()) {
-            SkMatrix44 xyzMatrix(SkMatrix44::kUninitialized_Constructor);
-            if (!colorSpace->toXYZD50(&xyzMatrix)) {
-                ALOGW("Incompatible color space!");
-            } else {
-                SkColorSpaceTransferFn fn;
-                if (!colorSpace->isNumericalTransferFn(&fn)) {
-                    ALOGW("Incompatible color space, no numerical transfer function!");
-                } else {
-                    float data[16];
-                    xyzMatrix.asColMajorf(data);
-
-                    ColorSpace::TransferParameters p = {fn.fG, fn.fA, fn.fB, fn.fC,
-                                                        fn.fD, fn.fE, fn.fF};
-                    ColorSpace src("Unnamed", mat4f((const float*)&data[0]).upperLeft(), p);
-                    mConnector.reset(new ColorSpaceConnector(src, ColorSpace::sRGB()));
-
-                    // A non-sRGB color space might have a transfer function close enough to sRGB
-                    // that we can save shader instructions by using an sRGB sampler
-                    // This is only possible if we have hardware support for sRGB textures
-                    if (needSRGB && internalFormat == GL_RGBA && mCaches.extensions().hasSRGB() &&
-                        !bitmap.isHardware()) {
-                        internalFormat = GL_SRGB8_ALPHA8;
-                    }
-                }
-            }
-        }
-    }
-
-    GLenum target = bitmap.isHardware() ? GL_TEXTURE_EXTERNAL_OES : GL_TEXTURE_2D;
-    needsAlloc |= updateLayout(bitmap.width(), bitmap.height(), internalFormat, format, target);
-
-    blend = !bitmap.isOpaque();
-    mCaches.textureState().bindTexture(mTarget, mId);
-
-    // TODO: Handle sRGB gray bitmaps
-    if (CC_UNLIKELY(hasUnsupportedColorType(bitmap.info(), hasLinearBlending))) {
-        SkBitmap skBitmap;
-        bitmap.getSkBitmap(&skBitmap);
-        sk_sp<SkColorSpace> sRGB = SkColorSpace::MakeSRGB();
-        SkBitmap rgbaBitmap = uploadToN32(skBitmap, hasLinearBlending, std::move(sRGB));
-        uploadToTexture(needsAlloc, internalFormat, format, type, rgbaBitmap.rowBytesAsPixels(),
-                        rgbaBitmap.bytesPerPixel(), rgbaBitmap.width(), rgbaBitmap.height(),
-                        rgbaBitmap.getPixels());
-    } else if (bitmap.isHardware()) {
-        uploadHardwareBitmapToTexture(bitmap.graphicBuffer());
-    } else {
-        uploadToTexture(needsAlloc, internalFormat, format, type, bitmap.rowBytesAsPixels(),
-                        bitmap.info().bytesPerPixel(), bitmap.width(), bitmap.height(),
-                        bitmap.pixels());
-    }
-
-    if (canMipMap) {
-        mipMap = bitmap.hasHardwareMipMap();
-        if (mipMap) {
-            glGenerateMipmap(GL_TEXTURE_2D);
-        }
-    }
-
-    if (setDefaultParams) {
-        setFilter(GL_NEAREST);
-        setWrap(GL_CLAMP_TO_EDGE);
-    }
-}
-
-void Texture::wrap(GLuint id, uint32_t width, uint32_t height, GLint internalFormat, GLint format,
-                   GLenum target) {
-    mId = id;
-    mWidth = width;
-    mHeight = height;
-    mFormat = format;
-    mInternalFormat = internalFormat;
-    mTarget = target;
-    mConnector.reset();
-    // We're wrapping an existing texture, so don't double count this memory
-    notifySizeChanged(0);
-}
-
-TransferFunctionType Texture::getTransferFunctionType() const {
-    if (mConnector.get() != nullptr && mInternalFormat != GL_SRGB8_ALPHA8) {
-        const ColorSpace::TransferParameters& p = mConnector->getSource().getTransferParameters();
-        if (MathUtils::isZero(p.e) && MathUtils::isZero(p.f)) {
-            if (MathUtils::areEqual(p.a, 1.0f) && MathUtils::isZero(p.b) &&
-                MathUtils::isZero(p.c) && MathUtils::isZero(p.d)) {
-                if (MathUtils::areEqual(p.g, 1.0f)) {
-                    return TransferFunctionType::None;
-                }
-                return TransferFunctionType::Gamma;
-            }
-            return TransferFunctionType::Limited;
-        }
-        return TransferFunctionType::Full;
-    }
-    return TransferFunctionType::None;
-}
-
-};  // namespace uirenderer
-};  // namespace android
diff --git a/libs/hwui/Texture.h b/libs/hwui/Texture.h
deleted file mode 100644
index 5b7e4e2..0000000
--- a/libs/hwui/Texture.h
+++ /dev/null
@@ -1,228 +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.
- */
-
-#ifndef ANDROID_HWUI_TEXTURE_H
-#define ANDROID_HWUI_TEXTURE_H
-
-#include "GpuMemoryTracker.h"
-#include "hwui/Bitmap.h"
-#include "utils/Color.h"
-
-#include <memory>
-
-#include <math/mat3.h>
-
-#include <ui/ColorSpace.h>
-
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-#include <GLES2/gl2.h>
-#include <GLES3/gl3.h>
-#include <SkBitmap.h>
-
-namespace android {
-
-class GraphicBuffer;
-
-namespace uirenderer {
-
-class Caches;
-class UvMapper;
-class Layer;
-
-/**
- * Represents an OpenGL texture.
- */
-class Texture : public GpuMemoryTracker {
-public:
-    static SkBitmap uploadToN32(const SkBitmap& bitmap, bool hasLinearBlending,
-                                sk_sp<SkColorSpace> sRGB);
-    static bool hasUnsupportedColorType(const SkImageInfo& info, bool hasLinearBlending);
-    static void colorTypeToGlFormatAndType(const Caches& caches, SkColorType colorType,
-                                           bool needSRGB, GLint* outInternalFormat,
-                                           GLint* outFormat, GLint* outType);
-
-    explicit Texture(Caches& caches) : GpuMemoryTracker(GpuObjectType::Texture), mCaches(caches) {}
-
-    virtual ~Texture() {}
-
-    inline void setWrap(GLenum wrap, bool bindTexture = false, bool force = false) {
-        setWrapST(wrap, wrap, bindTexture, force);
-    }
-
-    virtual void setWrapST(GLenum wrapS, GLenum wrapT, bool bindTexture = false,
-                           bool force = false);
-
-    inline void setFilter(GLenum filter, bool bindTexture = false, bool force = false) {
-        setFilterMinMag(filter, filter, bindTexture, force);
-    }
-
-    virtual void setFilterMinMag(GLenum min, GLenum mag, bool bindTexture = false,
-                                 bool force = false);
-
-    /**
-     * Convenience method to call glDeleteTextures() on this texture's id.
-     */
-    void deleteTexture();
-
-    /**
-     * Sets the width, height, and format of the texture along with allocating
-     * the texture ID. Does nothing if the width, height, and format are already
-     * the requested values.
-     *
-     * The image data is undefined after calling this.
-     */
-    void resize(uint32_t width, uint32_t height, GLint internalFormat, GLint format) {
-        upload(internalFormat, width, height, format,
-               internalFormat == GL_RGBA16F ? GL_HALF_FLOAT : GL_UNSIGNED_BYTE, nullptr);
-    }
-
-    /**
-     * Updates this Texture with the contents of the provided Bitmap,
-     * also setting the appropriate width, height, and format. It is not necessary
-     * to call resize() prior to this.
-     *
-     * Note this does not set the generation from the Bitmap.
-     */
-    void upload(Bitmap& source);
-
-    /**
-     * Basically glTexImage2D/glTexSubImage2D.
-     */
-    void upload(GLint internalFormat, uint32_t width, uint32_t height, GLenum format, GLenum type,
-                const void* pixels);
-
-    /**
-     * Wraps an existing texture.
-     */
-    void wrap(GLuint id, uint32_t width, uint32_t height, GLint internalFormat, GLint format,
-              GLenum target);
-
-    GLuint id() const { return mId; }
-
-    uint32_t width() const { return mWidth; }
-
-    uint32_t height() const { return mHeight; }
-
-    GLint format() const { return mFormat; }
-
-    GLint internalFormat() const { return mInternalFormat; }
-
-    GLenum target() const { return mTarget; }
-
-    /**
-     * Returns nullptr if this texture does not require color space conversion
-     * to sRGB, or a valid pointer to a ColorSpaceConnector if a conversion
-     * is required.
-     */
-    constexpr const ColorSpaceConnector* getColorSpaceConnector() const { return mConnector.get(); }
-
-    constexpr bool hasColorSpaceConversion() const { return mConnector.get() != nullptr; }
-
-    TransferFunctionType getTransferFunctionType() const;
-
-    /**
-     * Returns true if this texture uses a linear encoding format.
-     */
-    constexpr bool isLinear() const { return mIsLinear; }
-
-    /**
-     * Generation of the backing bitmap,
-     */
-    uint32_t generation = 0;
-    /**
-     * Indicates whether the texture requires blending.
-     */
-    bool blend = false;
-    /**
-     * Indicates whether this texture should be cleaned up after use.
-     */
-    bool cleanup = false;
-    /**
-     * Optional, size of the original bitmap.
-     */
-    uint32_t bitmapSize = 0;
-    /**
-     * Indicates whether this texture will use trilinear filtering.
-     */
-    bool mipMap = false;
-
-    /**
-     * Optional, pointer to a texture coordinates mapper.
-     */
-    const UvMapper* uvMapper = nullptr;
-
-    /**
-     * Whether or not the Texture is marked in use and thus not evictable for
-     * the current frame. This is reset at the start of a new frame.
-     */
-    void* isInUse = nullptr;
-
-private:
-    // TODO: Temporarily grant private access to GlLayer, remove once
-    // GlLayer can be de-tangled from being a dual-purpose render target
-    // and external texture wrapper
-    friend class GlLayer;
-
-    // Returns true if the texture layout (size, format, etc.) changed, false if it was the same
-    bool updateLayout(uint32_t width, uint32_t height, GLint internalFormat, GLint format,
-                      GLenum target);
-    void uploadHardwareBitmapToTexture(GraphicBuffer* buffer);
-    void resetCachedParams();
-
-    GLuint mId = 0;
-    uint32_t mWidth = 0;
-    uint32_t mHeight = 0;
-    GLint mFormat = 0;
-    GLint mInternalFormat = 0;
-    GLenum mTarget = GL_NONE;
-    EGLImageKHR mEglImageHandle = EGL_NO_IMAGE_KHR;
-
-    /* See GLES spec section 3.8.14
-     * "In the initial state, the value assigned to TEXTURE_MIN_FILTER is
-     * NEAREST_MIPMAP_LINEAR and the value for TEXTURE_MAG_FILTER is LINEAR.
-     * s, t, and r wrap modes are all set to REPEAT."
-     */
-    GLenum mWrapS = GL_REPEAT;
-    GLenum mWrapT = GL_REPEAT;
-    GLenum mMinFilter = GL_NEAREST_MIPMAP_LINEAR;
-    GLenum mMagFilter = GL_LINEAR;
-
-    // Indicates whether the content of the texture is in linear space
-    bool mIsLinear = false;
-
-    Caches& mCaches;
-
-    std::unique_ptr<ColorSpaceConnector> mConnector;
-};  // struct Texture
-
-class AutoTexture {
-public:
-    explicit AutoTexture(Texture* texture) : texture(texture) {}
-    ~AutoTexture() {
-        if (texture && texture->cleanup) {
-            texture->deleteTexture();
-            delete texture;
-        }
-    }
-
-    Texture* const texture;
-};  // class AutoTexture
-
-};  // namespace uirenderer
-};  // namespace android
-
-#endif  // ANDROID_HWUI_TEXTURE_H
diff --git a/libs/hwui/VkLayer.cpp b/libs/hwui/VkLayer.cpp
deleted file mode 100644
index 30fba7a..0000000
--- a/libs/hwui/VkLayer.cpp
+++ /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.
- */
-
-#include "VkLayer.h"
-
-#include "renderstate/RenderState.h"
-
-#include <SkCanvas.h>
-#include <SkSurface.h>
-
-namespace android {
-namespace uirenderer {
-
-void VkLayer::updateTexture() {
-    sk_sp<SkSurface> surface;
-    SkImageInfo info = SkImageInfo::MakeS32(mWidth, mHeight, kPremul_SkAlphaType);
-    surface = SkSurface::MakeRenderTarget(mRenderState.getGrContext(), SkBudgeted::kNo, info);
-    surface->getCanvas()->clear(SK_ColorBLUE);
-    mImage = surface->makeImageSnapshot();
-}
-
-void VkLayer::onVkContextDestroyed() {
-    mImage = nullptr;
-}
-
-};  // namespace uirenderer
-};  // namespace android
diff --git a/libs/hwui/VkLayer.h b/libs/hwui/VkLayer.h
deleted file mode 100644
index e9664d0..0000000
--- a/libs/hwui/VkLayer.h
+++ /dev/null
@@ -1,70 +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.
- */
-
-#pragma once
-
-#include "Layer.h"
-
-#include <SkImage.h>
-
-namespace android {
-namespace uirenderer {
-/**
- * A layer has dimensions and is backed by a VkImage.
- */
-class VkLayer : public Layer {
-public:
-    VkLayer(RenderState& renderState, uint32_t layerWidth, uint32_t layerHeight,
-            sk_sp<SkColorFilter> colorFilter, int alpha, SkBlendMode mode, bool blend)
-            : Layer(renderState, Api::Vulkan, colorFilter, alpha, mode)
-            , mWidth(layerWidth)
-            , mHeight(layerHeight)
-            , mBlend(blend) {}
-
-    virtual ~VkLayer() {}
-
-    uint32_t getWidth() const override { return mWidth; }
-
-    uint32_t getHeight() const override { return mHeight; }
-
-    void setSize(uint32_t width, uint32_t height) override {
-        mWidth = width;
-        mHeight = height;
-    }
-
-    void setBlend(bool blend) override { mBlend = blend; }
-
-    bool isBlend() const override { return mBlend; }
-
-    sk_sp<SkImage> getImage() { return mImage; }
-
-    void updateTexture();
-
-    // If we've destroyed the vulkan context (VkInstance, VkDevice, etc.), we must make sure to
-    // destroy any VkImages that were made with that context.
-    void onVkContextDestroyed();
-
-private:
-    int mWidth;
-    int mHeight;
-    bool mBlend;
-
-    sk_sp<SkImage> mImage;
-
-};  // struct VkLayer
-
-};  // namespace uirenderer
-};  // namespace android
diff --git a/libs/hwui/hwui/Bitmap.cpp b/libs/hwui/hwui/Bitmap.cpp
index a7d37f8..440620a 100644
--- a/libs/hwui/hwui/Bitmap.cpp
+++ b/libs/hwui/hwui/Bitmap.cpp
@@ -15,11 +15,11 @@
  */
 #include "Bitmap.h"
 
-#include "Caches.h"
 #include "HardwareBitmapUploader.h"
 #include "Properties.h"
 #include "renderthread/RenderProxy.h"
 #include "utils/Color.h"
+#include <utils/Trace.h>
 
 #include <sys/mman.h>
 
@@ -290,7 +290,7 @@
     if (isHardware()) {
         outBitmap->allocPixels(SkImageInfo::Make(info().width(), info().height(),
                                                  info().colorType(), info().alphaType(), nullptr));
-        uirenderer::renderthread::RenderProxy::copyGraphicBufferInto(graphicBuffer(), outBitmap);
+        uirenderer::renderthread::RenderProxy::copyHWBitmapInto(this, outBitmap);
         if (mInfo.colorSpace()) {
             sk_sp<SkPixelRef> pixelRef = sk_ref_sp(outBitmap->pixelRef());
             outBitmap->setInfo(mInfo);
diff --git a/libs/hwui/hwui/Typeface.cpp b/libs/hwui/hwui/Typeface.cpp
index d985633..e8332a8 100644
--- a/libs/hwui/hwui/Typeface.cpp
+++ b/libs/hwui/hwui/Typeface.cpp
@@ -178,8 +178,8 @@
     struct stat st = {};
     LOG_ALWAYS_FATAL_IF(fstat(fd, &st) == -1, "Failed to stat file %s", kRobotoFont);
     void* data = mmap(nullptr, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
-    std::unique_ptr<SkMemoryStream> fontData(new SkMemoryStream(data, st.st_size));
-    sk_sp<SkTypeface> typeface = SkTypeface::MakeFromStream(fontData.release());
+    std::unique_ptr<SkStreamAsset> fontData(new SkMemoryStream(data, st.st_size));
+    sk_sp<SkTypeface> typeface = SkTypeface::MakeFromStream(std::move(fontData));
     LOG_ALWAYS_FATAL_IF(typeface == nullptr, "Failed to make typeface from %s", kRobotoFont);
 
     std::shared_ptr<minikin::MinikinFont> font = std::make_shared<MinikinFontSkia>(
diff --git a/libs/hwui/pipeline/skia/LayerDrawable.cpp b/libs/hwui/pipeline/skia/LayerDrawable.cpp
index c41f6a6..3ca0f81 100644
--- a/libs/hwui/pipeline/skia/LayerDrawable.cpp
+++ b/libs/hwui/pipeline/skia/LayerDrawable.cpp
@@ -15,8 +15,6 @@
  */
 
 #include "LayerDrawable.h"
-#include "GlLayer.h"
-#include "VkLayer.h"
 
 #include "GrBackendSurface.h"
 #include "SkColorFilter.h"
@@ -30,87 +28,78 @@
 void LayerDrawable::onDraw(SkCanvas* canvas) {
     Layer* layer = mLayerUpdater->backingLayer();
     if (layer) {
-        DrawLayer(canvas->getGrContext(), canvas, layer);
+        DrawLayer(canvas->getGrContext(), canvas, layer, nullptr, nullptr, true);
     }
 }
 
 bool LayerDrawable::DrawLayer(GrContext* context, SkCanvas* canvas, Layer* layer,
-                              const SkRect* dstRect) {
+                              const SkRect* srcRect, const SkRect* dstRect,
+                              bool useLayerTransform) {
     if (context == nullptr) {
         SkDEBUGF(("Attempting to draw LayerDrawable into an unsupported surface"));
         return false;
     }
     // transform the matrix based on the layer
-    SkMatrix layerTransform;
-    layer->getTransform().copyTo(layerTransform);
-    sk_sp<SkImage> layerImage;
+    SkMatrix layerTransform = layer->getTransform();
+    sk_sp<SkImage> layerImage = layer->getImage();
     const int layerWidth = layer->getWidth();
     const int layerHeight = layer->getHeight();
-    if (layer->getApi() == Layer::Api::OpenGL) {
-        GlLayer* glLayer = static_cast<GlLayer*>(layer);
-        GrGLTextureInfo externalTexture;
-        externalTexture.fTarget = glLayer->getRenderTarget();
-        externalTexture.fID = glLayer->getTextureId();
-        // The format may not be GL_RGBA8, but given the DeferredLayerUpdater and GLConsumer don't
-        // expose that info we use it as our default.  Further, given that we only use this texture
-        // as a source this will not impact how Skia uses the texture.  The only potential affect
-        // this is anticipated to have is that for some format types if we are not bound as an OES
-        // texture we may get invalid results for SKP capture if we read back the texture.
-        externalTexture.fFormat = GL_RGBA8;
-        GrBackendTexture backendTexture(layerWidth, layerHeight, GrMipMapped::kNo, externalTexture);
-        layerImage = SkImage::MakeFromTexture(context, backendTexture, kTopLeft_GrSurfaceOrigin,
-                                              kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr);
-    } else {
-        SkASSERT(layer->getApi() == Layer::Api::Vulkan);
-        VkLayer* vkLayer = static_cast<VkLayer*>(layer);
-        canvas->clear(SK_ColorGREEN);
-        layerImage = vkLayer->getImage();
-    }
 
     if (layerImage) {
         SkMatrix textureMatrixInv;
-        layer->getTexTransform().copyTo(textureMatrixInv);
+        textureMatrixInv = layer->getTexTransform();
         // TODO: after skia bug https://bugs.chromium.org/p/skia/issues/detail?id=7075 is fixed
         // use bottom left origin and remove flipV and invert transformations.
         SkMatrix flipV;
         flipV.setAll(1, 0, 0, 0, -1, 1, 0, 0, 1);
         textureMatrixInv.preConcat(flipV);
         textureMatrixInv.preScale(1.0f / layerWidth, 1.0f / layerHeight);
-        textureMatrixInv.postScale(layerWidth, layerHeight);
+        textureMatrixInv.postScale(layerImage->width(), layerImage->height());
         SkMatrix textureMatrix;
         if (!textureMatrixInv.invert(&textureMatrix)) {
             textureMatrix = textureMatrixInv;
         }
 
         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 {
+        if (useLayerTransform) {
             matrix = SkMatrix::Concat(layerTransform, textureMatrix);
+        } else {
+            matrix = textureMatrix;
         }
 
         SkPaint paint;
         paint.setAlpha(layer->getAlpha());
         paint.setBlendMode(layer->getMode());
         paint.setColorFilter(layer->getColorSpaceWithFilter());
+        if (layer->getForceFilter()) {
+            paint.setFilterQuality(kLow_SkFilterQuality);
+        }
 
         const bool nonIdentityMatrix = !matrix.isIdentity();
         if (nonIdentityMatrix) {
             canvas->save();
             canvas->concat(matrix);
         }
-        if (dstRect) {
+        if (dstRect || srcRect) {
             SkMatrix matrixInv;
             if (!matrix.invert(&matrixInv)) {
                 matrixInv = matrix;
             }
-            SkRect srcRect = SkRect::MakeIWH(layerWidth, layerHeight);
-            matrixInv.mapRect(&srcRect);
-            SkRect skiaDestRect = *dstRect;
+            SkRect skiaSrcRect;
+            if (srcRect) {
+                skiaSrcRect = *srcRect;
+            } else {
+                skiaSrcRect = SkRect::MakeIWH(layerWidth, layerHeight);
+            }
+            matrixInv.mapRect(&skiaSrcRect);
+            SkRect skiaDestRect;
+            if (dstRect) {
+                skiaDestRect = *dstRect;
+            } else {
+                skiaDestRect = SkRect::MakeIWH(layerWidth, layerHeight);
+            }
             matrixInv.mapRect(&skiaDestRect);
-            canvas->drawImageRect(layerImage.get(), srcRect, skiaDestRect, &paint,
+            canvas->drawImageRect(layerImage.get(), skiaSrcRect, skiaDestRect, &paint,
                                   SkCanvas::kFast_SrcRectConstraint);
         } else {
             canvas->drawImage(layerImage.get(), 0, 0, &paint);
diff --git a/libs/hwui/pipeline/skia/LayerDrawable.h b/libs/hwui/pipeline/skia/LayerDrawable.h
index 18d1184..5c12590 100644
--- a/libs/hwui/pipeline/skia/LayerDrawable.h
+++ b/libs/hwui/pipeline/skia/LayerDrawable.h
@@ -33,7 +33,7 @@
     explicit LayerDrawable(DeferredLayerUpdater* layerUpdater) : mLayerUpdater(layerUpdater) {}
 
     static bool DrawLayer(GrContext* context, SkCanvas* canvas, Layer* layer,
-                          const SkRect* dstRect = nullptr);
+                          const SkRect* srcRect, const SkRect* dstRect, bool useLayerTransform);
 
 protected:
     virtual SkRect onGetBounds() override {
diff --git a/libs/hwui/pipeline/skia/ShaderCache.cpp b/libs/hwui/pipeline/skia/ShaderCache.cpp
index 6700748..073b481 100644
--- a/libs/hwui/pipeline/skia/ShaderCache.cpp
+++ b/libs/hwui/pipeline/skia/ShaderCache.cpp
@@ -18,6 +18,8 @@
 #include <algorithm>
 #include <log/log.h>
 #include <thread>
+#include <array>
+#include <openssl/sha.h>
 #include "FileBlobCache.h"
 #include "Properties.h"
 #include "utils/TraceUtils.h"
@@ -41,7 +43,40 @@
     return sCache;
 }
 
-void ShaderCache::initShaderDiskCache() {
+bool ShaderCache::validateCache(const void* identity, ssize_t size) {
+    if (nullptr == identity && size == 0)
+        return true;
+
+    if (nullptr == identity || size < 0) {
+        if (CC_UNLIKELY(Properties::debugLevel & kDebugCaches)) {
+            ALOGW("ShaderCache::validateCache invalid cache identity");
+        }
+        mBlobCache->clear();
+        return false;
+    }
+
+    SHA256_CTX ctx;
+    SHA256_Init(&ctx);
+
+    SHA256_Update(&ctx, identity, size);
+    mIDHash.resize(SHA256_DIGEST_LENGTH);
+    SHA256_Final(mIDHash.data(), &ctx);
+
+    std::array<uint8_t, SHA256_DIGEST_LENGTH> hash;
+    auto key = sIDKey;
+    auto loaded = mBlobCache->get(&key, sizeof(key), hash.data(), hash.size());
+
+    if (loaded && std::equal(hash.begin(), hash.end(), mIDHash.begin()))
+        return true;
+
+    if (CC_UNLIKELY(Properties::debugLevel & kDebugCaches)) {
+        ALOGW("ShaderCache::validateCache cache validation fails");
+    }
+    mBlobCache->clear();
+    return false;
+}
+
+void ShaderCache::initShaderDiskCache(const void* identity, ssize_t size) {
     ATRACE_NAME("initShaderDiskCache");
     std::lock_guard<std::mutex> lock(mMutex);
 
@@ -50,6 +85,7 @@
     // desktop / laptop GPUs. Thus, disable the shader disk cache for emulator builds.
     if (!Properties::runningInEmulator && mFilename.length() > 0) {
         mBlobCache.reset(new FileBlobCache(maxKeySize, maxValueSize, maxTotalSize, mFilename));
+        validateCache(identity, size);
         mInitialized = true;
     }
 }
@@ -104,6 +140,18 @@
     return SkData::MakeFromMalloc(valueBuffer, valueSize);
 }
 
+void ShaderCache::saveToDiskLocked() {
+    ATRACE_NAME("ShaderCache::saveToDiskLocked");
+    if (mInitialized && mBlobCache && mSavePending) {
+        if (mIDHash.size()) {
+            auto key = sIDKey;
+            mBlobCache->set(&key, sizeof(key), mIDHash.data(), mIDHash.size());
+        }
+        mBlobCache->writeToFile();
+    }
+    mSavePending = false;
+}
+
 void ShaderCache::store(const SkData& key, const SkData& data) {
     ATRACE_NAME("ShaderCache::store");
     std::lock_guard<std::mutex> lock(mMutex);
@@ -129,11 +177,7 @@
         std::thread deferredSaveThread([this]() {
             sleep(mDeferredSaveDelay);
             std::lock_guard<std::mutex> lock(mMutex);
-            ATRACE_NAME("ShaderCache::saveToDisk");
-            if (mInitialized && mBlobCache) {
-                mBlobCache->writeToFile();
-            }
-            mSavePending = false;
+            saveToDiskLocked();
         });
         deferredSaveThread.detach();
     }
diff --git a/libs/hwui/pipeline/skia/ShaderCache.h b/libs/hwui/pipeline/skia/ShaderCache.h
index 27473d6..82804cf 100644
--- a/libs/hwui/pipeline/skia/ShaderCache.h
+++ b/libs/hwui/pipeline/skia/ShaderCache.h
@@ -40,12 +40,21 @@
     ANDROID_API static ShaderCache& get();
 
     /**
-     * "initShaderDiskCache" loads the serialized cache contents from disk and puts the ShaderCache
-     * into an initialized state, such that it is able to insert and retrieve entries from the
-     * cache.  This should be called when HWUI pipeline is initialized.  When not in the initialized
-     * state the load and store methods will return without performing any cache operations.
+     * initShaderDiskCache" loads the serialized cache contents from disk,
+     * optionally checks that the on-disk cache matches a provided identity,
+     * and puts the ShaderCache into an initialized state, such that it is
+     * able to insert and retrieve entries from the cache. If identity is
+     * non-null and validation fails, the cache is initialized but contains
+     * no data. If size is less than zero, the cache is initilaized but
+     * contains no data.
+     *
+     * This should be called when HWUI pipeline is initialized. When not in
+     * the initialized state the load and store methods will return without
+     * performing any cache operations.
      */
-    virtual void initShaderDiskCache();
+    virtual void initShaderDiskCache(const void *identity, ssize_t size);
+
+    virtual void initShaderDiskCache() { initShaderDiskCache(nullptr, 0); }
 
     /**
      * "setFilename" sets the name of the file that should be used to store
@@ -83,6 +92,19 @@
     BlobCache* getBlobCacheLocked();
 
     /**
+     * "validateCache" updates the cache to match the given identity.  If the
+     * cache currently has the wrong identity, all entries in the cache are cleared.
+     */
+    bool validateCache(const void* identity, ssize_t size);
+
+    /**
+     * "saveToDiskLocked" attemps to save the current contents of the cache to
+     * disk. If the identity hash exists, we will insert the identity hash into
+     * the cache for next validation.
+     */
+    void saveToDiskLocked();
+
+    /**
      * "mInitialized" indicates whether the ShaderCache is in the initialized
      * state.  It is initialized to false at construction time, and gets set to
      * true when initialize is called.
@@ -111,6 +133,15 @@
     std::string mFilename;
 
     /**
+     * "mIDHash" is the current identity hash for the cache validation. It is
+     * initialized to an empty vector at construction time, and its content is
+     * generated in the call of the validateCache method. An empty vector
+     * indicates that cache validation is not performed, and the hash should
+     * not be stored on disk.
+     */
+    std::vector<uint8_t> mIDHash;
+
+    /**
      * "mSavePending" indicates whether or not a deferred save operation is
      * pending.  Each time a key/value pair is inserted into the cache via
      * load, a deferred save is initiated if one is not already pending.
@@ -140,6 +171,11 @@
      */
     static ShaderCache sCache;
 
+    /**
+     * "sIDKey" is the cache key of the identity hash
+     */
+    static constexpr uint8_t sIDKey = 0;
+
     friend class ShaderCacheTestUtils; //used for unit testing
 };
 
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
index 78f5a71..26f01ce 100644
--- a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
@@ -17,7 +17,6 @@
 #include "SkiaOpenGLPipeline.h"
 
 #include "DeferredLayerUpdater.h"
-#include "GlLayer.h"
 #include "LayerDrawable.h"
 #include "SkiaPipeline.h"
 #include "SkiaProfileRenderer.h"
@@ -63,21 +62,23 @@
 bool SkiaOpenGLPipeline::draw(const Frame& frame, const SkRect& screenDirty, const SkRect& dirty,
                               const LightGeometry& lightGeometry,
                               LayerUpdateQueue* layerUpdateQueue, const Rect& contentDrawBounds,
-                              bool opaque, bool wideColorGamut, const LightInfo& lightInfo,
+                              bool opaque, const LightInfo& lightInfo,
                               const std::vector<sp<RenderNode>>& renderNodes,
                               FrameInfoVisualizer* profiler) {
     mEglManager.damageFrame(frame, dirty);
 
-    SkColorType colorType;
+    SkColorType colorType = getSurfaceColorType();
     // setup surface for fbo0
     GrGLFramebufferInfo fboInfo;
     fboInfo.fFBOID = 0;
-    if (wideColorGamut) {
+    if (colorType == kRGBA_F16_SkColorType) {
         fboInfo.fFormat = GL_RGBA16F;
-        colorType = kRGBA_F16_SkColorType;
-    } else {
+    } else if (colorType == kN32_SkColorType) {
+        // Note: The default preference of pixel format is RGBA_8888, when other
+        // pixel format is available, we should branch out and do more check.
         fboInfo.fFormat = GL_RGBA8;
-        colorType = kN32_SkColorType;
+    } else {
+        LOG_ALWAYS_FATAL("Unsupported color type.");
     }
 
     GrBackendRenderTarget backendRT(frame.width(), frame.height(), 0, STENCIL_BUFFER_SIZE, fboInfo);
@@ -90,8 +91,7 @@
             nullptr, &props));
 
     SkiaPipeline::updateLighting(lightGeometry, lightInfo);
-    renderFrame(*layerUpdateQueue, dirty, renderNodes, opaque, wideColorGamut, contentDrawBounds,
-                surface);
+    renderFrame(*layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface);
     layerUpdateQueue->clear();
 
     // Draw visual debugging features
@@ -128,77 +128,9 @@
     return *requireSwap;
 }
 
-bool SkiaOpenGLPipeline::copyLayerInto(DeferredLayerUpdater* deferredLayer, SkBitmap* bitmap) {
-    if (!mRenderThread.getGrContext()) {
-        return false;
-    }
-
-    // acquire most recent buffer for drawing
-    deferredLayer->updateTexImage();
-    deferredLayer->apply();
-
-    // drop the colorSpace as we only support readback into sRGB or extended sRGB
-    SkImageInfo surfaceInfo = bitmap->info().makeColorSpace(nullptr);
-
-    /* This intermediate surface is present to work around a bug in SwiftShader that
-     * prevents us from reading the contents of the layer's texture directly. The
-     * workaround involves first rendering that texture into an intermediate buffer and
-     * then reading from the intermediate buffer into the bitmap.
-     */
-    sk_sp<SkSurface> tmpSurface = SkSurface::MakeRenderTarget(mRenderThread.getGrContext(),
-                                                              SkBudgeted::kYes, surfaceInfo);
-
-    if (!tmpSurface.get()) {
-        surfaceInfo = surfaceInfo.makeColorType(SkColorType::kN32_SkColorType);
-        tmpSurface = SkSurface::MakeRenderTarget(mRenderThread.getGrContext(), SkBudgeted::kYes,
-                                                 surfaceInfo);
-        if (!tmpSurface.get()) {
-            ALOGW("Unable to readback GPU contents into the provided bitmap");
-            return false;
-        }
-    }
-
-    Layer* layer = deferredLayer->backingLayer();
-    const SkRect dstRect = SkRect::MakeIWH(bitmap->width(), bitmap->height());
-    if (LayerDrawable::DrawLayer(mRenderThread.getGrContext(), tmpSurface->getCanvas(), layer,
-                                 &dstRect)) {
-        sk_sp<SkImage> tmpImage = tmpSurface->makeImageSnapshot();
-        if (tmpImage->readPixels(surfaceInfo, bitmap->getPixels(), bitmap->rowBytes(), 0, 0)) {
-            bitmap->notifyPixelsChanged();
-            return true;
-        }
-
-        // if we fail to readback from the GPU directly (e.g. 565) then we attempt to read into 8888
-        // and then draw that into the destination format before giving up.
-        SkBitmap tmpBitmap;
-        SkImageInfo bitmapInfo =
-                SkImageInfo::MakeN32(bitmap->width(), bitmap->height(), bitmap->alphaType());
-        if (tmpBitmap.tryAllocPixels(bitmapInfo) &&
-            tmpImage->readPixels(bitmapInfo, tmpBitmap.getPixels(), tmpBitmap.rowBytes(), 0, 0)) {
-            SkCanvas canvas(*bitmap);
-            SkPaint paint;
-            paint.setBlendMode(SkBlendMode::kSrc);
-            canvas.drawBitmap(tmpBitmap, 0, 0, &paint);
-            bitmap->notifyPixelsChanged();
-            return true;
-        }
-    }
-
-    return false;
-}
-
-static Layer* createLayer(RenderState& renderState, uint32_t layerWidth, uint32_t layerHeight,
-                          sk_sp<SkColorFilter> colorFilter, int alpha, SkBlendMode mode,
-                          bool blend) {
-    GlLayer* layer =
-            new GlLayer(renderState, layerWidth, layerHeight, colorFilter, alpha, mode, blend);
-    layer->generateTexture();
-    return layer;
-}
-
 DeferredLayerUpdater* SkiaOpenGLPipeline::createTextureLayer() {
     mRenderThread.requireGlContext();
-    return new DeferredLayerUpdater(mRenderThread.renderState(), createLayer, Layer::Api::OpenGL);
+    return new DeferredLayerUpdater(mRenderThread.renderState());
 }
 
 void SkiaOpenGLPipeline::onStop() {
@@ -216,8 +148,7 @@
 
     if (surface) {
         mRenderThread.requireGlContext();
-        const bool wideColorGamut = colorMode == ColorMode::WideColorGamut;
-        mEglSurface = mEglManager.createSurface(surface, wideColorGamut);
+        mEglSurface = mEglManager.createSurface(surface, colorMode);
     }
 
     if (mEglSurface != EGL_NO_SURFACE) {
@@ -237,6 +168,14 @@
     return CC_LIKELY(mEglManager.hasEglContext());
 }
 
+SkColorType SkiaOpenGLPipeline::getSurfaceColorType() const {
+    return mEglManager.getSurfaceColorType();
+}
+
+sk_sp<SkColorSpace> SkiaOpenGLPipeline::getSurfaceColorSpace() {
+    return mEglManager.getSurfaceColorSpace();
+}
+
 void SkiaOpenGLPipeline::invokeFunctor(const RenderThread& thread, Functor* functor) {
     DrawGlInfo::Mode mode = DrawGlInfo::kModeProcessNoContext;
     if (thread.eglManager().hasEglContext()) {
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h
index 2e2e152..fbdf313 100644
--- a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h
@@ -34,19 +34,19 @@
     renderthread::Frame getFrame() override;
     bool draw(const renderthread::Frame& frame, const SkRect& screenDirty, const SkRect& dirty,
               const LightGeometry& lightGeometry, LayerUpdateQueue* layerUpdateQueue,
-              const Rect& contentDrawBounds, bool opaque, bool wideColorGamut,
-              const LightInfo& lightInfo,
+              const Rect& contentDrawBounds, bool opaque, const LightInfo& lightInfo,
               const std::vector<sp<RenderNode> >& renderNodes,
               FrameInfoVisualizer* profiler) override;
     bool swapBuffers(const renderthread::Frame& frame, bool drew, const SkRect& screenDirty,
                      FrameInfo* currentFrameInfo, bool* requireSwap) override;
-    bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) override;
     DeferredLayerUpdater* createTextureLayer() override;
     bool setSurface(Surface* window, renderthread::SwapBehavior swapBehavior,
                     renderthread::ColorMode colorMode) override;
     void onStop() override;
     bool isSurfaceReady() override;
     bool isContextReady() override;
+    SkColorType getSurfaceColorType() const override;
+    sk_sp<SkColorSpace> getSurfaceColorSpace() override;
 
     static void invokeFunctor(const renderthread::RenderThread& thread, Functor* functor);
 
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLReadback.cpp b/libs/hwui/pipeline/skia/SkiaOpenGLReadback.cpp
deleted file mode 100644
index f2f5056..0000000
--- a/libs/hwui/pipeline/skia/SkiaOpenGLReadback.cpp
+++ /dev/null
@@ -1,147 +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.
- */
-
-#include "SkiaOpenGLReadback.h"
-
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-#include <GrBackendSurface.h>
-#include <SkCanvas.h>
-#include <SkSurface.h>
-#include <gl/GrGLInterface.h>
-#include <gl/GrGLTypes.h>
-#include "DeviceInfo.h"
-#include "Matrix.h"
-#include "Properties.h"
-#include "utils/MathUtils.h"
-
-using namespace android::uirenderer::renderthread;
-
-namespace android {
-namespace uirenderer {
-namespace skiapipeline {
-
-CopyResult SkiaOpenGLReadback::copyImageInto(EGLImageKHR eglImage, const Matrix4& imgTransform,
-                                             int imgWidth, int imgHeight, const Rect& srcRect,
-                                             SkBitmap* bitmap) {
-    GLuint sourceTexId;
-    glGenTextures(1, &sourceTexId);
-    glBindTexture(GL_TEXTURE_EXTERNAL_OES, sourceTexId);
-    glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, eglImage);
-
-    sk_sp<GrContext> grContext = sk_ref_sp(mRenderThread.getGrContext());
-    if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaVulkan) {
-        sk_sp<const GrGLInterface> glInterface(GrGLCreateNativeInterface());
-        LOG_ALWAYS_FATAL_IF(!glInterface.get());
-        grContext = GrContext::MakeGL(std::move(glInterface));
-    } else {
-        grContext->resetContext();
-    }
-
-    if (bitmap->colorType() == kRGBA_F16_SkColorType &&
-            !grContext->colorTypeSupportedAsSurface(bitmap->colorType())) {
-        ALOGW("Can't copy surface into bitmap, RGBA_F16 config is not supported");
-        return CopyResult::DestinationInvalid;
-    }
-
-    GrGLTextureInfo externalTexture;
-    externalTexture.fTarget = GL_TEXTURE_EXTERNAL_OES;
-    externalTexture.fID = sourceTexId;
-    switch (bitmap->colorType()) {
-        case kRGBA_F16_SkColorType:
-            externalTexture.fFormat = GL_RGBA16F;
-            break;
-        case kN32_SkColorType:
-        default:
-            externalTexture.fFormat = GL_RGBA8;
-            break;
-    }
-
-    GrBackendTexture backendTexture(imgWidth, imgHeight, GrMipMapped::kNo, externalTexture);
-
-    CopyResult copyResult = CopyResult::UnknownError;
-    sk_sp<SkImage> image(SkImage::MakeFromAdoptedTexture(grContext.get(), backendTexture,
-                                                         kTopLeft_GrSurfaceOrigin,
-                                                         bitmap->colorType()));
-    if (image) {
-        int displayedWidth = imgWidth, displayedHeight = imgHeight;
-        // If this is a 90 or 270 degree rotation we need to swap width/height to get the device
-        // size.
-        if (imgTransform[Matrix4::kSkewX] >= 0.5f || imgTransform[Matrix4::kSkewX] <= -0.5f) {
-            std::swap(displayedWidth, displayedHeight);
-        }
-        SkRect skiaDestRect = SkRect::MakeWH(bitmap->width(), bitmap->height());
-        SkRect skiaSrcRect = srcRect.toSkRect();
-        if (skiaSrcRect.isEmpty()) {
-            skiaSrcRect = SkRect::MakeIWH(displayedWidth, displayedHeight);
-        }
-        bool srcNotEmpty = skiaSrcRect.intersect(SkRect::MakeIWH(displayedWidth, displayedHeight));
-
-        if (srcNotEmpty) {
-            SkMatrix textureMatrixInv;
-            imgTransform.copyTo(textureMatrixInv);
-            // TODO: after skia bug https://bugs.chromium.org/p/skia/issues/detail?id=7075 is fixed
-            // use bottom left origin and remove flipV and invert transformations.
-            SkMatrix flipV;
-            flipV.setAll(1, 0, 0, 0, -1, 1, 0, 0, 1);
-            textureMatrixInv.preConcat(flipV);
-            textureMatrixInv.preScale(1.0f / displayedWidth, 1.0f / displayedHeight);
-            textureMatrixInv.postScale(imgWidth, imgHeight);
-            SkMatrix textureMatrix;
-            if (!textureMatrixInv.invert(&textureMatrix)) {
-                textureMatrix = textureMatrixInv;
-            }
-
-            textureMatrixInv.mapRect(&skiaSrcRect);
-            textureMatrixInv.mapRect(&skiaDestRect);
-
-            // we render in an offscreen buffer to scale and to avoid an issue b/62262733
-            // with reading incorrect data from EGLImage backed SkImage (likely a driver bug)
-            sk_sp<SkSurface> scaledSurface =
-                    SkSurface::MakeRenderTarget(grContext.get(), SkBudgeted::kYes, bitmap->info());
-            SkPaint paint;
-            paint.setBlendMode(SkBlendMode::kSrc);
-            // Apply a filter, which is matching OpenGL pipeline readback behaviour. Filter usage
-            // is codified by tests using golden images like DecodeAccuracyTest.
-            bool disableFilter = MathUtils::areEqual(skiaSrcRect.width(), skiaDestRect.width())
-                    && MathUtils::areEqual(skiaSrcRect.height(), skiaDestRect.height());
-            if (!disableFilter) {
-                paint.setFilterQuality(kLow_SkFilterQuality);
-            }
-            scaledSurface->getCanvas()->concat(textureMatrix);
-            scaledSurface->getCanvas()->drawImageRect(image, skiaSrcRect, skiaDestRect, &paint,
-                                                      SkCanvas::kFast_SrcRectConstraint);
-
-            image = scaledSurface->makeImageSnapshot();
-
-            if (image->readPixels(bitmap->info(), bitmap->getPixels(), bitmap->rowBytes(), 0, 0)) {
-                bitmap->notifyPixelsChanged();
-                copyResult = CopyResult::Success;
-            }
-        }
-    }
-
-    // make sure that we have deleted the texture (in the SkImage) before we
-    // destroy the EGLImage that it was created from
-    image.reset();
-    glFinish();
-
-    return copyResult;
-}
-
-} /* namespace skiapipeline */
-} /* namespace uirenderer */
-} /* namespace android */
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLReadback.h b/libs/hwui/pipeline/skia/SkiaOpenGLReadback.h
deleted file mode 100644
index 1ce4773..0000000
--- a/libs/hwui/pipeline/skia/SkiaOpenGLReadback.h
+++ /dev/null
@@ -1,37 +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.
- */
-
-#pragma once
-
-#include "EglReadback.h"
-
-namespace android {
-namespace uirenderer {
-namespace skiapipeline {
-
-class SkiaOpenGLReadback : public EglReadback {
-public:
-    SkiaOpenGLReadback(renderthread::RenderThread& thread) : EglReadback(thread) {}
-
-protected:
-    virtual CopyResult copyImageInto(EGLImageKHR eglImage, const Matrix4& imgTransform,
-                                     int imgWidth, int imgHeight, const Rect& srcRect,
-                                     SkBitmap* bitmap) override;
-};
-
-} /* namespace skiapipeline */
-} /* namespace uirenderer */
-} /* namespace android */
diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.cpp b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
index 988981d..7f8abb8 100644
--- a/libs/hwui/pipeline/skia/SkiaPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
@@ -83,16 +83,15 @@
 
 void SkiaPipeline::renderLayers(const LightGeometry& lightGeometry,
                                 LayerUpdateQueue* layerUpdateQueue, bool opaque,
-                                bool wideColorGamut, const LightInfo& lightInfo) {
+                                const LightInfo& lightInfo) {
     updateLighting(lightGeometry, lightInfo);
     ATRACE_NAME("draw layers");
     renderVectorDrawableCache();
-    renderLayersImpl(*layerUpdateQueue, opaque, wideColorGamut);
+    renderLayersImpl(*layerUpdateQueue, opaque);
     layerUpdateQueue->clear();
 }
 
-void SkiaPipeline::renderLayersImpl(const LayerUpdateQueue& layers, bool opaque,
-                                    bool wideColorGamut) {
+void SkiaPipeline::renderLayersImpl(const LayerUpdateQueue& layers, bool opaque) {
     sk_sp<GrContext> cachedContext;
 
     // Render all layers that need to be updated, in order.
@@ -161,7 +160,7 @@
 }
 
 bool SkiaPipeline::createOrUpdateLayer(RenderNode* node, const DamageAccumulator& damageAccumulator,
-                                       bool wideColorGamut, ErrorHandler* errorHandler) {
+                                       ErrorHandler* errorHandler) {
     // compute the size of the surface (i.e. texture) to be allocated for this layer
     const int surfaceWidth = ceilf(node->getWidth() / float(LAYER_SIZE)) * LAYER_SIZE;
     const int surfaceHeight = ceilf(node->getHeight() / float(LAYER_SIZE)) * LAYER_SIZE;
@@ -169,12 +168,8 @@
     SkSurface* layer = node->getLayerSurface();
     if (!layer || layer->width() != surfaceWidth || layer->height() != surfaceHeight) {
         SkImageInfo info;
-        if (wideColorGamut) {
-            info = SkImageInfo::Make(surfaceWidth, surfaceHeight, kRGBA_F16_SkColorType,
-                                     kPremul_SkAlphaType);
-        } else {
-            info = SkImageInfo::MakeN32Premul(surfaceWidth, surfaceHeight);
-        }
+        info = SkImageInfo::Make(surfaceWidth, surfaceHeight, getSurfaceColorType(),
+                                 kPremul_SkAlphaType);
         SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
         SkASSERT(mRenderThread.getGrContext() != nullptr);
         node->setLayerSurface(SkSurface::MakeRenderTarget(mRenderThread.getGrContext(),
@@ -321,19 +316,18 @@
 
 void SkiaPipeline::renderFrame(const LayerUpdateQueue& layers, const SkRect& clip,
                                const std::vector<sp<RenderNode>>& nodes, bool opaque,
-                               bool wideColorGamut, const Rect& contentDrawBounds,
-                               sk_sp<SkSurface> surface) {
+                               const Rect& contentDrawBounds, sk_sp<SkSurface> surface) {
     renderVectorDrawableCache();
 
     // draw all layers up front
-    renderLayersImpl(layers, opaque, wideColorGamut);
+    renderLayersImpl(layers, opaque);
 
     // initialize the canvas for the current frame, that might be a recording canvas if SKP
     // capture is enabled.
     std::unique_ptr<SkPictureRecorder> recorder;
     SkCanvas* canvas = tryCapture(surface.get());
 
-    renderFrameImpl(layers, clip, nodes, opaque, wideColorGamut, contentDrawBounds, canvas);
+    renderFrameImpl(layers, clip, nodes, opaque, contentDrawBounds, canvas);
 
     endCapture(surface.get());
 
@@ -354,13 +348,12 @@
 
 void SkiaPipeline::renderFrameImpl(const LayerUpdateQueue& layers, const SkRect& clip,
                                    const std::vector<sp<RenderNode>>& nodes, bool opaque,
-                                   bool wideColorGamut, const Rect& contentDrawBounds,
-                                   SkCanvas* canvas) {
+                                   const Rect& contentDrawBounds, SkCanvas* canvas) {
     SkAutoCanvasRestore saver(canvas, true);
     canvas->androidFramework_setDeviceClipRestriction(clip.roundOut());
 
     // STOPSHIP: Revert, temporary workaround to clear always F16 frame buffer for b/74976293
-    if (!opaque || wideColorGamut) {
+    if (!opaque || getSurfaceColorType() == kRGBA_F16_SkColorType) {
         canvas->clear(SK_ColorTRANSPARENT);
     }
 
@@ -493,7 +486,7 @@
     // each time a pixel would have been drawn.
     // Pass true for opaque so we skip the clear - the overdrawCanvas is already zero
     // initialized.
-    renderFrameImpl(layers, clip, nodes, true, false, contentDrawBounds, &overdrawCanvas);
+    renderFrameImpl(layers, clip, nodes, true, contentDrawBounds, &overdrawCanvas);
     sk_sp<SkImage> counts = offscreen->makeImageSnapshot();
 
     // Draw overdraw colors to the canvas.  The color filter will convert counts to colors.
diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.h b/libs/hwui/pipeline/skia/SkiaPipeline.h
index 8c9c803..b78dea1 100644
--- a/libs/hwui/pipeline/skia/SkiaPipeline.h
+++ b/libs/hwui/pipeline/skia/SkiaPipeline.h
@@ -42,15 +42,14 @@
     void unpinImages() override;
     void onPrepareTree() override;
 
-    void renderLayers(const LightGeometry& lightGeometry,
-                      LayerUpdateQueue* layerUpdateQueue, bool opaque, bool wideColorGamut,
-                      const LightInfo& lightInfo) override;
+    void renderLayers(const LightGeometry& lightGeometry, LayerUpdateQueue* layerUpdateQueue,
+                      bool opaque, const LightInfo& lightInfo) override;
 
     bool createOrUpdateLayer(RenderNode* node, const DamageAccumulator& damageAccumulator,
-                             bool wideColorGamut, ErrorHandler* errorHandler) override;
+                             ErrorHandler* errorHandler) override;
 
     void renderFrame(const LayerUpdateQueue& layers, const SkRect& clip,
-                     const std::vector<sp<RenderNode>>& nodes, bool opaque, bool wideColorGamut,
+                     const std::vector<sp<RenderNode>>& nodes, bool opaque,
                      const Rect& contentDrawBounds, sk_sp<SkSurface> surface);
 
     std::vector<VectorDrawableRoot*>* getVectorDrawables() { return &mVectorDrawables; }
@@ -59,7 +58,7 @@
 
     static void prepareToDraw(const renderthread::RenderThread& thread, Bitmap* bitmap);
 
-    void renderLayersImpl(const LayerUpdateQueue& layers, bool opaque, bool wideColorGamut);
+    void renderLayersImpl(const LayerUpdateQueue& layers, bool opaque);
 
     static float getLightRadius() {
         if (CC_UNLIKELY(Properties::overrideLightRadius > 0)) {
@@ -112,7 +111,7 @@
 
 private:
     void renderFrameImpl(const LayerUpdateQueue& layers, const SkRect& clip,
-                         const std::vector<sp<RenderNode>>& nodes, bool opaque, bool wideColorGamut,
+                         const std::vector<sp<RenderNode>>& nodes, bool opaque,
                          const Rect& contentDrawBounds, SkCanvas* canvas);
 
     /**
diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
index b2519fe..5cbe33d 100644
--- a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
@@ -20,7 +20,6 @@
 #include "Readback.h"
 #include "SkiaPipeline.h"
 #include "SkiaProfileRenderer.h"
-#include "VkLayer.h"
 #include "renderstate/RenderState.h"
 #include "renderthread/Frame.h"
 
@@ -64,8 +63,7 @@
 bool SkiaVulkanPipeline::draw(const Frame& frame, const SkRect& screenDirty, const SkRect& dirty,
                               const LightGeometry& lightGeometry,
                               LayerUpdateQueue* layerUpdateQueue, const Rect& contentDrawBounds,
-                              bool opaque, bool wideColorGamut,
-                              const LightInfo& lightInfo,
+                              bool opaque, const LightInfo& lightInfo,
                               const std::vector<sp<RenderNode>>& renderNodes,
                               FrameInfoVisualizer* profiler) {
     sk_sp<SkSurface> backBuffer = mVkSurface->getBackBufferSurface();
@@ -73,8 +71,7 @@
         return false;
     }
     SkiaPipeline::updateLighting(lightGeometry, lightInfo);
-    renderFrame(*layerUpdateQueue, dirty, renderNodes, opaque, wideColorGamut, contentDrawBounds,
-                backBuffer);
+    renderFrame(*layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, backBuffer);
     layerUpdateQueue->clear();
 
     // Draw visual debugging features
@@ -109,21 +106,10 @@
     return *requireSwap;
 }
 
-bool SkiaVulkanPipeline::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) {
-    // TODO: implement copyLayerInto for vulkan.
-    return false;
-}
-
-static Layer* createLayer(RenderState& renderState, uint32_t layerWidth, uint32_t layerHeight,
-                          sk_sp<SkColorFilter> colorFilter, int alpha, SkBlendMode mode,
-                          bool blend) {
-    return new VkLayer(renderState, layerWidth, layerHeight, colorFilter, alpha, mode, blend);
-}
-
 DeferredLayerUpdater* SkiaVulkanPipeline::createTextureLayer() {
     mVkManager.initialize();
 
-    return new DeferredLayerUpdater(mRenderThread.renderState(), createLayer, Layer::Api::Vulkan);
+    return new DeferredLayerUpdater(mRenderThread.renderState());
 }
 
 void SkiaVulkanPipeline::onStop() {}
@@ -151,6 +137,14 @@
     return CC_LIKELY(mVkManager.hasVkContext());
 }
 
+SkColorType SkiaVulkanPipeline::getSurfaceColorType() const {
+    return mVkManager.getSurfaceColorType();
+}
+
+sk_sp<SkColorSpace> SkiaVulkanPipeline::getSurfaceColorSpace() {
+    return mVkManager.getSurfaceColorSpace();
+}
+
 void SkiaVulkanPipeline::invokeFunctor(const RenderThread& thread, Functor* functor) {
     // TODO: we currently don't support OpenGL WebView's
     DrawGlInfo::Mode mode = DrawGlInfo::kModeProcessNoContext;
diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h
index 7806b42..6e723a8 100644
--- a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h
+++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h
@@ -32,19 +32,19 @@
     renderthread::Frame getFrame() override;
     bool draw(const renderthread::Frame& frame, const SkRect& screenDirty, const SkRect& dirty,
               const LightGeometry& lightGeometry, LayerUpdateQueue* layerUpdateQueue,
-              const Rect& contentDrawBounds, bool opaque, bool wideColorGamut,
-              const LightInfo& lightInfo,
+              const Rect& contentDrawBounds, bool opaque, const LightInfo& lightInfo,
               const std::vector<sp<RenderNode> >& renderNodes,
               FrameInfoVisualizer* profiler) override;
     bool swapBuffers(const renderthread::Frame& frame, bool drew, const SkRect& screenDirty,
                      FrameInfo* currentFrameInfo, bool* requireSwap) override;
-    bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) override;
     DeferredLayerUpdater* createTextureLayer() override;
     bool setSurface(Surface* window, renderthread::SwapBehavior swapBehavior,
                     renderthread::ColorMode colorMode) override;
     void onStop() override;
     bool isSurfaceReady() override;
     bool isContextReady() override;
+    SkColorType getSurfaceColorType() const override;
+    sk_sp<SkColorSpace> getSurfaceColorSpace() override;
 
     static void invokeFunctor(const renderthread::RenderThread& thread, Functor* functor);
     static sk_sp<Bitmap> allocateHardwareBitmap(renderthread::RenderThread& thread,
diff --git a/libs/hwui/pipeline/skia/SkiaVulkanReadback.h b/libs/hwui/pipeline/skia/SkiaVulkanReadback.h
deleted file mode 100644
index 65b89d6..0000000
--- a/libs/hwui/pipeline/skia/SkiaVulkanReadback.h
+++ /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.
- */
-
-#pragma once
-
-#include "Readback.h"
-
-namespace android {
-namespace uirenderer {
-namespace skiapipeline {
-
-class SkiaVulkanReadback : public Readback {
-public:
-    SkiaVulkanReadback(renderthread::RenderThread& thread) : Readback(thread) {}
-
-    virtual CopyResult copySurfaceInto(Surface& surface, const Rect& srcRect,
-            SkBitmap* bitmap) override {
-        //TODO: implement Vulkan readback.
-        return CopyResult::UnknownError;
-    }
-
-    virtual CopyResult copyGraphicBufferInto(GraphicBuffer* graphicBuffer,
-            SkBitmap* bitmap) override {
-        //TODO: implement Vulkan readback.
-        return CopyResult::UnknownError;
-    }
-};
-
-} /* namespace skiapipeline */
-} /* namespace uirenderer */
-} /* namespace android */
diff --git a/libs/hwui/renderstate/PixelBufferState.cpp b/libs/hwui/renderstate/PixelBufferState.cpp
deleted file mode 100644
index 3a6efb8..0000000
--- a/libs/hwui/renderstate/PixelBufferState.cpp
+++ /dev/null
@@ -1,42 +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 "renderstate/PixelBufferState.h"
-
-namespace android {
-namespace uirenderer {
-
-PixelBufferState::PixelBufferState() : mCurrentPixelBuffer(0) {}
-
-bool PixelBufferState::bind(GLuint buffer) {
-    if (mCurrentPixelBuffer != buffer) {
-        glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer);
-        mCurrentPixelBuffer = buffer;
-        return true;
-    }
-    return false;
-}
-
-bool PixelBufferState::unbind() {
-    if (mCurrentPixelBuffer) {
-        glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
-        mCurrentPixelBuffer = 0;
-        return true;
-    }
-    return false;
-}
-
-} /* namespace uirenderer */
-} /* namespace android */
diff --git a/libs/hwui/renderstate/PixelBufferState.h b/libs/hwui/renderstate/PixelBufferState.h
deleted file mode 100644
index f7ae6c5..0000000
--- a/libs/hwui/renderstate/PixelBufferState.h
+++ /dev/null
@@ -1,38 +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 RENDERSTATE_PIXELBUFFERSTATE_H
-#define RENDERSTATE_PIXELBUFFERSTATE_H
-
-#include <GLES3/gl3.h>
-
-namespace android {
-namespace uirenderer {
-
-class PixelBufferState {
-    friend class Caches;  // TODO: move to RenderState
-public:
-    bool bind(GLuint buffer);
-    bool unbind();
-
-private:
-    PixelBufferState();
-    GLuint mCurrentPixelBuffer;
-};
-
-} /* namespace uirenderer */
-} /* namespace android */
-
-#endif  // RENDERSTATE_PIXELBUFFERSTATE_H
diff --git a/libs/hwui/renderstate/RenderState.cpp b/libs/hwui/renderstate/RenderState.cpp
index 3be84f58..b524bcb 100644
--- a/libs/hwui/renderstate/RenderState.cpp
+++ b/libs/hwui/renderstate/RenderState.cpp
@@ -16,8 +16,6 @@
 #include "renderstate/RenderState.h"
 #include <GpuMemoryTracker.h>
 #include "DeferredLayerUpdater.h"
-#include "GlLayer.h"
-#include "VkLayer.h"
 #include "Snapshot.h"
 
 #include "renderthread/CanvasContext.h"
@@ -39,44 +37,11 @@
 RenderState::~RenderState() {
 }
 
-void RenderState::onGLContextCreated() {
-    GpuMemoryTracker::onGpuContextCreated();
-
-    // This is delayed because the first access of Caches makes GL calls
-    if (!mCaches) {
-        mCaches = &Caches::createInstance(*this);
-    }
-    mCaches->init();
-}
-
-static void layerLostGlContext(Layer* layer) {
-    LOG_ALWAYS_FATAL_IF(layer->getApi() != Layer::Api::OpenGL,
-                        "layerLostGlContext on non GL layer");
-    static_cast<GlLayer*>(layer)->onGlContextLost();
-}
-
-void RenderState::onGLContextDestroyed() {
-    // TODO: reset all cached state in state objects
-    std::for_each(mActiveLayers.begin(), mActiveLayers.end(), layerLostGlContext);
-
-    mCaches->terminate();
-
-    destroyLayersInUpdater();
-    GpuMemoryTracker::onGpuContextDestroyed();
-}
-
-void RenderState::onVkContextCreated() {
+void RenderState::onContextCreated() {
     GpuMemoryTracker::onGpuContextCreated();
 }
 
-static void layerDestroyedVkContext(Layer* layer) {
-    LOG_ALWAYS_FATAL_IF(layer->getApi() != Layer::Api::Vulkan,
-                        "layerLostVkContext on non Vulkan layer");
-    static_cast<VkLayer*>(layer)->onVkContextDestroyed();
-}
-
-void RenderState::onVkContextDestroyed() {
-    std::for_each(mActiveLayers.begin(), mActiveLayers.end(), layerDestroyedVkContext);
+void RenderState::onContextDestroyed() {
     destroyLayersInUpdater();
     GpuMemoryTracker::onGpuContextDestroyed();
 }
@@ -85,10 +50,6 @@
     return mRenderThread.getGrContext();
 }
 
-void RenderState::flush(Caches::FlushMode mode) {
-    if (mCaches) mCaches->flush(mode);
-}
-
 void RenderState::onBitmapDestroyed(uint32_t pixelRefId) {
     // DEAD CODE
 }
@@ -126,42 +87,6 @@
     glDeleteFramebuffers(1, &fbo);
 }
 
-void RenderState::invokeFunctor(Functor* functor, DrawGlInfo::Mode mode, DrawGlInfo* info) {
-    if (mode == DrawGlInfo::kModeProcessNoContext) {
-        // If there's no context we don't need to interrupt as there's
-        // no gl state to save/restore
-        (*functor)(mode, info);
-    } else {
-        interruptForFunctorInvoke();
-        (*functor)(mode, info);
-        resumeFromFunctorInvoke();
-    }
-}
-
-void RenderState::interruptForFunctorInvoke() {
-    mCaches->textureState().resetActiveTexture();
-    debugOverdraw(false, false);
-    // TODO: We need a way to know whether the functor is sRGB aware (b/32072673)
-    if (mCaches->extensions().hasLinearBlending() && mCaches->extensions().hasSRGBWriteControl()) {
-        glDisable(GL_FRAMEBUFFER_SRGB_EXT);
-    }
-}
-
-void RenderState::resumeFromFunctorInvoke() {
-    if (mCaches->extensions().hasLinearBlending() && mCaches->extensions().hasSRGBWriteControl()) {
-        glEnable(GL_FRAMEBUFFER_SRGB_EXT);
-    }
-
-    glViewport(0, 0, mViewportWidth, mViewportHeight);
-    glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
-    debugOverdraw(false, false);
-
-    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
-
-    mCaches->textureState().activateTexture(0);
-    mCaches->textureState().resetBoundTextures();
-}
-
 void RenderState::debugOverdraw(bool enable, bool clear) {
     // DEAD CODE
 }
@@ -190,5 +115,9 @@
     // DEAD CODE
 }
 
+renderthread::RenderThread& RenderState::getRenderThread() {
+    return mRenderThread;
+}
+
 } /* namespace uirenderer */
 } /* namespace android */
diff --git a/libs/hwui/renderstate/RenderState.h b/libs/hwui/renderstate/RenderState.h
index 97785a4..f39aa4b 100644
--- a/libs/hwui/renderstate/RenderState.h
+++ b/libs/hwui/renderstate/RenderState.h
@@ -16,8 +16,6 @@
 #ifndef RENDERSTATE_H
 #define RENDERSTATE_H
 
-#include "Caches.h"
-#include "renderstate/PixelBufferState.h"
 #include "utils/Macros.h"
 
 #include <GLES2/gl2.h>
@@ -34,7 +32,6 @@
 namespace android {
 namespace uirenderer {
 
-class Caches;
 class Layer;
 class DeferredLayerUpdater;
 
@@ -44,22 +41,16 @@
 class RenderThread;
 }
 
-// TODO: Replace Cache's GL state tracking with this. For now it's more a thin
 // wrapper of Caches for users to migrate to.
 class RenderState {
     PREVENT_COPY_AND_ASSIGN(RenderState);
     friend class renderthread::RenderThread;
-    friend class Caches;
     friend class renderthread::CacheManager;
 
 public:
-    void onGLContextCreated();
-    void onGLContextDestroyed();
+    void onContextCreated();
+    void onContextDestroyed();
 
-    void onVkContextCreated();
-    void onVkContextDestroyed();
-
-    void flush(Caches::FlushMode flushMode);
     void onBitmapDestroyed(uint32_t pixelRefId);
 
     void setViewport(GLsizei width, GLsizei height);
@@ -70,8 +61,6 @@
     GLuint createFramebuffer();
     void deleteFramebuffer(GLuint fbo);
 
-    void invokeFunctor(Functor* functor, DrawGlInfo::Mode mode, DrawGlInfo* info);
-
     void debugOverdraw(bool enable, bool clear);
 
     void registerLayer(Layer* layer) { mActiveLayers.insert(layer); }
@@ -101,16 +90,15 @@
 
     void dump();
 
+    renderthread::RenderThread& getRenderThread();
+
 private:
-    void interruptForFunctorInvoke();
-    void resumeFromFunctorInvoke();
     void destroyLayersInUpdater();
 
     explicit RenderState(renderthread::RenderThread& thread);
     ~RenderState();
 
     renderthread::RenderThread& mRenderThread;
-    Caches* mCaches = nullptr;
 
     std::set<Layer*> mActiveLayers;
     std::set<DeferredLayerUpdater*> mActiveLayerUpdaters;
diff --git a/libs/hwui/renderstate/TextureState.cpp b/libs/hwui/renderstate/TextureState.cpp
deleted file mode 100644
index 470b4f5..0000000
--- a/libs/hwui/renderstate/TextureState.cpp
+++ /dev/null
@@ -1,147 +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 "renderstate/TextureState.h"
-
-#include "Caches.h"
-#include "utils/TraceUtils.h"
-
-#include <GLES3/gl3.h>
-#include <SkBitmap.h>
-#include <SkCanvas.h>
-#include <memory>
-
-namespace android {
-namespace uirenderer {
-
-// Width of mShadowLutTexture, defines how accurate the shadow alpha lookup table is
-static const int SHADOW_LUT_SIZE = 128;
-
-// Must define as many texture units as specified by kTextureUnitsCount
-const GLenum kTextureUnits[] = {GL_TEXTURE0, GL_TEXTURE1, GL_TEXTURE2, GL_TEXTURE3};
-
-TextureState::TextureState() : mTextureUnit(0) {
-    glActiveTexture(kTextureUnits[0]);
-    resetBoundTextures();
-
-    GLint maxTextureUnits;
-    glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
-    LOG_ALWAYS_FATAL_IF(maxTextureUnits < kTextureUnitsCount,
-                        "At least %d texture units are required!", kTextureUnitsCount);
-    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
-}
-
-TextureState::~TextureState() {
-    if (mShadowLutTexture != nullptr) {
-        mShadowLutTexture->deleteTexture();
-    }
-}
-
-/**
- * Maps shadow geometry 'alpha' varying (1 for darkest, 0 for transparent) to
- * darkness at that spot. Input values of 0->1 should be mapped within the same
- * range, but can affect the curve for a different visual falloff.
- *
- * This is used to populate the shadow LUT texture for quick lookup in the
- * shadow shader.
- */
-static float computeShadowOpacity(float ratio) {
-    // exponential falloff function provided by UX
-    float val = 1 - ratio;
-    return exp(-val * val * 4.0) - 0.018;
-}
-
-void TextureState::constructTexture(Caches& caches) {
-    if (mShadowLutTexture == nullptr) {
-        mShadowLutTexture.reset(new Texture(caches));
-
-        unsigned char bytes[SHADOW_LUT_SIZE];
-        for (int i = 0; i < SHADOW_LUT_SIZE; i++) {
-            float inputRatio = i / (SHADOW_LUT_SIZE - 1.0f);
-            bytes[i] = computeShadowOpacity(inputRatio) * 255;
-        }
-        mShadowLutTexture->upload(GL_ALPHA, SHADOW_LUT_SIZE, 1, GL_ALPHA, GL_UNSIGNED_BYTE, &bytes);
-        mShadowLutTexture->setFilter(GL_LINEAR);
-        mShadowLutTexture->setWrap(GL_CLAMP_TO_EDGE);
-    }
-}
-
-void TextureState::activateTexture(GLuint textureUnit) {
-    LOG_ALWAYS_FATAL_IF(textureUnit >= kTextureUnitsCount,
-                        "Tried to use texture unit index %d, only %d exist", textureUnit,
-                        kTextureUnitsCount);
-    if (mTextureUnit != textureUnit) {
-        glActiveTexture(kTextureUnits[textureUnit]);
-        mTextureUnit = textureUnit;
-    }
-}
-
-void TextureState::resetActiveTexture() {
-    mTextureUnit = -1;
-}
-
-void TextureState::bindTexture(GLuint texture) {
-    if (mBoundTextures[mTextureUnit] != texture) {
-        glBindTexture(GL_TEXTURE_2D, texture);
-        mBoundTextures[mTextureUnit] = texture;
-    }
-}
-
-void TextureState::bindTexture(GLenum target, GLuint texture) {
-    if (target == GL_TEXTURE_2D) {
-        bindTexture(texture);
-    } else {
-        // GLConsumer directly calls glBindTexture() with
-        // target=GL_TEXTURE_EXTERNAL_OES, don't cache this target
-        // since the cached state could be stale
-        glBindTexture(target, texture);
-    }
-}
-
-void TextureState::deleteTexture(GLuint texture) {
-    // When glDeleteTextures() is called on a currently bound texture,
-    // OpenGL ES specifies that the texture is then considered unbound
-    // Consider the following series of calls:
-    //
-    // glGenTextures -> creates texture name 2
-    // glBindTexture(2)
-    // glDeleteTextures(2) -> 2 is now unbound
-    // glGenTextures -> can return 2 again
-    //
-    // If we don't call glBindTexture(2) after the second glGenTextures
-    // call, any texture operation will be performed on the default
-    // texture (name=0)
-
-    unbindTexture(texture);
-
-    glDeleteTextures(1, &texture);
-}
-
-void TextureState::resetBoundTextures() {
-    for (int i = 0; i < kTextureUnitsCount; i++) {
-        mBoundTextures[i] = 0;
-    }
-}
-
-void TextureState::unbindTexture(GLuint texture) {
-    for (int i = 0; i < kTextureUnitsCount; i++) {
-        if (mBoundTextures[i] == texture) {
-            mBoundTextures[i] = 0;
-        }
-    }
-}
-
-} /* namespace uirenderer */
-} /* namespace android */
diff --git a/libs/hwui/renderstate/TextureState.h b/libs/hwui/renderstate/TextureState.h
deleted file mode 100644
index f1996d4..0000000
--- a/libs/hwui/renderstate/TextureState.h
+++ /dev/null
@@ -1,98 +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 RENDERSTATE_TEXTURESTATE_H
-#define RENDERSTATE_TEXTURESTATE_H
-
-#include "Texture.h"
-#include "Vertex.h"
-
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-#include <memory>
-
-namespace android {
-namespace uirenderer {
-
-class Texture;
-
-class TextureState {
-    friend class Caches;  // TODO: move to RenderState
-public:
-    void constructTexture(Caches& caches);
-
-    /**
-     * Activate the specified texture unit. The texture unit must
-     * be specified using an integer number (0 for GL_TEXTURE0 etc.)
-     */
-    void activateTexture(GLuint textureUnit);
-
-    /**
-     * Invalidate the cached value of the active texture unit.
-     */
-    void resetActiveTexture();
-
-    /**
-     * Binds the specified texture as a GL_TEXTURE_2D texture.
-     * All texture bindings must be performed with this method or
-     * bindTexture(GLenum, GLuint).
-     */
-    void bindTexture(GLuint texture);
-
-    /**
-     * Binds the specified texture with the specified render target.
-     * All texture bindings must be performed with this method or
-     * bindTexture(GLuint).
-     */
-    void bindTexture(GLenum target, GLuint texture);
-
-    /**
-     * Deletes the specified texture and clears it from the cache
-     * of bound textures.
-     * All textures must be deleted using this method.
-     */
-    void deleteTexture(GLuint texture);
-
-    /**
-     * Signals that the cache of bound textures should be cleared.
-     * Other users of the context may have altered which textures are bound.
-     */
-    void resetBoundTextures();
-
-    /**
-     * Clear the cache of bound textures.
-     */
-    void unbindTexture(GLuint texture);
-
-    Texture* getShadowLutTexture() { return mShadowLutTexture.get(); }
-
-private:
-    // total number of texture units available for use
-    static const int kTextureUnitsCount = 4;
-
-    TextureState();
-    ~TextureState();
-    GLuint mTextureUnit;
-
-    // Caches texture bindings for the GL_TEXTURE_2D target
-    GLuint mBoundTextures[kTextureUnitsCount];
-
-    std::unique_ptr<Texture> mShadowLutTexture;
-};
-
-} /* namespace uirenderer */
-} /* namespace android */
-
-#endif  // RENDERSTATE_BLEND_H
diff --git a/libs/hwui/renderthread/CacheManager.cpp b/libs/hwui/renderthread/CacheManager.cpp
index bec80b1e..7acc44c 100644
--- a/libs/hwui/renderthread/CacheManager.cpp
+++ b/libs/hwui/renderthread/CacheManager.cpp
@@ -21,6 +21,7 @@
 #include "RenderThread.h"
 #include "pipeline/skia/ShaderCache.h"
 #include "pipeline/skia/SkiaMemoryTracer.h"
+#include "Properties.h"
 #include "renderstate/RenderState.h"
 
 #include <GrContextOptions.h>
@@ -50,7 +51,6 @@
     mVectorDrawableAtlas = new skiapipeline::VectorDrawableAtlas(
             mMaxSurfaceArea / 2,
             skiapipeline::VectorDrawableAtlas::StorageMode::disallowSharedSurface);
-    skiapipeline::ShaderCache::get().initShaderDiskCache();
 }
 
 void CacheManager::reset(sk_sp<GrContext> context) {
@@ -103,7 +103,7 @@
     }
 };
 
-void CacheManager::configureContext(GrContextOptions* contextOptions) {
+void CacheManager::configureContext(GrContextOptions* contextOptions, const void* identity, ssize_t size) {
     contextOptions->fAllowPathMaskCaching = true;
 
     float screenMP = mMaxSurfaceArea / 1024.0f / 1024.0f;
@@ -133,7 +133,9 @@
         contextOptions->fExecutor = mTaskProcessor.get();
     }
 
-    contextOptions->fPersistentCache = &skiapipeline::ShaderCache::get();
+    auto& cache = skiapipeline::ShaderCache::get();
+    cache.initShaderDiskCache(identity, size);
+    contextOptions->fPersistentCache = &cache;
     contextOptions->fGpuPathRenderers &= ~GpuPathRenderers::kCoverageCounting;
 }
 
@@ -214,11 +216,12 @@
             log.appendFormat("  Layer Info:\n");
         }
 
+        const char* layerType = Properties::getRenderPipelineType() == RenderPipelineType::SkiaGL
+                ? "GlLayer" : "VkLayer";
         size_t layerMemoryTotal = 0;
         for (std::set<Layer*>::iterator it = renderState->mActiveLayers.begin();
              it != renderState->mActiveLayers.end(); it++) {
             const Layer* layer = *it;
-            const char* layerType = layer->getApi() == Layer::Api::OpenGL ? "GlLayer" : "VkLayer";
             log.appendFormat("    %s size %dx%d\n", layerType, layer->getWidth(),
                              layer->getHeight());
             layerMemoryTotal += layer->getWidth() * layer->getHeight() * 4;
diff --git a/libs/hwui/renderthread/CacheManager.h b/libs/hwui/renderthread/CacheManager.h
index 7d73352..35fc91a 100644
--- a/libs/hwui/renderthread/CacheManager.h
+++ b/libs/hwui/renderthread/CacheManager.h
@@ -44,7 +44,7 @@
 public:
     enum class TrimMemoryMode { Complete, UiHidden };
 
-    void configureContext(GrContextOptions* context);
+    void configureContext(GrContextOptions* context, const void* identity, ssize_t size);
     void trimMemory(TrimMemoryMode mode);
     void trimStaleResources();
     void dumpMemoryUsage(String8& log, const RenderState* renderState = nullptr);
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 5d72523..ea6a851 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -18,7 +18,6 @@
 #include <GpuMemoryTracker.h>
 
 #include "AnimationContext.h"
-#include "Caches.h"
 #include "EglManager.h"
 #include "Frame.h"
 #include "LayerUpdateQueue.h"
@@ -152,7 +151,8 @@
 
     mNativeSurface = std::move(surface);
 
-    ColorMode colorMode = mWideColorGamut ? ColorMode::WideColorGamut : ColorMode::Srgb;
+    // TODO(b/111436479) Introduce a way for app to specify DisplayColorGamut mode.
+    ColorMode colorMode = mWideColorGamut ? ColorMode::WideColorGamut : ColorMode::Legacy;
     bool hasSurface = mRenderPipeline->setSurface(mNativeSurface.get(), mSwapBehavior, colorMode);
 
     mFrameNumber = -1;
@@ -417,7 +417,7 @@
     SkRect windowDirty = computeDirtyRect(frame, &dirty);
 
     bool drew = mRenderPipeline->draw(frame, windowDirty, dirty, mLightGeometry, &mLayerUpdateQueue,
-                                      mContentDrawBounds, mOpaque, mWideColorGamut, mLightInfo,
+                                      mContentDrawBounds, mOpaque, mLightInfo,
                                       mRenderNodes, &(profiler()));
 
     int64_t frameCompleteNr = mFrameCompleteCallbacks.size() ? getFrameNumber() : -1;
@@ -495,13 +495,6 @@
     }
 
     GpuMemoryTracker::onFrameCompleted();
-#ifdef BUGREPORT_FONT_CACHE_USAGE
-    auto renderType = Properties::getRenderPipelineType();
-    if (RenderPipelineType::OpenGL == renderType) {
-        Caches& caches = Caches::getInstance();
-        caches.fontRenderer.getFontRenderer().historyTracker().frameCompleted();
-    }
-#endif
 }
 
 // Called by choreographer to do an RT-driven animation
@@ -563,17 +556,12 @@
     // purposes when the frame is actually drawn
     node->setPropertyFieldsDirty(RenderNode::GENERIC);
 
-    mRenderPipeline->renderLayers(mLightGeometry, &mLayerUpdateQueue, mOpaque, mWideColorGamut,
-                                  mLightInfo);
+    mRenderPipeline->renderLayers(mLightGeometry, &mLayerUpdateQueue, mOpaque, mLightInfo);
 
     node->incStrong(nullptr);
     mPrefetchedLayers.insert(node);
 }
 
-bool CanvasContext::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) {
-    return mRenderPipeline->copyLayerInto(layer, bitmap);
-}
-
 void CanvasContext::destroyHardwareResources() {
     stopDrawing();
     if (mRenderPipeline->isContextReady()) {
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 8ca54af..8448788 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -75,8 +75,7 @@
      */
     bool createOrUpdateLayer(RenderNode* node, const DamageAccumulator& dmgAccumulator,
                              ErrorHandler* errorHandler) {
-        return mRenderPipeline->createOrUpdateLayer(node, dmgAccumulator, mWideColorGamut,
-                errorHandler);
+        return mRenderPipeline->createOrUpdateLayer(node, dmgAccumulator, errorHandler);
     }
 
     /**
@@ -135,7 +134,6 @@
     void prepareAndDraw(RenderNode* node);
 
     void buildLayer(RenderNode* node);
-    bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap);
     void markLayerInUse(RenderNode* node);
 
     void destroyHardwareResources();
diff --git a/libs/hwui/renderthread/EglManager.cpp b/libs/hwui/renderthread/EglManager.cpp
index cd21822..8e44d63 100644
--- a/libs/hwui/renderthread/EglManager.cpp
+++ b/libs/hwui/renderthread/EglManager.cpp
@@ -18,7 +18,9 @@
 
 #include <cutils/properties.h>
 #include <log/log.h>
+#include <private/gui/SyncFeatures.h>
 #include <utils/Trace.h>
+#include "utils/Color.h"
 #include "utils/StringUtils.h"
 
 #include "DeviceInfo.h"
@@ -74,6 +76,7 @@
     bool pixelFormatFloat = false;
     bool glColorSpace = false;
     bool scRGB = false;
+    bool displayP3 = false;
     bool contextPriority = false;
     bool surfacelessContext = false;
 } EglExtensions;
@@ -124,6 +127,17 @@
     createPBufferSurface();
     makeCurrent(mPBufferSurface, nullptr, /* force */ true);
     DeviceInfo::initialize();
+
+    mSurfaceColorGamut = DataSpaceToColorGamut(
+        static_cast<android_dataspace>(DeviceInfo::get()->getTargetDataSpace()));
+
+    LOG_ALWAYS_FATAL_IF(mSurfaceColorGamut == SkColorSpace::kDCIP3_D65_Gamut &&
+                        !EglExtensions.displayP3, "EGL doesn't support Display P3.");
+
+    mSurfaceColorType = PixelFormatToColorType(
+        static_cast<android_pixel_format>(DeviceInfo::get()->getTargetPixelFormat()));
+    mSurfaceColorSpace = DataSpaceToColorSpace(
+        static_cast<android_dataspace>(DeviceInfo::get()->getTargetDataSpace()));
 }
 
 void EglManager::initExtensions() {
@@ -147,6 +161,7 @@
 #else
     EglExtensions.scRGB = extensions.has("EGL_EXT_gl_colorspace_scrgb");
 #endif
+    EglExtensions.displayP3 = extensions.has("EGL_EXT_gl_colorspace_display_p3");
     EglExtensions.contextPriority = extensions.has("EGL_IMG_context_priority");
     EglExtensions.surfacelessContext = extensions.has("EGL_KHR_surfaceless_context");
 }
@@ -159,6 +174,10 @@
     ALOGD("Swap behavior %d", static_cast<int>(mSwapBehavior));
     EGLint swapBehavior =
             (mSwapBehavior == SwapBehavior::Preserved) ? EGL_SWAP_BEHAVIOR_PRESERVED_BIT : 0;
+
+    // Note: The default pixel format is RGBA_8888, when other formats are
+    // available, we should check the target pixel format and configure the
+    // attributes list properly.
     EGLint attribs[] = {EGL_RENDERABLE_TYPE,
                         EGL_OPENGL_ES2_BIT,
                         EGL_RED_SIZE,
@@ -254,11 +273,12 @@
     }
 }
 
-EGLSurface EglManager::createSurface(EGLNativeWindowType window, bool wideColorGamut) {
+EGLSurface EglManager::createSurface(EGLNativeWindowType window, ColorMode colorMode) {
     LOG_ALWAYS_FATAL_IF(!hasEglContext(), "Not initialized");
 
-    wideColorGamut = wideColorGamut && EglExtensions.glColorSpace && EglExtensions.scRGB &&
-                     EglExtensions.pixelFormatFloat && EglExtensions.noConfigContext;
+    bool wideColorGamut = colorMode == ColorMode::WideColorGamut && EglExtensions.glColorSpace &&
+                          EglExtensions.scRGB && EglExtensions.pixelFormatFloat &&
+                          EglExtensions.noConfigContext;
 
     // The color space we want to use depends on whether linear blending is turned
     // on and whether the app has requested wide color gamut rendering. When wide
@@ -268,9 +288,9 @@
     // When wide gamut rendering is off:
     // - Blending is done by default in gamma space, which requires using a
     //   linear EGL color space (the GPU uses the color values as is)
-    // - If linear blending is on, we must use the sRGB EGL color space (the
-    //   GPU will perform sRGB to linear and linear to SRGB conversions before
-    //   and after blending)
+    // - If linear blending is on, we must use the non-linear EGL color space
+    //   (the GPU will perform sRGB to linear and linear to SRGB conversions
+    //   before and after blending)
     //
     // When wide gamut rendering is on we cannot rely on the GPU performing
     // linear blending for us. We use two different color spaces to tag the
@@ -278,7 +298,7 @@
     // - Gamma blending (default) requires the use of the scRGB-nl color space
     // - Linear blending requires the use of the scRGB color space
 
-    // Not all Android targets support the EGL_GL_COLOR_SPACE_KHR extension
+    // Not all Android targets support the EGL_GL_COLORSPACE_KHR extension
     // We insert to placeholders to set EGL_GL_COLORSPACE_KHR and its value.
     // According to section 3.4.1 of the EGL specification, the attributes
     // list is considered empty if the first entry is EGL_NONE
@@ -290,13 +310,21 @@
         if (wideColorGamut) {
             attribs[1] = EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT;
         } else {
-            attribs[1] = EGL_GL_COLORSPACE_SRGB_KHR;
+            if (mSurfaceColorGamut == SkColorSpace::kDCIP3_D65_Gamut) {
+                attribs[1] = EGL_GL_COLORSPACE_DISPLAY_P3_EXT;
+            } else {
+                attribs[1] = EGL_GL_COLORSPACE_SRGB_KHR;
+            }
         }
 #else
         if (wideColorGamut) {
             attribs[1] = EGL_GL_COLORSPACE_SCRGB_EXT;
         } else {
-            attribs[1] = EGL_GL_COLORSPACE_LINEAR_KHR;
+            if (mSurfaceColorGamut == SkColorSpace::kDCIP3_D65_Gamut) {
+                attribs[1] = EGL_GL_COLORSPACE_DISPLAY_P3_EXT;
+            } else {
+                attribs[1] = EGL_GL_COLORSPACE_LINEAR_KHR;
+            }
         }
 #endif
     }
@@ -464,6 +492,109 @@
     return preserved;
 }
 
+status_t EglManager::fenceWait(sp<Fence>& fence) {
+    if (!hasEglContext()) {
+        ALOGE("EglManager::fenceWait: EGLDisplay not initialized");
+        return INVALID_OPERATION;
+    }
+
+    if (SyncFeatures::getInstance().useWaitSync() &&
+        SyncFeatures::getInstance().useNativeFenceSync()) {
+        // Block GPU on the fence.
+        // Create an EGLSyncKHR from the current fence.
+        int fenceFd = fence->dup();
+        if (fenceFd == -1) {
+            ALOGE("EglManager::fenceWait: error dup'ing fence fd: %d", errno);
+            return -errno;
+        }
+        EGLint attribs[] = {
+            EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fenceFd,
+            EGL_NONE
+        };
+        EGLSyncKHR sync = eglCreateSyncKHR(mEglDisplay,
+                EGL_SYNC_NATIVE_FENCE_ANDROID, attribs);
+        if (sync == EGL_NO_SYNC_KHR) {
+            close(fenceFd);
+            ALOGE("EglManager::fenceWait: error creating EGL fence: %#x", eglGetError());
+            return UNKNOWN_ERROR;
+        }
+
+        // XXX: The spec draft is inconsistent as to whether this should
+        // return an EGLint or void.  Ignore the return value for now, as
+        // it's not strictly needed.
+        eglWaitSyncKHR(mEglDisplay, sync, 0);
+        EGLint eglErr = eglGetError();
+        eglDestroySyncKHR(mEglDisplay, sync);
+        if (eglErr != EGL_SUCCESS) {
+            ALOGE("EglManager::fenceWait: error waiting for EGL fence: %#x", eglErr);
+            return UNKNOWN_ERROR;
+        }
+    } else {
+        // Block CPU on the fence.
+        status_t err = fence->waitForever("EglManager::fenceWait");
+        if (err != NO_ERROR) {
+            ALOGE("EglManager::fenceWait: error waiting for fence: %d", err);
+            return err;
+        }
+    }
+    return OK;
+}
+
+status_t EglManager::createReleaseFence(bool useFenceSync, EGLSyncKHR* eglFence,
+        sp<Fence>& nativeFence) {
+    if (!hasEglContext()) {
+        ALOGE("EglManager::createReleaseFence: EGLDisplay not initialized");
+        return INVALID_OPERATION;
+    }
+
+    if (SyncFeatures::getInstance().useNativeFenceSync()) {
+        EGLSyncKHR sync = eglCreateSyncKHR(mEglDisplay,
+                EGL_SYNC_NATIVE_FENCE_ANDROID, nullptr);
+        if (sync == EGL_NO_SYNC_KHR) {
+            ALOGE("EglManager::createReleaseFence: error creating EGL fence: %#x",
+                    eglGetError());
+            return UNKNOWN_ERROR;
+        }
+        glFlush();
+        int fenceFd = eglDupNativeFenceFDANDROID(mEglDisplay, sync);
+        eglDestroySyncKHR(mEglDisplay, sync);
+        if (fenceFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
+            ALOGE("EglManager::createReleaseFence: error dup'ing native fence "
+                    "fd: %#x", eglGetError());
+            return UNKNOWN_ERROR;
+        }
+        nativeFence = new Fence(fenceFd);
+        *eglFence = EGL_NO_SYNC_KHR;
+    } else if (useFenceSync && SyncFeatures::getInstance().useFenceSync()) {
+        if (*eglFence != EGL_NO_SYNC_KHR) {
+            // There is already a fence for the current slot.  We need to
+            // wait on that before replacing it with another fence to
+            // ensure that all outstanding buffer accesses have completed
+            // before the producer accesses it.
+            EGLint result = eglClientWaitSyncKHR(mEglDisplay, *eglFence, 0, 1000000000);
+            if (result == EGL_FALSE) {
+                ALOGE("EglManager::createReleaseFence: error waiting for previous fence: %#x",
+                        eglGetError());
+                return UNKNOWN_ERROR;
+            } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
+                ALOGE("EglManager::createReleaseFence: timeout waiting for previous fence");
+                return TIMED_OUT;
+            }
+            eglDestroySyncKHR(mEglDisplay, *eglFence);
+        }
+
+        // Create a fence for the outstanding accesses in the current
+        // OpenGL ES context.
+        *eglFence = eglCreateSyncKHR(mEglDisplay, EGL_SYNC_FENCE_KHR, nullptr);
+        if (*eglFence == EGL_NO_SYNC_KHR) {
+            ALOGE("EglManager::createReleaseFence: error creating fence: %#x", eglGetError());
+            return UNKNOWN_ERROR;
+        }
+        glFlush();
+    }
+    return OK;
+}
+
 } /* namespace renderthread */
 } /* namespace uirenderer */
 } /* namespace android */
diff --git a/libs/hwui/renderthread/EglManager.h b/libs/hwui/renderthread/EglManager.h
index 8e8bb8b..e97228c 100644
--- a/libs/hwui/renderthread/EglManager.h
+++ b/libs/hwui/renderthread/EglManager.h
@@ -17,10 +17,14 @@
 #define EGLMANAGER_H
 
 #include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <SkImageInfo.h>
 #include <SkRect.h>
 #include <cutils/compiler.h>
+#include <ui/Fence.h>
 #include <ui/GraphicBuffer.h>
 #include <utils/StrongPointer.h>
+#include "IRenderPipeline.h"
 
 namespace android {
 namespace uirenderer {
@@ -43,7 +47,7 @@
 
     bool hasEglContext();
 
-    EGLSurface createSurface(EGLNativeWindowType window, bool wideColorGamut);
+    EGLSurface createSurface(EGLNativeWindowType window, ColorMode colorMode);
     void destroySurface(EGLSurface surface);
 
     void destroy();
@@ -66,6 +70,17 @@
 
     EGLDisplay eglDisplay() const { return mEglDisplay; }
 
+    // Inserts a wait on fence command into the OpenGL ES command stream. If EGL extension
+    // support is missing, block the CPU on the fence.
+    status_t fenceWait(sp<Fence>& fence);
+
+    // Creates a fence that is signaled, when all the pending GL commands are flushed.
+    // Depending on installed extensions, the result is either Android native fence or EGL fence.
+    status_t createReleaseFence(bool useFenceSync, EGLSyncKHR* eglFence, sp<Fence>& nativeFence);
+
+    SkColorType getSurfaceColorType() const { return mSurfaceColorType; }
+    sk_sp<SkColorSpace> getSurfaceColorSpace() { return mSurfaceColorSpace; }
+
 private:
 
     void initExtensions();
@@ -79,8 +94,10 @@
     EGLConfig mEglConfigWideGamut;
     EGLContext mEglContext;
     EGLSurface mPBufferSurface;
-
     EGLSurface mCurrentSurface;
+    SkColorSpace::Gamut mSurfaceColorGamut;
+    SkColorType mSurfaceColorType;
+    sk_sp<SkColorSpace> mSurfaceColorSpace;
 
     enum class SwapBehavior {
         Discard,
diff --git a/libs/hwui/renderthread/IRenderPipeline.h b/libs/hwui/renderthread/IRenderPipeline.h
index b94a758..0297c9c 100644
--- a/libs/hwui/renderthread/IRenderPipeline.h
+++ b/libs/hwui/renderthread/IRenderPipeline.h
@@ -16,11 +16,12 @@
 
 #pragma once
 
+#include "DamageAccumulator.h"
 #include "FrameInfoVisualizer.h"
 #include "LayerUpdateQueue.h"
+#include "Lighting.h"
 #include "SwapBehavior.h"
 #include "hwui/Bitmap.h"
-#include "thread/TaskManager.h"
 
 #include <SkRect.h>
 #include <utils/RefBase.h>
@@ -35,13 +36,25 @@
 
 class DeferredLayerUpdater;
 class ErrorHandler;
+class TaskManager;
 
 namespace renderthread {
 
 enum class MakeCurrentResult { AlreadyCurrent, Failed, Succeeded };
 
 enum class ColorMode {
-    Srgb,
+    // Legacy means HWUI will produce buffer with whatever platform prefers
+    // HWUI to produce, however, HWUI doesn't accurately convert color from
+    // source color space to destination color space, instead HWUI will take
+    // the pixel value directly and interpret it destination color space.
+    Legacy,
+    // DisplayColorGamut means HWUI will produce buffer with whatever platform
+    // prefers HWUI to produce and accurately convert color from source color
+    // space to destination color space.
+    DisplayColorGamut,
+    // WideColorGamut means HWUI would support rendering scRGB non-linear into
+    // a signed buffer with enough range to support the wide color gamut of the
+    // display.
     WideColorGamut,
     // Hdr
 };
@@ -55,12 +68,11 @@
     virtual bool draw(const Frame& frame, const SkRect& screenDirty, const SkRect& dirty,
                       const LightGeometry& lightGeometry,
                       LayerUpdateQueue* layerUpdateQueue, const Rect& contentDrawBounds,
-                      bool opaque, bool wideColorGamut, const LightInfo& lightInfo,
+                      bool opaque, const LightInfo& lightInfo,
                       const std::vector<sp<RenderNode>>& renderNodes,
                       FrameInfoVisualizer* profiler) = 0;
     virtual bool swapBuffers(const Frame& frame, bool drew, const SkRect& screenDirty,
                              FrameInfo* currentFrameInfo, bool* requireSwap) = 0;
-    virtual bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) = 0;
     virtual DeferredLayerUpdater* createTextureLayer() = 0;
     virtual bool setSurface(Surface* window, SwapBehavior swapBehavior, ColorMode colorMode) = 0;
     virtual void onStop() = 0;
@@ -68,15 +80,17 @@
     virtual bool isContextReady() = 0;
     virtual void onDestroyHardwareResources() = 0;
     virtual void renderLayers(const LightGeometry& lightGeometry,
-                              LayerUpdateQueue* layerUpdateQueue, bool opaque, bool wideColorGamut,
+                              LayerUpdateQueue* layerUpdateQueue, bool opaque,
                               const LightInfo& lightInfo) = 0;
     virtual TaskManager* getTaskManager() = 0;
     virtual bool createOrUpdateLayer(RenderNode* node, const DamageAccumulator& damageAccumulator,
-                                     bool wideColorGamut, ErrorHandler* errorHandler) = 0;
+                                     ErrorHandler* errorHandler) = 0;
     virtual bool pinImages(std::vector<SkImage*>& mutableImages) = 0;
     virtual bool pinImages(LsaVector<sk_sp<Bitmap>>& images) = 0;
     virtual void unpinImages() = 0;
     virtual void onPrepareTree() = 0;
+    virtual SkColorType getSurfaceColorType() const = 0;
+    virtual sk_sp<SkColorSpace> getSurfaceColorSpace() = 0;
 
     virtual ~IRenderPipeline() {}
 };
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index e3807e6..7a5348a 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -160,8 +160,10 @@
 }
 
 bool RenderProxy::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap& bitmap) {
-    return mRenderThread.queue().runSync(
-            [&]() -> bool { return mContext->copyLayerInto(layer, &bitmap); });
+    auto& thread = RenderThread::getInstance();
+    return thread.queue().runSync(
+            [&]() -> bool { return thread.readback().copyLayerInto(layer, &bitmap)
+                                   == CopyResult::Success; });
 }
 
 void RenderProxy::pushLayerUpdate(DeferredLayerUpdater* layer) {
@@ -331,14 +333,14 @@
     }
 }
 
-int RenderProxy::copyGraphicBufferInto(GraphicBuffer* buffer, SkBitmap* bitmap) {
+int RenderProxy::copyHWBitmapInto(Bitmap* hwBitmap, SkBitmap* bitmap) {
     RenderThread& thread = RenderThread::getInstance();
     if (gettid() == thread.getTid()) {
         // TODO: fix everything that hits this. We should never be triggering a readback ourselves.
-        return (int)thread.readback().copyGraphicBufferInto(buffer, bitmap);
+        return (int)thread.readback().copyHWBitmapInto(hwBitmap, bitmap);
     } else {
         return thread.queue().runSync([&]() -> int {
-            return (int)thread.readback().copyGraphicBufferInto(buffer, bitmap);
+            return (int)thread.readback().copyHWBitmapInto(hwBitmap, bitmap);
         });
     }
 }
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index c2964a4..969ad00 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -125,7 +125,7 @@
                                            int bottom, SkBitmap* bitmap);
     ANDROID_API static void prepareToDraw(Bitmap& bitmap);
 
-    static int copyGraphicBufferInto(GraphicBuffer* buffer, SkBitmap* bitmap);
+    static int copyHWBitmapInto(Bitmap* hwBitmap, SkBitmap* bitmap);
 
     static void onBitmapDestroyed(uint32_t pixelRefId);
 
diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp
index c1284ec..7258a0a 100644
--- a/libs/hwui/renderthread/RenderThread.cpp
+++ b/libs/hwui/renderthread/RenderThread.cpp
@@ -19,13 +19,12 @@
 #include "CanvasContext.h"
 #include "DeviceInfo.h"
 #include "EglManager.h"
+#include "Readback.h"
 #include "RenderProxy.h"
 #include "VulkanManager.h"
 #include "hwui/Bitmap.h"
 #include "pipeline/skia/SkiaOpenGLPipeline.h"
-#include "pipeline/skia/SkiaOpenGLReadback.h"
 #include "pipeline/skia/SkiaVulkanPipeline.h"
-#include "pipeline/skia/SkiaVulkanReadback.h"
 #include "renderstate/RenderState.h"
 #include "utils/FatVector.h"
 #include "utils/TimeUtils.h"
@@ -178,7 +177,7 @@
         return;
     }
     mEglManager->initialize();
-    renderState().onGLContextCreated();
+    renderState().onContextCreated();
 
 #ifdef HWUI_GLES_WRAP_ENABLED
     debug::GlesDriver* driver = debug::GlesDriver::get();
@@ -191,7 +190,9 @@
     GrContextOptions options;
     options.fPreferExternalImagesOverES3 = true;
     options.fDisableDistanceFieldPaths = true;
-    cacheManager().configureContext(&options);
+    auto glesVersion = reinterpret_cast<const char*>(glGetString(GL_VERSION));
+    auto size = glesVersion ? strlen(glesVersion) : -1;
+    cacheManager().configureContext(&options, glesVersion, size);
     sk_sp<GrContext> grContext(GrContext::MakeGL(std::move(glInterface), options));
     LOG_ALWAYS_FATAL_IF(!grContext.get());
     setGrContext(grContext);
@@ -200,7 +201,7 @@
 void RenderThread::destroyGlContext() {
     if (mEglManager->hasEglContext()) {
         setGrContext(nullptr);
-        renderState().onGLContextDestroyed();
+        renderState().onContextDestroyed();
         mEglManager->destroy();
     }
 }
@@ -233,18 +234,7 @@
 
 Readback& RenderThread::readback() {
     if (!mReadback) {
-        auto renderType = Properties::getRenderPipelineType();
-        switch (renderType) {
-            case RenderPipelineType::SkiaGL:
-                mReadback = new skiapipeline::SkiaOpenGLReadback(*this);
-                break;
-            case RenderPipelineType::SkiaVulkan:
-                mReadback = new skiapipeline::SkiaVulkanReadback(*this);
-                break;
-            default:
-                LOG_ALWAYS_FATAL("canvas context type %d not supported", (int32_t)renderType);
-                break;
-        }
+        mReadback = new Readback(*this);
     }
 
     return *mReadback;
diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp
index 1517f57..038e13c 100644
--- a/libs/hwui/renderthread/VulkanManager.cpp
+++ b/libs/hwui/renderthread/VulkanManager.cpp
@@ -40,7 +40,7 @@
 VulkanManager::VulkanManager(RenderThread& thread) : mRenderThread(thread) {}
 
 void VulkanManager::destroy() {
-    mRenderThread.renderState().onVkContextDestroyed();
+    mRenderThread.renderState().onContextDestroyed();
     mRenderThread.setGrContext(nullptr);
 
     if (VK_NULL_HANDLE != mCommandPool) {
@@ -391,7 +391,8 @@
 
     GrContextOptions options;
     options.fDisableDistanceFieldPaths = true;
-    mRenderThread.cacheManager().configureContext(&options);
+    // TODO: get a string describing the SPIR-V compiler version and use it here
+    mRenderThread.cacheManager().configureContext(&options, nullptr, 0);
     sk_sp<GrContext> grContext(GrContext::MakeVulkan(backendContext, options));
     LOG_ALWAYS_FATAL_IF(!grContext.get());
     mRenderThread.setGrContext(grContext);
@@ -404,7 +405,7 @@
         mSwapBehavior = SwapBehavior::BufferAge;
     }
 
-    mRenderThread.renderState().onVkContextCreated();
+    mRenderThread.renderState().onContextCreated();
 }
 
 // Returns the next BackbufferInfo to use for the next draw. The function will make sure all
@@ -981,6 +982,22 @@
     return surface->mCurrentTime - lastUsed;
 }
 
+status_t VulkanManager::fenceWait(sp<Fence>& fence) {
+    //TODO: Insert a wait on fence command into the Vulkan command buffer.
+    // Block CPU on the fence.
+    status_t err = fence->waitForever("VulkanManager::fenceWait");
+    if (err != NO_ERROR) {
+        ALOGE("VulkanManager::fenceWait: error waiting for fence: %d", err);
+        return err;
+    }
+    return OK;
+}
+
+status_t VulkanManager::createReleaseFence(sp<Fence>& nativeFence) {
+    //TODO: Create a fence that is signaled, when all the pending Vulkan commands are flushed.
+    return OK;
+}
+
 } /* namespace renderthread */
 } /* namespace uirenderer */
 } /* namespace android */
diff --git a/libs/hwui/renderthread/VulkanManager.h b/libs/hwui/renderthread/VulkanManager.h
index 5524c39..7a539ae 100644
--- a/libs/hwui/renderthread/VulkanManager.h
+++ b/libs/hwui/renderthread/VulkanManager.h
@@ -23,6 +23,8 @@
 #include <vulkan/vulkan.h>
 
 #include <SkSurface.h>
+#include <ui/Fence.h>
+#include <utils/StrongPointer.h>
 #include <vk/GrVkBackendContext.h>
 
 class GrVkExtensions;
@@ -110,6 +112,16 @@
     // Presents the current VkImage.
     void swapBuffers(VulkanSurface* surface);
 
+    // Inserts a wait on fence command into the Vulkan command buffer.
+    status_t fenceWait(sp<Fence>& fence);
+
+    // Creates a fence that is signaled, when all the pending Vulkan commands are flushed.
+    status_t createReleaseFence(sp<Fence>& nativeFence);
+
+    // TODO(b/115636873): Handle composition preference.
+    SkColorType getSurfaceColorType() const { return SkColorType::kN32_SkColorType; }
+    sk_sp<SkColorSpace> getSurfaceColorSpace() { return SkColorSpace::MakeSRGB(); }
+
 private:
     friend class RenderThread;
 
diff --git a/libs/hwui/surfacetexture/EGLConsumer.cpp b/libs/hwui/surfacetexture/EGLConsumer.cpp
new file mode 100644
index 0000000..c8220c6
--- /dev/null
+++ b/libs/hwui/surfacetexture/EGLConsumer.cpp
@@ -0,0 +1,675 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <inttypes.h>
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+#include <cutils/compiler.h>
+#include <gui/BufferItem.h>
+#include <gui/BufferQueue.h>
+#include <private/gui/SyncFeatures.h>
+#include "EGLConsumer.h"
+#include "SurfaceTexture.h"
+
+#include <utils/Log.h>
+#include <utils/String8.h>
+#include <utils/Trace.h>
+
+#define PROT_CONTENT_EXT_STR "EGL_EXT_protected_content"
+#define EGL_PROTECTED_CONTENT_EXT 0x32C0
+
+namespace android {
+
+// Macros for including the SurfaceTexture name in log messages
+#define EGC_LOGV(x, ...) ALOGV("[%s] " x, st.mName.string(), ##__VA_ARGS__)
+#define EGC_LOGD(x, ...) ALOGD("[%s] " x, st.mName.string(), ##__VA_ARGS__)
+#define EGC_LOGW(x, ...) ALOGW("[%s] " x, st.mName.string(), ##__VA_ARGS__)
+#define EGC_LOGE(x, ...) ALOGE("[%s] " x, st.mName.string(), ##__VA_ARGS__)
+
+static const struct {
+    uint32_t width, height;
+    char const* bits;
+} kDebugData = {15, 12,
+                "_______________"
+                "_______________"
+                "_____XX_XX_____"
+                "__X_X_____X_X__"
+                "__X_XXXXXXX_X__"
+                "__XXXXXXXXXXX__"
+                "___XX_XXX_XX___"
+                "____XXXXXXX____"
+                "_____X___X_____"
+                "____X_____X____"
+                "_______________"
+                "_______________"};
+
+Mutex EGLConsumer::sStaticInitLock;
+sp<GraphicBuffer> EGLConsumer::sReleasedTexImageBuffer;
+
+static bool hasEglProtectedContentImpl() {
+    EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+    const char* exts = eglQueryString(dpy, EGL_EXTENSIONS);
+    size_t cropExtLen = strlen(PROT_CONTENT_EXT_STR);
+    size_t extsLen = strlen(exts);
+    bool equal = !strcmp(PROT_CONTENT_EXT_STR, exts);
+    bool atStart = !strncmp(PROT_CONTENT_EXT_STR " ", exts, cropExtLen + 1);
+    bool atEnd = (cropExtLen + 1) < extsLen &&
+                 !strcmp(" " PROT_CONTENT_EXT_STR, exts + extsLen - (cropExtLen + 1));
+    bool inMiddle = strstr(exts, " " PROT_CONTENT_EXT_STR " ");
+    return equal || atStart || atEnd || inMiddle;
+}
+
+static bool hasEglProtectedContent() {
+    // Only compute whether the extension is present once the first time this
+    // function is called.
+    static bool hasIt = hasEglProtectedContentImpl();
+    return hasIt;
+}
+
+EGLConsumer::EGLConsumer() : mEglDisplay(EGL_NO_DISPLAY), mEglContext(EGL_NO_CONTEXT) {}
+
+status_t EGLConsumer::updateTexImage(SurfaceTexture& st) {
+    // Make sure the EGL state is the same as in previous calls.
+    status_t err = checkAndUpdateEglStateLocked(st);
+    if (err != NO_ERROR) {
+        return err;
+    }
+
+    BufferItem item;
+
+    // Acquire the next buffer.
+    // In asynchronous mode the list is guaranteed to be one buffer
+    // deep, while in synchronous mode we use the oldest buffer.
+    err = st.acquireBufferLocked(&item, 0);
+    if (err != NO_ERROR) {
+        if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
+            // We always bind the texture even if we don't update its contents.
+            EGC_LOGV("updateTexImage: no buffers were available");
+            glBindTexture(st.mTexTarget, st.mTexName);
+            err = NO_ERROR;
+        } else {
+            EGC_LOGE("updateTexImage: acquire failed: %s (%d)", strerror(-err), err);
+        }
+        return err;
+    }
+
+    // Release the previous buffer.
+    err = updateAndReleaseLocked(item, nullptr, st);
+    if (err != NO_ERROR) {
+        // We always bind the texture.
+        glBindTexture(st.mTexTarget, st.mTexName);
+        return err;
+    }
+
+    // Bind the new buffer to the GL texture, and wait until it's ready.
+    return bindTextureImageLocked(st);
+}
+
+status_t EGLConsumer::releaseTexImage(SurfaceTexture& st) {
+    // Make sure the EGL state is the same as in previous calls.
+    status_t err = NO_ERROR;
+
+    // if we're detached, no need to validate EGL's state -- we won't use it.
+    if (st.mOpMode == SurfaceTexture::OpMode::attachedToGL) {
+        err = checkAndUpdateEglStateLocked(st, true);
+        if (err != NO_ERROR) {
+            return err;
+        }
+    }
+
+    // Update the EGLConsumer state.
+    int buf = st.mCurrentTexture;
+    if (buf != BufferQueue::INVALID_BUFFER_SLOT) {
+        EGC_LOGV("releaseTexImage: (slot=%d, mOpMode=%d)", buf, (int)st.mOpMode);
+
+        // if we're detached, we just use the fence that was created in detachFromContext()
+        // so... basically, nothing more to do here.
+        if (st.mOpMode == SurfaceTexture::OpMode::attachedToGL) {
+            // Do whatever sync ops we need to do before releasing the slot.
+            err = syncForReleaseLocked(mEglDisplay, st);
+            if (err != NO_ERROR) {
+                EGC_LOGE("syncForReleaseLocked failed (slot=%d), err=%d", buf, err);
+                return err;
+            }
+        }
+
+        err = st.releaseBufferLocked(buf, st.mSlots[buf].mGraphicBuffer, mEglDisplay,
+                                     EGL_NO_SYNC_KHR);
+        if (err < NO_ERROR) {
+            EGC_LOGE("releaseTexImage: failed to release buffer: %s (%d)", strerror(-err), err);
+            return err;
+        }
+
+        if (mReleasedTexImage == nullptr) {
+            mReleasedTexImage = new EglImage(getDebugTexImageBuffer());
+        }
+
+        st.mCurrentTexture = BufferQueue::INVALID_BUFFER_SLOT;
+        mCurrentTextureImage = mReleasedTexImage;
+        st.mCurrentCrop.makeInvalid();
+        st.mCurrentTransform = 0;
+        st.mCurrentTimestamp = 0;
+        st.mCurrentDataSpace = HAL_DATASPACE_UNKNOWN;
+        st.mCurrentFence = Fence::NO_FENCE;
+        st.mCurrentFenceTime = FenceTime::NO_FENCE;
+
+        // detached, don't touch the texture (and we may not even have an
+        // EGLDisplay here.
+        if (st.mOpMode == SurfaceTexture::OpMode::attachedToGL) {
+            // This binds a dummy buffer (mReleasedTexImage).
+            status_t result = bindTextureImageLocked(st);
+            if (result != NO_ERROR) {
+                return result;
+            }
+        }
+    }
+
+    return NO_ERROR;
+}
+
+sp<GraphicBuffer> EGLConsumer::getDebugTexImageBuffer() {
+    Mutex::Autolock _l(sStaticInitLock);
+    if (CC_UNLIKELY(sReleasedTexImageBuffer == nullptr)) {
+        // The first time, create the debug texture in case the application
+        // continues to use it.
+        sp<GraphicBuffer> buffer = new GraphicBuffer(
+                kDebugData.width, kDebugData.height, PIXEL_FORMAT_RGBA_8888,
+                GraphicBuffer::USAGE_SW_WRITE_RARELY, "[EGLConsumer debug texture]");
+        uint32_t* bits;
+        buffer->lock(GraphicBuffer::USAGE_SW_WRITE_RARELY, reinterpret_cast<void**>(&bits));
+        uint32_t stride = buffer->getStride();
+        uint32_t height = buffer->getHeight();
+        memset(bits, 0, stride * height * 4);
+        for (uint32_t y = 0; y < kDebugData.height; y++) {
+            for (uint32_t x = 0; x < kDebugData.width; x++) {
+                bits[x] = (kDebugData.bits[y + kDebugData.width + x] == 'X') ? 0xFF000000
+                                                                             : 0xFFFFFFFF;
+            }
+            bits += stride;
+        }
+        buffer->unlock();
+        sReleasedTexImageBuffer = buffer;
+    }
+    return sReleasedTexImageBuffer;
+}
+
+void EGLConsumer::onAcquireBufferLocked(BufferItem* item, SurfaceTexture& st) {
+    // If item->mGraphicBuffer is not null, this buffer has not been acquired
+    // before, so any prior EglImage created is using a stale buffer. This
+    // replaces any old EglImage with a new one (using the new buffer).
+    int slot = item->mSlot;
+    if (item->mGraphicBuffer != nullptr || mEglSlots[slot].mEglImage.get() == nullptr) {
+        mEglSlots[slot].mEglImage = new EglImage(st.mSlots[slot].mGraphicBuffer);
+    }
+}
+
+void EGLConsumer::onReleaseBufferLocked(int buf) {
+    mEglSlots[buf].mEglFence = EGL_NO_SYNC_KHR;
+}
+
+status_t EGLConsumer::updateAndReleaseLocked(const BufferItem& item, PendingRelease* pendingRelease,
+                                             SurfaceTexture& st) {
+    status_t err = NO_ERROR;
+
+    int slot = item.mSlot;
+
+    if (st.mOpMode != SurfaceTexture::OpMode::attachedToGL) {
+        EGC_LOGE(
+                "updateAndRelease: EGLConsumer is not attached to an OpenGL "
+                "ES context");
+        st.releaseBufferLocked(slot, st.mSlots[slot].mGraphicBuffer, mEglDisplay, EGL_NO_SYNC_KHR);
+        return INVALID_OPERATION;
+    }
+
+    // Confirm state.
+    err = checkAndUpdateEglStateLocked(st);
+    if (err != NO_ERROR) {
+        st.releaseBufferLocked(slot, st.mSlots[slot].mGraphicBuffer, mEglDisplay, EGL_NO_SYNC_KHR);
+        return err;
+    }
+
+    // Ensure we have a valid EglImageKHR for the slot, creating an EglImage
+    // if nessessary, for the gralloc buffer currently in the slot in
+    // ConsumerBase.
+    // We may have to do this even when item.mGraphicBuffer == NULL (which
+    // means the buffer was previously acquired).
+    err = mEglSlots[slot].mEglImage->createIfNeeded(mEglDisplay);
+    if (err != NO_ERROR) {
+        EGC_LOGW("updateAndRelease: unable to createImage on display=%p slot=%d", mEglDisplay,
+                 slot);
+        st.releaseBufferLocked(slot, st.mSlots[slot].mGraphicBuffer, mEglDisplay, EGL_NO_SYNC_KHR);
+        return UNKNOWN_ERROR;
+    }
+
+    // Do whatever sync ops we need to do before releasing the old slot.
+    if (slot != st.mCurrentTexture) {
+        err = syncForReleaseLocked(mEglDisplay, st);
+        if (err != NO_ERROR) {
+            // Release the buffer we just acquired.  It's not safe to
+            // release the old buffer, so instead we just drop the new frame.
+            // As we are still under lock since acquireBuffer, it is safe to
+            // release by slot.
+            st.releaseBufferLocked(slot, st.mSlots[slot].mGraphicBuffer, mEglDisplay,
+                                   EGL_NO_SYNC_KHR);
+            return err;
+        }
+    }
+
+    EGC_LOGV(
+            "updateAndRelease: (slot=%d buf=%p) -> (slot=%d buf=%p)", st.mCurrentTexture,
+            mCurrentTextureImage != nullptr ? mCurrentTextureImage->graphicBufferHandle() : nullptr,
+            slot, st.mSlots[slot].mGraphicBuffer->handle);
+
+    // Hang onto the pointer so that it isn't freed in the call to
+    // releaseBufferLocked() if we're in shared buffer mode and both buffers are
+    // the same.
+    sp<EglImage> nextTextureImage = mEglSlots[slot].mEglImage;
+
+    // release old buffer
+    if (st.mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
+        if (pendingRelease == nullptr) {
+            status_t status = st.releaseBufferLocked(
+                    st.mCurrentTexture, mCurrentTextureImage->graphicBuffer(), mEglDisplay,
+                    mEglSlots[st.mCurrentTexture].mEglFence);
+            if (status < NO_ERROR) {
+                EGC_LOGE("updateAndRelease: failed to release buffer: %s (%d)", strerror(-status),
+                         status);
+                err = status;
+                // keep going, with error raised [?]
+            }
+        } else {
+            pendingRelease->currentTexture = st.mCurrentTexture;
+            pendingRelease->graphicBuffer = mCurrentTextureImage->graphicBuffer();
+            pendingRelease->display = mEglDisplay;
+            pendingRelease->fence = mEglSlots[st.mCurrentTexture].mEglFence;
+            pendingRelease->isPending = true;
+        }
+    }
+
+    // Update the EGLConsumer state.
+    st.mCurrentTexture = slot;
+    mCurrentTextureImage = nextTextureImage;
+    st.mCurrentCrop = item.mCrop;
+    st.mCurrentTransform = item.mTransform;
+    st.mCurrentScalingMode = item.mScalingMode;
+    st.mCurrentTimestamp = item.mTimestamp;
+    st.mCurrentDataSpace = item.mDataSpace;
+    st.mCurrentFence = item.mFence;
+    st.mCurrentFenceTime = item.mFenceTime;
+    st.mCurrentFrameNumber = item.mFrameNumber;
+
+    st.computeCurrentTransformMatrixLocked();
+
+    return err;
+}
+
+status_t EGLConsumer::bindTextureImageLocked(SurfaceTexture& st) {
+    if (mEglDisplay == EGL_NO_DISPLAY) {
+        ALOGE("bindTextureImage: invalid display");
+        return INVALID_OPERATION;
+    }
+
+    GLenum error;
+    while ((error = glGetError()) != GL_NO_ERROR) {
+        EGC_LOGW("bindTextureImage: clearing GL error: %#04x", error);
+    }
+
+    glBindTexture(st.mTexTarget, st.mTexName);
+    if (st.mCurrentTexture == BufferQueue::INVALID_BUFFER_SLOT && mCurrentTextureImage == nullptr) {
+        EGC_LOGE("bindTextureImage: no currently-bound texture");
+        return NO_INIT;
+    }
+
+    status_t err = mCurrentTextureImage->createIfNeeded(mEglDisplay);
+    if (err != NO_ERROR) {
+        EGC_LOGW("bindTextureImage: can't create image on display=%p slot=%d", mEglDisplay,
+                 st.mCurrentTexture);
+        return UNKNOWN_ERROR;
+    }
+    mCurrentTextureImage->bindToTextureTarget(st.mTexTarget);
+
+    // In the rare case that the display is terminated and then initialized
+    // again, we can't detect that the display changed (it didn't), but the
+    // image is invalid. In this case, repeat the exact same steps while
+    // forcing the creation of a new image.
+    if ((error = glGetError()) != GL_NO_ERROR) {
+        glBindTexture(st.mTexTarget, st.mTexName);
+        status_t result = mCurrentTextureImage->createIfNeeded(mEglDisplay, true);
+        if (result != NO_ERROR) {
+            EGC_LOGW("bindTextureImage: can't create image on display=%p slot=%d", mEglDisplay,
+                     st.mCurrentTexture);
+            return UNKNOWN_ERROR;
+        }
+        mCurrentTextureImage->bindToTextureTarget(st.mTexTarget);
+        if ((error = glGetError()) != GL_NO_ERROR) {
+            EGC_LOGE("bindTextureImage: error binding external image: %#04x", error);
+            return UNKNOWN_ERROR;
+        }
+    }
+
+    // Wait for the new buffer to be ready.
+    return doGLFenceWaitLocked(st);
+}
+
+status_t EGLConsumer::checkAndUpdateEglStateLocked(SurfaceTexture& st, bool contextCheck) {
+    EGLDisplay dpy = eglGetCurrentDisplay();
+    EGLContext ctx = eglGetCurrentContext();
+
+    if (!contextCheck) {
+        // if this is the first time we're called, mEglDisplay/mEglContext have
+        // never been set, so don't error out (below).
+        if (mEglDisplay == EGL_NO_DISPLAY) {
+            mEglDisplay = dpy;
+        }
+        if (mEglContext == EGL_NO_CONTEXT) {
+            mEglContext = ctx;
+        }
+    }
+
+    if (mEglDisplay != dpy || dpy == EGL_NO_DISPLAY) {
+        EGC_LOGE("checkAndUpdateEglState: invalid current EGLDisplay");
+        return INVALID_OPERATION;
+    }
+
+    if (mEglContext != ctx || ctx == EGL_NO_CONTEXT) {
+        EGC_LOGE("checkAndUpdateEglState: invalid current EGLContext");
+        return INVALID_OPERATION;
+    }
+
+    mEglDisplay = dpy;
+    mEglContext = ctx;
+    return NO_ERROR;
+}
+
+status_t EGLConsumer::detachFromContext(SurfaceTexture& st) {
+    EGLDisplay dpy = eglGetCurrentDisplay();
+    EGLContext ctx = eglGetCurrentContext();
+
+    if (mEglDisplay != dpy && mEglDisplay != EGL_NO_DISPLAY) {
+        EGC_LOGE("detachFromContext: invalid current EGLDisplay");
+        return INVALID_OPERATION;
+    }
+
+    if (mEglContext != ctx && mEglContext != EGL_NO_CONTEXT) {
+        EGC_LOGE("detachFromContext: invalid current EGLContext");
+        return INVALID_OPERATION;
+    }
+
+    if (dpy != EGL_NO_DISPLAY && ctx != EGL_NO_CONTEXT) {
+        status_t err = syncForReleaseLocked(dpy, st);
+        if (err != OK) {
+            return err;
+        }
+
+        glDeleteTextures(1, &st.mTexName);
+    }
+
+    mEglDisplay = EGL_NO_DISPLAY;
+    mEglContext = EGL_NO_CONTEXT;
+
+    return OK;
+}
+
+status_t EGLConsumer::attachToContext(uint32_t tex, SurfaceTexture& st) {
+    // Initialize mCurrentTextureImage if there is a current buffer from past attached state.
+    int slot = st.mCurrentTexture;
+    if (slot != BufferItem::INVALID_BUFFER_SLOT) {
+        if (!mEglSlots[slot].mEglImage.get()) {
+            mEglSlots[slot].mEglImage = new EglImage(st.mSlots[slot].mGraphicBuffer);
+        }
+        mCurrentTextureImage = mEglSlots[slot].mEglImage;
+    }
+
+    EGLDisplay dpy = eglGetCurrentDisplay();
+    EGLContext ctx = eglGetCurrentContext();
+
+    if (dpy == EGL_NO_DISPLAY) {
+        EGC_LOGE("attachToContext: invalid current EGLDisplay");
+        return INVALID_OPERATION;
+    }
+
+    if (ctx == EGL_NO_CONTEXT) {
+        EGC_LOGE("attachToContext: invalid current EGLContext");
+        return INVALID_OPERATION;
+    }
+
+    // We need to bind the texture regardless of whether there's a current
+    // buffer.
+    glBindTexture(st.mTexTarget, GLuint(tex));
+
+    mEglDisplay = dpy;
+    mEglContext = ctx;
+    st.mTexName = tex;
+    st.mOpMode = SurfaceTexture::OpMode::attachedToGL;
+
+    if (mCurrentTextureImage != nullptr) {
+        // This may wait for a buffer a second time. This is likely required if
+        // this is a different context, since otherwise the wait could be skipped
+        // by bouncing through another context. For the same context the extra
+        // wait is redundant.
+        status_t err = bindTextureImageLocked(st);
+        if (err != NO_ERROR) {
+            return err;
+        }
+    }
+
+    return OK;
+}
+
+status_t EGLConsumer::syncForReleaseLocked(EGLDisplay dpy, SurfaceTexture& st) {
+    EGC_LOGV("syncForReleaseLocked");
+
+    if (st.mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
+        if (SyncFeatures::getInstance().useNativeFenceSync()) {
+            EGLSyncKHR sync = eglCreateSyncKHR(dpy, EGL_SYNC_NATIVE_FENCE_ANDROID, nullptr);
+            if (sync == EGL_NO_SYNC_KHR) {
+                EGC_LOGE("syncForReleaseLocked: error creating EGL fence: %#x", eglGetError());
+                return UNKNOWN_ERROR;
+            }
+            glFlush();
+            int fenceFd = eglDupNativeFenceFDANDROID(dpy, sync);
+            eglDestroySyncKHR(dpy, sync);
+            if (fenceFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
+                EGC_LOGE(
+                        "syncForReleaseLocked: error dup'ing native fence "
+                        "fd: %#x",
+                        eglGetError());
+                return UNKNOWN_ERROR;
+            }
+            sp<Fence> fence(new Fence(fenceFd));
+            status_t err = st.addReleaseFenceLocked(st.mCurrentTexture,
+                                                    mCurrentTextureImage->graphicBuffer(), fence);
+            if (err != OK) {
+                EGC_LOGE(
+                        "syncForReleaseLocked: error adding release fence: "
+                        "%s (%d)",
+                        strerror(-err), err);
+                return err;
+            }
+        } else if (st.mUseFenceSync && SyncFeatures::getInstance().useFenceSync()) {
+            EGLSyncKHR fence = mEglSlots[st.mCurrentTexture].mEglFence;
+            if (fence != EGL_NO_SYNC_KHR) {
+                // There is already a fence for the current slot.  We need to
+                // wait on that before replacing it with another fence to
+                // ensure that all outstanding buffer accesses have completed
+                // before the producer accesses it.
+                EGLint result = eglClientWaitSyncKHR(dpy, fence, 0, 1000000000);
+                if (result == EGL_FALSE) {
+                    EGC_LOGE(
+                            "syncForReleaseLocked: error waiting for previous "
+                            "fence: %#x",
+                            eglGetError());
+                    return UNKNOWN_ERROR;
+                } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
+                    EGC_LOGE(
+                            "syncForReleaseLocked: timeout waiting for previous "
+                            "fence");
+                    return TIMED_OUT;
+                }
+                eglDestroySyncKHR(dpy, fence);
+            }
+
+            // Create a fence for the outstanding accesses in the current
+            // OpenGL ES context.
+            fence = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, nullptr);
+            if (fence == EGL_NO_SYNC_KHR) {
+                EGC_LOGE("syncForReleaseLocked: error creating fence: %#x", eglGetError());
+                return UNKNOWN_ERROR;
+            }
+            glFlush();
+            mEglSlots[st.mCurrentTexture].mEglFence = fence;
+        }
+    }
+
+    return OK;
+}
+
+status_t EGLConsumer::doGLFenceWaitLocked(SurfaceTexture& st) const {
+    EGLDisplay dpy = eglGetCurrentDisplay();
+    EGLContext ctx = eglGetCurrentContext();
+
+    if (mEglDisplay != dpy || mEglDisplay == EGL_NO_DISPLAY) {
+        EGC_LOGE("doGLFenceWait: invalid current EGLDisplay");
+        return INVALID_OPERATION;
+    }
+
+    if (mEglContext != ctx || mEglContext == EGL_NO_CONTEXT) {
+        EGC_LOGE("doGLFenceWait: invalid current EGLContext");
+        return INVALID_OPERATION;
+    }
+
+    if (st.mCurrentFence->isValid()) {
+        if (SyncFeatures::getInstance().useWaitSync() &&
+            SyncFeatures::getInstance().useNativeFenceSync()) {
+            // Create an EGLSyncKHR from the current fence.
+            int fenceFd = st.mCurrentFence->dup();
+            if (fenceFd == -1) {
+                EGC_LOGE("doGLFenceWait: error dup'ing fence fd: %d", errno);
+                return -errno;
+            }
+            EGLint attribs[] = {EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fenceFd, EGL_NONE};
+            EGLSyncKHR sync = eglCreateSyncKHR(dpy, EGL_SYNC_NATIVE_FENCE_ANDROID, attribs);
+            if (sync == EGL_NO_SYNC_KHR) {
+                close(fenceFd);
+                EGC_LOGE("doGLFenceWait: error creating EGL fence: %#x", eglGetError());
+                return UNKNOWN_ERROR;
+            }
+
+            // XXX: The spec draft is inconsistent as to whether this should
+            // return an EGLint or void.  Ignore the return value for now, as
+            // it's not strictly needed.
+            eglWaitSyncKHR(dpy, sync, 0);
+            EGLint eglErr = eglGetError();
+            eglDestroySyncKHR(dpy, sync);
+            if (eglErr != EGL_SUCCESS) {
+                EGC_LOGE("doGLFenceWait: error waiting for EGL fence: %#x", eglErr);
+                return UNKNOWN_ERROR;
+            }
+        } else {
+            status_t err = st.mCurrentFence->waitForever("EGLConsumer::doGLFenceWaitLocked");
+            if (err != NO_ERROR) {
+                EGC_LOGE("doGLFenceWait: error waiting for fence: %d", err);
+                return err;
+            }
+        }
+    }
+
+    return NO_ERROR;
+}
+
+void EGLConsumer::onFreeBufferLocked(int slotIndex) {
+    mEglSlots[slotIndex].mEglImage.clear();
+}
+
+void EGLConsumer::onAbandonLocked() {
+    mCurrentTextureImage.clear();
+}
+
+EGLConsumer::EglImage::EglImage(sp<GraphicBuffer> graphicBuffer)
+        : mGraphicBuffer(graphicBuffer), mEglImage(EGL_NO_IMAGE_KHR), mEglDisplay(EGL_NO_DISPLAY) {}
+
+EGLConsumer::EglImage::~EglImage() {
+    if (mEglImage != EGL_NO_IMAGE_KHR) {
+        if (!eglDestroyImageKHR(mEglDisplay, mEglImage)) {
+            ALOGE("~EglImage: eglDestroyImageKHR failed");
+        }
+        eglTerminate(mEglDisplay);
+    }
+}
+
+status_t EGLConsumer::EglImage::createIfNeeded(EGLDisplay eglDisplay, bool forceCreation) {
+    // If there's an image and it's no longer valid, destroy it.
+    bool haveImage = mEglImage != EGL_NO_IMAGE_KHR;
+    bool displayInvalid = mEglDisplay != eglDisplay;
+    if (haveImage && (displayInvalid || forceCreation)) {
+        if (!eglDestroyImageKHR(mEglDisplay, mEglImage)) {
+            ALOGE("createIfNeeded: eglDestroyImageKHR failed");
+        }
+        eglTerminate(mEglDisplay);
+        mEglImage = EGL_NO_IMAGE_KHR;
+        mEglDisplay = EGL_NO_DISPLAY;
+    }
+
+    // If there's no image, create one.
+    if (mEglImage == EGL_NO_IMAGE_KHR) {
+        mEglDisplay = eglDisplay;
+        mEglImage = createImage(mEglDisplay, mGraphicBuffer);
+    }
+
+    // Fail if we can't create a valid image.
+    if (mEglImage == EGL_NO_IMAGE_KHR) {
+        mEglDisplay = EGL_NO_DISPLAY;
+        const sp<GraphicBuffer>& buffer = mGraphicBuffer;
+        ALOGE("Failed to create image. size=%ux%u st=%u usage=%#" PRIx64 " fmt=%d",
+              buffer->getWidth(), buffer->getHeight(), buffer->getStride(), buffer->getUsage(),
+              buffer->getPixelFormat());
+        return UNKNOWN_ERROR;
+    }
+
+    return OK;
+}
+
+void EGLConsumer::EglImage::bindToTextureTarget(uint32_t texTarget) {
+    glEGLImageTargetTexture2DOES(texTarget, static_cast<GLeglImageOES>(mEglImage));
+}
+
+EGLImageKHR EGLConsumer::EglImage::createImage(EGLDisplay dpy,
+                                               const sp<GraphicBuffer>& graphicBuffer) {
+    EGLClientBuffer cbuf = static_cast<EGLClientBuffer>(graphicBuffer->getNativeBuffer());
+    const bool createProtectedImage =
+            (graphicBuffer->getUsage() & GRALLOC_USAGE_PROTECTED) && hasEglProtectedContent();
+    EGLint attrs[] = {
+            EGL_IMAGE_PRESERVED_KHR,
+            EGL_TRUE,
+            createProtectedImage ? EGL_PROTECTED_CONTENT_EXT : EGL_NONE,
+            createProtectedImage ? EGL_TRUE : EGL_NONE,
+            EGL_NONE,
+    };
+    eglInitialize(dpy, nullptr, nullptr);
+    EGLImageKHR image =
+            eglCreateImageKHR(dpy, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, cbuf, attrs);
+    if (image == EGL_NO_IMAGE_KHR) {
+        EGLint error = eglGetError();
+        ALOGE("error creating EGLImage: %#x", error);
+        eglTerminate(dpy);
+    }
+    return image;
+}
+
+};  // namespace android
diff --git a/libs/hwui/surfacetexture/EGLConsumer.h b/libs/hwui/surfacetexture/EGLConsumer.h
new file mode 100644
index 0000000..eccb082
--- /dev/null
+++ b/libs/hwui/surfacetexture/EGLConsumer.h
@@ -0,0 +1,311 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <EGL/egl.h>
+#include <EGL/eglext.h>
+
+#include <gui/BufferQueueDefs.h>
+
+#include <ui/FenceTime.h>
+#include <ui/GraphicBuffer.h>
+#include <utils/Mutex.h>
+
+namespace android {
+
+class SurfaceTexture;
+
+/*
+ * EGLConsumer implements the parts of SurfaceTexture that deal with
+ * textures attached to an GL context.
+ */
+class EGLConsumer {
+public:
+    EGLConsumer();
+
+    /**
+     * updateTexImage acquires the most recently queued buffer, and sets the
+     * image contents of the target texture to it.
+     *
+     * This call may only be made while the OpenGL ES context to which the
+     * target texture belongs is bound to the calling thread.
+     *
+     * This calls doGLFenceWait to ensure proper synchronization.
+     */
+    status_t updateTexImage(SurfaceTexture& st);
+
+    /*
+     * releaseTexImage releases the texture acquired in updateTexImage().
+     * This is intended to be used in single buffer mode.
+     *
+     * This call may only be made while the OpenGL ES context to which the
+     * target texture belongs is bound to the calling thread.
+     */
+    status_t releaseTexImage(SurfaceTexture& st);
+
+    /**
+     * detachFromContext detaches the EGLConsumer from the calling thread's
+     * current OpenGL ES context.  This context must be the same as the context
+     * that was current for previous calls to updateTexImage.
+     *
+     * Detaching a EGLConsumer from an OpenGL ES context will result in the
+     * deletion of the OpenGL ES texture object into which the images were being
+     * streamed.  After a EGLConsumer has been detached from the OpenGL ES
+     * context calls to updateTexImage will fail returning INVALID_OPERATION
+     * until the EGLConsumer is attached to a new OpenGL ES context using the
+     * attachToContext method.
+     */
+    status_t detachFromContext(SurfaceTexture& st);
+
+    /**
+     * attachToContext attaches a EGLConsumer that is currently in the
+     * 'detached' state to the current OpenGL ES context.  A EGLConsumer is
+     * in the 'detached' state iff detachFromContext has successfully been
+     * called and no calls to attachToContext have succeeded since the last
+     * detachFromContext call.  Calls to attachToContext made on a
+     * EGLConsumer that is not in the 'detached' state will result in an
+     * INVALID_OPERATION error.
+     *
+     * The tex argument specifies the OpenGL ES texture object name in the
+     * new context into which the image contents will be streamed.  A successful
+     * call to attachToContext will result in this texture object being bound to
+     * the texture target and populated with the image contents that were
+     * current at the time of the last call to detachFromContext.
+     */
+    status_t attachToContext(uint32_t tex, SurfaceTexture& st);
+
+    /**
+     * onAcquireBufferLocked amends the ConsumerBase method to update the
+     * mEglSlots array in addition to the ConsumerBase behavior.
+     */
+    void onAcquireBufferLocked(BufferItem* item, SurfaceTexture& st);
+
+    /**
+     * onReleaseBufferLocked amends the ConsumerBase method to update the
+     * mEglSlots array in addition to the ConsumerBase.
+     */
+    void onReleaseBufferLocked(int slot);
+
+    /**
+     * onFreeBufferLocked frees up the given buffer slot. If the slot has been
+     * initialized this will release the reference to the GraphicBuffer in that
+     * slot and destroy the EGLImage in that slot.  Otherwise it has no effect.
+     */
+    void onFreeBufferLocked(int slotIndex);
+
+    /**
+     * onAbandonLocked amends the ConsumerBase method to clear
+     * mCurrentTextureImage in addition to the ConsumerBase behavior.
+     */
+    void onAbandonLocked();
+
+protected:
+    struct PendingRelease {
+        PendingRelease()
+                : isPending(false)
+                , currentTexture(-1)
+                , graphicBuffer()
+                , display(nullptr)
+                , fence(nullptr) {}
+
+        bool isPending;
+        int currentTexture;
+        sp<GraphicBuffer> graphicBuffer;
+        EGLDisplay display;
+        EGLSyncKHR fence;
+    };
+
+    /**
+     * This releases the buffer in the slot referenced by mCurrentTexture,
+     * then updates state to refer to the BufferItem, which must be a
+     * newly-acquired buffer. If pendingRelease is not null, the parameters
+     * which would have been passed to releaseBufferLocked upon the successful
+     * completion of the method will instead be returned to the caller, so that
+     * it may call releaseBufferLocked itself later.
+     */
+    status_t updateAndReleaseLocked(const BufferItem& item, PendingRelease* pendingRelease,
+                                    SurfaceTexture& st);
+
+    /**
+     * Binds mTexName and the current buffer to mTexTarget.  Uses
+     * mCurrentTexture if it's set, mCurrentTextureImage if not.  If the
+     * bind succeeds, this calls doGLFenceWait.
+     */
+    status_t bindTextureImageLocked(SurfaceTexture& st);
+
+    /**
+     * Gets the current EGLDisplay and EGLContext values, and compares them
+     * to mEglDisplay and mEglContext.  If the fields have been previously
+     * set, the values must match; if not, the fields are set to the current
+     * values.
+     * The contextCheck argument is used to ensure that a GL context is
+     * properly set; when set to false, the check is not performed.
+     */
+    status_t checkAndUpdateEglStateLocked(SurfaceTexture& st, bool contextCheck = false);
+
+    /**
+     * EglImage is a utility class for tracking and creating EGLImageKHRs. There
+     * is primarily just one image per slot, but there is also special cases:
+     *  - For releaseTexImage, we use a debug image (mReleasedTexImage)
+     *  - After freeBuffer, we must still keep the current image/buffer
+     * Reference counting EGLImages lets us handle all these cases easily while
+     * also only creating new EGLImages from buffers when required.
+     */
+    class EglImage : public LightRefBase<EglImage> {
+    public:
+        EglImage(sp<GraphicBuffer> graphicBuffer);
+
+        /**
+         * createIfNeeded creates an EGLImage if required (we haven't created
+         * one yet, or the EGLDisplay or crop-rect has changed).
+         */
+        status_t createIfNeeded(EGLDisplay display, bool forceCreate = false);
+
+        /**
+         * This calls glEGLImageTargetTexture2DOES to bind the image to the
+         * texture in the specified texture target.
+         */
+        void bindToTextureTarget(uint32_t texTarget);
+
+        const sp<GraphicBuffer>& graphicBuffer() { return mGraphicBuffer; }
+        const native_handle* graphicBufferHandle() {
+            return mGraphicBuffer == nullptr ? nullptr : mGraphicBuffer->handle;
+        }
+
+    private:
+        // Only allow instantiation using ref counting.
+        friend class LightRefBase<EglImage>;
+        virtual ~EglImage();
+
+        // createImage creates a new EGLImage from a GraphicBuffer.
+        EGLImageKHR createImage(EGLDisplay dpy, const sp<GraphicBuffer>& graphicBuffer);
+
+        // Disallow copying
+        EglImage(const EglImage& rhs);
+        void operator=(const EglImage& rhs);
+
+        // mGraphicBuffer is the buffer that was used to create this image.
+        sp<GraphicBuffer> mGraphicBuffer;
+
+        // mEglImage is the EGLImage created from mGraphicBuffer.
+        EGLImageKHR mEglImage;
+
+        // mEGLDisplay is the EGLDisplay that was used to create mEglImage.
+        EGLDisplay mEglDisplay;
+
+        // mCropRect is the crop rectangle passed to EGL when mEglImage
+        // was created.
+        Rect mCropRect;
+    };
+
+    /**
+     * doGLFenceWaitLocked inserts a wait command into the OpenGL ES command
+     * stream to ensure that it is safe for future OpenGL ES commands to
+     * access the current texture buffer.
+     */
+    status_t doGLFenceWaitLocked(SurfaceTexture& st) const;
+
+    /**
+     * syncForReleaseLocked performs the synchronization needed to release the
+     * current slot from an OpenGL ES context.  If needed it will set the
+     * current slot's fence to guard against a producer accessing the buffer
+     * before the outstanding accesses have completed.
+     */
+    status_t syncForReleaseLocked(EGLDisplay dpy, SurfaceTexture& st);
+
+    /**
+     * returns a graphic buffer used when the texture image has been released
+     */
+    static sp<GraphicBuffer> getDebugTexImageBuffer();
+
+    /**
+     * The default consumer usage flags that EGLConsumer always sets on its
+     * BufferQueue instance; these will be OR:d with any additional flags passed
+     * from the EGLConsumer user. In particular, EGLConsumer will always
+     * consume buffers as hardware textures.
+     */
+    static const uint64_t DEFAULT_USAGE_FLAGS = GraphicBuffer::USAGE_HW_TEXTURE;
+
+    /**
+     * mCurrentTextureImage is the EglImage/buffer of the current texture. It's
+     * possible that this buffer is not associated with any buffer slot, so we
+     * must track it separately in order to support the getCurrentBuffer method.
+     */
+    sp<EglImage> mCurrentTextureImage;
+
+    /**
+     * EGLSlot contains the information and object references that
+     * EGLConsumer maintains about a BufferQueue buffer slot.
+     */
+    struct EglSlot {
+        EglSlot() : mEglFence(EGL_NO_SYNC_KHR) {}
+
+        /**
+         * mEglImage is the EGLImage created from mGraphicBuffer.
+         */
+        sp<EglImage> mEglImage;
+
+        /**
+         * mFence is the EGL sync object that must signal before the buffer
+         * associated with this buffer slot may be dequeued. It is initialized
+         * to EGL_NO_SYNC_KHR when the buffer is created and (optionally, based
+         * on a compile-time option) set to a new sync object in updateTexImage.
+         */
+        EGLSyncKHR mEglFence;
+    };
+
+    /**
+     * mEglDisplay is the EGLDisplay with which this EGLConsumer is currently
+     * associated.  It is intialized to EGL_NO_DISPLAY and gets set to the
+     * current display when updateTexImage is called for the first time and when
+     * attachToContext is called.
+     */
+    EGLDisplay mEglDisplay;
+
+    /**
+     * mEglContext is the OpenGL ES context with which this EGLConsumer is
+     * currently associated.  It is initialized to EGL_NO_CONTEXT and gets set
+     * to the current GL context when updateTexImage is called for the first
+     * time and when attachToContext is called.
+     */
+    EGLContext mEglContext;
+
+    /**
+     * mEGLSlots stores the buffers that have been allocated by the BufferQueue
+     * for each buffer slot.  It is initialized to null pointers, and gets
+     * filled in with the result of BufferQueue::acquire when the
+     * client dequeues a buffer from a
+     * slot that has not yet been used. The buffer allocated to a slot will also
+     * be replaced if the requested buffer usage or geometry differs from that
+     * of the buffer allocated to a slot.
+     */
+    EglSlot mEglSlots[BufferQueueDefs::NUM_BUFFER_SLOTS];
+
+    /**
+     * protects static initialization
+     */
+    static Mutex sStaticInitLock;
+
+    /**
+     * mReleasedTexImageBuffer is a dummy buffer used when in single buffer
+     * mode and releaseTexImage() has been called
+     */
+    static sp<GraphicBuffer> sReleasedTexImageBuffer;
+    sp<EglImage> mReleasedTexImage;
+};
+
+};  // namespace android
diff --git a/libs/hwui/surfacetexture/ImageConsumer.cpp b/libs/hwui/surfacetexture/ImageConsumer.cpp
new file mode 100644
index 0000000..9ffccfb
--- /dev/null
+++ b/libs/hwui/surfacetexture/ImageConsumer.cpp
@@ -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.
+ */
+
+#include "ImageConsumer.h"
+#include <gui/BufferQueue.h>
+#include "Properties.h"
+#include "SurfaceTexture.h"
+#include "renderstate/RenderState.h"
+#include "renderthread/EglManager.h"
+#include "renderthread/RenderThread.h"
+#include "renderthread/VulkanManager.h"
+
+// Macro for including the SurfaceTexture name in log messages
+#define IMG_LOGE(x, ...) ALOGE("[%s] " x, st.mName.string(), ##__VA_ARGS__)
+
+namespace android {
+
+void ImageConsumer::onFreeBufferLocked(int slotIndex) {
+    mImageSlots[slotIndex].mImage.reset();
+}
+
+void ImageConsumer::onAcquireBufferLocked(BufferItem* item) {
+    // If item->mGraphicBuffer is not null, this buffer has not been acquired
+    // before, so any prior SkImage is created with a stale buffer. This resets the stale SkImage.
+    if (item->mGraphicBuffer != nullptr) {
+        mImageSlots[item->mSlot].mImage.reset();
+    }
+}
+
+void ImageConsumer::onReleaseBufferLocked(int buf) {
+    mImageSlots[buf].mEglFence = EGL_NO_SYNC_KHR;
+}
+
+void ImageConsumer::ImageSlot::createIfNeeded(sp<GraphicBuffer> graphicBuffer) {
+    if (!mImage.get()) {
+        mImage = graphicBuffer.get()
+                         ? SkImage::MakeFromAHardwareBuffer(
+                                   reinterpret_cast<AHardwareBuffer*>(graphicBuffer.get()),
+                                   kPremul_SkAlphaType)
+                         : nullptr;
+    }
+}
+
+sk_sp<SkImage> ImageConsumer::dequeueImage(bool* queueEmpty, SurfaceTexture& st,
+                                           uirenderer::RenderState& renderState) {
+    BufferItem item;
+    status_t err;
+    err = st.acquireBufferLocked(&item, 0);
+    if (err != OK) {
+        if (err != BufferQueue::NO_BUFFER_AVAILABLE) {
+            IMG_LOGE("Error acquiring buffer: %s (%d)", strerror(err), err);
+        } else {
+            int slot = st.mCurrentTexture;
+            if (slot != BufferItem::INVALID_BUFFER_SLOT) {
+                *queueEmpty = true;
+                mImageSlots[slot].createIfNeeded(st.mSlots[slot].mGraphicBuffer);
+                return mImageSlots[slot].mImage;
+            }
+        }
+        return nullptr;
+    }
+
+    int slot = item.mSlot;
+    if (item.mFence->isValid()) {
+        // Wait on the producer fence for the buffer to be ready.
+        if (uirenderer::Properties::getRenderPipelineType() ==
+            uirenderer::RenderPipelineType::SkiaGL) {
+            err = renderState.getRenderThread().eglManager().fenceWait(item.mFence);
+        } else {
+            err = renderState.getRenderThread().vulkanManager().fenceWait(item.mFence);
+        }
+        if (err != OK) {
+            st.releaseBufferLocked(slot, st.mSlots[slot].mGraphicBuffer, EGL_NO_DISPLAY,
+                                   EGL_NO_SYNC_KHR);
+            return nullptr;
+        }
+    }
+
+    // Release old buffer.
+    if (st.mCurrentTexture != BufferItem::INVALID_BUFFER_SLOT) {
+        // If needed, set the released slot's fence to guard against a producer accessing the
+        // buffer before the outstanding accesses have completed.
+        sp<Fence> releaseFence;
+        EGLDisplay display = EGL_NO_DISPLAY;
+        if (uirenderer::Properties::getRenderPipelineType() ==
+            uirenderer::RenderPipelineType::SkiaGL) {
+            auto& eglManager = renderState.getRenderThread().eglManager();
+            display = eglManager.eglDisplay();
+            err = eglManager.createReleaseFence(st.mUseFenceSync, &mImageSlots[slot].mEglFence,
+                                                releaseFence);
+        } else {
+            err = renderState.getRenderThread().vulkanManager().createReleaseFence(releaseFence);
+        }
+        if (OK != err) {
+            st.releaseBufferLocked(slot, st.mSlots[slot].mGraphicBuffer, EGL_NO_DISPLAY,
+                                   EGL_NO_SYNC_KHR);
+            return nullptr;
+        }
+
+        if (releaseFence.get()) {
+            status_t err = st.addReleaseFenceLocked(
+                    st.mCurrentTexture, st.mSlots[st.mCurrentTexture].mGraphicBuffer, releaseFence);
+            if (err != OK) {
+                IMG_LOGE("dequeueImage: error adding release fence: %s (%d)", strerror(-err), err);
+                st.releaseBufferLocked(slot, st.mSlots[slot].mGraphicBuffer, EGL_NO_DISPLAY,
+                                       EGL_NO_SYNC_KHR);
+                return nullptr;
+            }
+        }
+
+        // Finally release the old buffer.
+        status_t status = st.releaseBufferLocked(
+                st.mCurrentTexture, st.mSlots[st.mCurrentTexture].mGraphicBuffer, display,
+                mImageSlots[st.mCurrentTexture].mEglFence);
+        if (status < NO_ERROR) {
+            IMG_LOGE("dequeueImage: failed to release buffer: %s (%d)", strerror(-status), status);
+            err = status;
+            // Keep going, with error raised.
+        }
+    }
+
+    // Update the state.
+    st.mCurrentTexture = slot;
+    st.mCurrentCrop = item.mCrop;
+    st.mCurrentTransform = item.mTransform;
+    st.mCurrentScalingMode = item.mScalingMode;
+    st.mCurrentTimestamp = item.mTimestamp;
+    st.mCurrentDataSpace = item.mDataSpace;
+    st.mCurrentFence = item.mFence;
+    st.mCurrentFenceTime = item.mFenceTime;
+    st.mCurrentFrameNumber = item.mFrameNumber;
+    st.computeCurrentTransformMatrixLocked();
+
+    *queueEmpty = false;
+    mImageSlots[slot].createIfNeeded(st.mSlots[slot].mGraphicBuffer);
+    return mImageSlots[slot].mImage;
+}
+
+} /* namespace android */
diff --git a/libs/hwui/surfacetexture/ImageConsumer.h b/libs/hwui/surfacetexture/ImageConsumer.h
new file mode 100644
index 0000000..31ee8db
--- /dev/null
+++ b/libs/hwui/surfacetexture/ImageConsumer.h
@@ -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.
+ */
+
+#pragma once
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+#include <gui/BufferQueueDefs.h>
+
+#include <SkImage.h>
+#include <cutils/compiler.h>
+#include <gui/BufferItem.h>
+#include <system/graphics.h>
+
+namespace android {
+
+namespace uirenderer {
+class RenderState;
+}
+
+class SurfaceTexture;
+
+/*
+ * ImageConsumer implements the parts of SurfaceTexture that deal with
+ * images consumed by HWUI view system.
+ */
+class ImageConsumer {
+public:
+    sk_sp<SkImage> dequeueImage(bool* queueEmpty, SurfaceTexture& cb,
+                                uirenderer::RenderState& renderState);
+
+    /**
+     * onAcquireBufferLocked amends the ConsumerBase method to update the
+     * mImageSlots array in addition to the ConsumerBase behavior.
+     */
+    void onAcquireBufferLocked(BufferItem* item);
+
+    /**
+     * onReleaseBufferLocked amends the ConsumerBase method to update the
+     * mImageSlots array in addition to the ConsumerBase.
+     */
+    void onReleaseBufferLocked(int slot);
+
+    /**
+     * onFreeBufferLocked frees up the given buffer slot. If the slot has been
+     * initialized this will release the reference to the GraphicBuffer in that
+     * slot and destroy the SkImage in that slot. Otherwise it has no effect.
+     */
+    void onFreeBufferLocked(int slotIndex);
+
+private:
+    /**
+     * ImageSlot contains the information and object references that
+     * ImageConsumer maintains about a BufferQueue buffer slot.
+     */
+    struct ImageSlot {
+        ImageSlot() : mEglFence(EGL_NO_SYNC_KHR) {}
+
+        // mImage is the SkImage created from mGraphicBuffer.
+        sk_sp<SkImage> mImage;
+
+        /**
+         * mEglFence is the EGL sync object that must signal before the buffer
+         * associated with this buffer slot may be dequeued.
+         */
+        EGLSyncKHR mEglFence;
+
+        void createIfNeeded(sp<GraphicBuffer> graphicBuffer);
+    };
+
+    /**
+     * ImageConsumer stores the SkImages that have been allocated by the BufferQueue
+     * for each buffer slot.  It is initialized to null pointers, and gets
+     * filled in with the result of BufferQueue::acquire when the
+     * client dequeues a buffer from a
+     * slot that has not yet been used. The buffer allocated to a slot will also
+     * be replaced if the requested buffer usage or geometry differs from that
+     * of the buffer allocated to a slot.
+     */
+    ImageSlot mImageSlots[BufferQueueDefs::NUM_BUFFER_SLOTS];
+};
+
+}; /* namespace android */
diff --git a/libs/hwui/surfacetexture/SurfaceTexture.cpp b/libs/hwui/surfacetexture/SurfaceTexture.cpp
new file mode 100644
index 0000000..4bff715
--- /dev/null
+++ b/libs/hwui/surfacetexture/SurfaceTexture.cpp
@@ -0,0 +1,496 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <cutils/compiler.h>
+#include <gui/BufferQueue.h>
+#include <math/mat4.h>
+#include <system/window.h>
+
+#include <utils/Trace.h>
+
+#include "Matrix.h"
+#include "SurfaceTexture.h"
+
+namespace android {
+
+// Macros for including the SurfaceTexture name in log messages
+#define SFT_LOGV(x, ...) ALOGV("[%s] " x, mName.string(), ##__VA_ARGS__)
+#define SFT_LOGD(x, ...) ALOGD("[%s] " x, mName.string(), ##__VA_ARGS__)
+#define SFT_LOGW(x, ...) ALOGW("[%s] " x, mName.string(), ##__VA_ARGS__)
+#define SFT_LOGE(x, ...) ALOGE("[%s] " x, mName.string(), ##__VA_ARGS__)
+
+static const mat4 mtxIdentity;
+
+SurfaceTexture::SurfaceTexture(const sp<IGraphicBufferConsumer>& bq, uint32_t tex,
+                               uint32_t texTarget, bool useFenceSync, bool isControlledByApp)
+        : ConsumerBase(bq, isControlledByApp)
+        , mCurrentCrop(Rect::EMPTY_RECT)
+        , mCurrentTransform(0)
+        , mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE)
+        , mCurrentFence(Fence::NO_FENCE)
+        , mCurrentTimestamp(0)
+        , mCurrentDataSpace(HAL_DATASPACE_UNKNOWN)
+        , mCurrentFrameNumber(0)
+        , mDefaultWidth(1)
+        , mDefaultHeight(1)
+        , mFilteringEnabled(true)
+        , mTexName(tex)
+        , mUseFenceSync(useFenceSync)
+        , mTexTarget(texTarget)
+        , mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT)
+        , mOpMode(OpMode::attachedToGL) {
+    SFT_LOGV("SurfaceTexture");
+
+    memcpy(mCurrentTransformMatrix, mtxIdentity.asArray(), sizeof(mCurrentTransformMatrix));
+
+    mConsumer->setConsumerUsageBits(DEFAULT_USAGE_FLAGS);
+}
+
+SurfaceTexture::SurfaceTexture(const sp<IGraphicBufferConsumer>& bq, uint32_t texTarget,
+                               bool useFenceSync, bool isControlledByApp)
+        : ConsumerBase(bq, isControlledByApp)
+        , mCurrentCrop(Rect::EMPTY_RECT)
+        , mCurrentTransform(0)
+        , mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE)
+        , mCurrentFence(Fence::NO_FENCE)
+        , mCurrentTimestamp(0)
+        , mCurrentDataSpace(HAL_DATASPACE_UNKNOWN)
+        , mCurrentFrameNumber(0)
+        , mDefaultWidth(1)
+        , mDefaultHeight(1)
+        , mFilteringEnabled(true)
+        , mTexName(0)
+        , mUseFenceSync(useFenceSync)
+        , mTexTarget(texTarget)
+        , mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT)
+        , mOpMode(OpMode::detached) {
+    SFT_LOGV("SurfaceTexture");
+
+    memcpy(mCurrentTransformMatrix, mtxIdentity.asArray(), sizeof(mCurrentTransformMatrix));
+
+    mConsumer->setConsumerUsageBits(DEFAULT_USAGE_FLAGS);
+}
+
+status_t SurfaceTexture::setDefaultBufferSize(uint32_t w, uint32_t h) {
+    Mutex::Autolock lock(mMutex);
+    if (mAbandoned) {
+        SFT_LOGE("setDefaultBufferSize: SurfaceTexture is abandoned!");
+        return NO_INIT;
+    }
+    mDefaultWidth = w;
+    mDefaultHeight = h;
+    return mConsumer->setDefaultBufferSize(w, h);
+}
+
+status_t SurfaceTexture::updateTexImage() {
+    ATRACE_CALL();
+    SFT_LOGV("updateTexImage");
+    Mutex::Autolock lock(mMutex);
+
+    if (mAbandoned) {
+        SFT_LOGE("updateTexImage: SurfaceTexture is abandoned!");
+        return NO_INIT;
+    }
+
+    return mEGLConsumer.updateTexImage(*this);
+}
+
+status_t SurfaceTexture::releaseTexImage() {
+    // releaseTexImage can be invoked even when not attached to a GL context.
+    ATRACE_CALL();
+    SFT_LOGV("releaseTexImage");
+    Mutex::Autolock lock(mMutex);
+
+    if (mAbandoned) {
+        SFT_LOGE("releaseTexImage: SurfaceTexture is abandoned!");
+        return NO_INIT;
+    }
+
+    return mEGLConsumer.releaseTexImage(*this);
+}
+
+status_t SurfaceTexture::acquireBufferLocked(BufferItem* item, nsecs_t presentWhen,
+                                             uint64_t maxFrameNumber) {
+    status_t err = ConsumerBase::acquireBufferLocked(item, presentWhen, maxFrameNumber);
+    if (err != NO_ERROR) {
+        return err;
+    }
+
+    switch (mOpMode) {
+        case OpMode::attachedToView:
+            mImageConsumer.onAcquireBufferLocked(item);
+            break;
+        case OpMode::attachedToGL:
+            mEGLConsumer.onAcquireBufferLocked(item, *this);
+            break;
+        case OpMode::detached:
+            break;
+    }
+
+    return NO_ERROR;
+}
+
+status_t SurfaceTexture::releaseBufferLocked(int buf, sp<GraphicBuffer> graphicBuffer,
+                                             EGLDisplay display, EGLSyncKHR eglFence) {
+    // release the buffer if it hasn't already been discarded by the
+    // BufferQueue. This can happen, for example, when the producer of this
+    // buffer has reallocated the original buffer slot after this buffer
+    // was acquired.
+    status_t err = ConsumerBase::releaseBufferLocked(buf, graphicBuffer, display, eglFence);
+    // We could be releasing an EGL buffer, even if not currently attached to a GL context.
+    mImageConsumer.onReleaseBufferLocked(buf);
+    mEGLConsumer.onReleaseBufferLocked(buf);
+    return err;
+}
+
+status_t SurfaceTexture::detachFromContext() {
+    ATRACE_CALL();
+    SFT_LOGV("detachFromContext");
+    Mutex::Autolock lock(mMutex);
+
+    if (mAbandoned) {
+        SFT_LOGE("detachFromContext: abandoned SurfaceTexture");
+        return NO_INIT;
+    }
+
+    if (mOpMode != OpMode::attachedToGL) {
+        SFT_LOGE("detachFromContext: SurfaceTexture is not attached to a GL context");
+        return INVALID_OPERATION;
+    }
+
+    status_t err = mEGLConsumer.detachFromContext(*this);
+    if (err == OK) {
+        mOpMode = OpMode::detached;
+    }
+
+    return err;
+}
+
+status_t SurfaceTexture::attachToContext(uint32_t tex) {
+    ATRACE_CALL();
+    SFT_LOGV("attachToContext");
+    Mutex::Autolock lock(mMutex);
+
+    if (mAbandoned) {
+        SFT_LOGE("attachToContext: abandoned SurfaceTexture");
+        return NO_INIT;
+    }
+
+    if (mOpMode != OpMode::detached) {
+        SFT_LOGE(
+                "attachToContext: SurfaceTexture is already attached to a "
+                "context");
+        return INVALID_OPERATION;
+    }
+
+    if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
+        // release possible ImageConsumer cache
+        mImageConsumer.onFreeBufferLocked(mCurrentTexture);
+    }
+
+    return mEGLConsumer.attachToContext(tex, *this);
+}
+
+void SurfaceTexture::attachToView() {
+    ATRACE_CALL();
+    Mutex::Autolock _l(mMutex);
+    if (mAbandoned) {
+        SFT_LOGE("attachToView: abandoned SurfaceTexture");
+        return;
+    }
+    if (mOpMode == OpMode::detached) {
+        mOpMode = OpMode::attachedToView;
+
+        if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
+            // release possible EGLConsumer texture cache
+            mEGLConsumer.onFreeBufferLocked(mCurrentTexture);
+            mEGLConsumer.onAbandonLocked();
+        }
+    } else {
+        SFT_LOGE("attachToView: already attached");
+    }
+}
+
+void SurfaceTexture::detachFromView() {
+    ATRACE_CALL();
+    Mutex::Autolock _l(mMutex);
+
+    if (mAbandoned) {
+        SFT_LOGE("detachFromView: abandoned SurfaceTexture");
+        return;
+    }
+
+    if (mOpMode == OpMode::attachedToView) {
+        mOpMode = OpMode::detached;
+    } else {
+        SFT_LOGE("detachFromView: not attached to View");
+    }
+}
+
+uint32_t SurfaceTexture::getCurrentTextureTarget() const {
+    return mTexTarget;
+}
+
+void SurfaceTexture::getTransformMatrix(float mtx[16]) {
+    Mutex::Autolock lock(mMutex);
+    memcpy(mtx, mCurrentTransformMatrix, sizeof(mCurrentTransformMatrix));
+}
+
+void SurfaceTexture::setFilteringEnabled(bool enabled) {
+    Mutex::Autolock lock(mMutex);
+    if (mAbandoned) {
+        SFT_LOGE("setFilteringEnabled: SurfaceTexture is abandoned!");
+        return;
+    }
+    bool needsRecompute = mFilteringEnabled != enabled;
+    mFilteringEnabled = enabled;
+
+    if (needsRecompute && mCurrentTexture == BufferQueue::INVALID_BUFFER_SLOT) {
+        SFT_LOGD("setFilteringEnabled called with no current item");
+    }
+
+    if (needsRecompute && mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
+        computeCurrentTransformMatrixLocked();
+    }
+}
+
+void SurfaceTexture::computeCurrentTransformMatrixLocked() {
+    SFT_LOGV("computeCurrentTransformMatrixLocked");
+    sp<GraphicBuffer> buf = (mCurrentTexture == BufferQueue::INVALID_BUFFER_SLOT)
+                                    ? nullptr
+                                    : mSlots[mCurrentTexture].mGraphicBuffer;
+    if (buf == nullptr) {
+        SFT_LOGD("computeCurrentTransformMatrixLocked: no current item");
+    }
+    computeTransformMatrix(mCurrentTransformMatrix, buf, mCurrentCrop, mCurrentTransform,
+                           mFilteringEnabled);
+}
+
+void SurfaceTexture::computeTransformMatrix(float outTransform[16], const sp<GraphicBuffer>& buf,
+                                            const Rect& cropRect, uint32_t transform,
+                                            bool filtering) {
+    // Transform matrices
+    static const mat4 mtxFlipH(-1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1);
+    static const mat4 mtxFlipV(1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1);
+    static const mat4 mtxRot90(0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1);
+
+    mat4 xform;
+    if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_H) {
+        xform *= mtxFlipH;
+    }
+    if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_V) {
+        xform *= mtxFlipV;
+    }
+    if (transform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
+        xform *= mtxRot90;
+    }
+
+    if (!cropRect.isEmpty() && buf.get()) {
+        float tx = 0.0f, ty = 0.0f, sx = 1.0f, sy = 1.0f;
+        float bufferWidth = buf->getWidth();
+        float bufferHeight = buf->getHeight();
+        float shrinkAmount = 0.0f;
+        if (filtering) {
+            // In order to prevent bilinear sampling beyond the edge of the
+            // crop rectangle we may need to shrink it by 2 texels in each
+            // dimension.  Normally this would just need to take 1/2 a texel
+            // off each end, but because the chroma channels of YUV420 images
+            // are subsampled we may need to shrink the crop region by a whole
+            // texel on each side.
+            switch (buf->getPixelFormat()) {
+                case PIXEL_FORMAT_RGBA_8888:
+                case PIXEL_FORMAT_RGBX_8888:
+                case PIXEL_FORMAT_RGBA_FP16:
+                case PIXEL_FORMAT_RGBA_1010102:
+                case PIXEL_FORMAT_RGB_888:
+                case PIXEL_FORMAT_RGB_565:
+                case PIXEL_FORMAT_BGRA_8888:
+                    // We know there's no subsampling of any channels, so we
+                    // only need to shrink by a half a pixel.
+                    shrinkAmount = 0.5;
+                    break;
+
+                default:
+                    // If we don't recognize the format, we must assume the
+                    // worst case (that we care about), which is YUV420.
+                    shrinkAmount = 1.0;
+                    break;
+            }
+        }
+
+        // Only shrink the dimensions that are not the size of the buffer.
+        if (cropRect.width() < bufferWidth) {
+            tx = (float(cropRect.left) + shrinkAmount) / bufferWidth;
+            sx = (float(cropRect.width()) - (2.0f * shrinkAmount)) / bufferWidth;
+        }
+        if (cropRect.height() < bufferHeight) {
+            ty = (float(bufferHeight - cropRect.bottom) + shrinkAmount) / bufferHeight;
+            sy = (float(cropRect.height()) - (2.0f * shrinkAmount)) / bufferHeight;
+        }
+
+        mat4 crop(sx, 0, 0, 0, 0, sy, 0, 0, 0, 0, 1, 0, tx, ty, 0, 1);
+        xform = crop * xform;
+    }
+
+    // SurfaceFlinger expects the top of its window textures to be at a Y
+    // coordinate of 0, so SurfaceTexture must behave the same way.  We don't
+    // want to expose this to applications, however, so we must add an
+    // additional vertical flip to the transform after all the other transforms.
+    xform = mtxFlipV * xform;
+
+    memcpy(outTransform, xform.asArray(), sizeof(xform));
+}
+
+Rect SurfaceTexture::scaleDownCrop(const Rect& crop, uint32_t bufferWidth, uint32_t bufferHeight) {
+    Rect outCrop = crop;
+
+    uint32_t newWidth = static_cast<uint32_t>(crop.width());
+    uint32_t newHeight = static_cast<uint32_t>(crop.height());
+
+    if (newWidth * bufferHeight > newHeight * bufferWidth) {
+        newWidth = newHeight * bufferWidth / bufferHeight;
+        ALOGV("too wide: newWidth = %d", newWidth);
+    } else if (newWidth * bufferHeight < newHeight * bufferWidth) {
+        newHeight = newWidth * bufferHeight / bufferWidth;
+        ALOGV("too tall: newHeight = %d", newHeight);
+    }
+
+    uint32_t currentWidth = static_cast<uint32_t>(crop.width());
+    uint32_t currentHeight = static_cast<uint32_t>(crop.height());
+
+    // The crop is too wide
+    if (newWidth < currentWidth) {
+        uint32_t dw = currentWidth - newWidth;
+        auto halfdw = dw / 2;
+        outCrop.left += halfdw;
+        // Not halfdw because it would subtract 1 too few when dw is odd
+        outCrop.right -= (dw - halfdw);
+        // The crop is too tall
+    } else if (newHeight < currentHeight) {
+        uint32_t dh = currentHeight - newHeight;
+        auto halfdh = dh / 2;
+        outCrop.top += halfdh;
+        // Not halfdh because it would subtract 1 too few when dh is odd
+        outCrop.bottom -= (dh - halfdh);
+    }
+
+    ALOGV("getCurrentCrop final crop [%d,%d,%d,%d]", outCrop.left, outCrop.top, outCrop.right,
+          outCrop.bottom);
+
+    return outCrop;
+}
+
+nsecs_t SurfaceTexture::getTimestamp() {
+    SFT_LOGV("getTimestamp");
+    Mutex::Autolock lock(mMutex);
+    return mCurrentTimestamp;
+}
+
+android_dataspace SurfaceTexture::getCurrentDataSpace() {
+    SFT_LOGV("getCurrentDataSpace");
+    Mutex::Autolock lock(mMutex);
+    return mCurrentDataSpace;
+}
+
+uint64_t SurfaceTexture::getFrameNumber() {
+    SFT_LOGV("getFrameNumber");
+    Mutex::Autolock lock(mMutex);
+    return mCurrentFrameNumber;
+}
+
+Rect SurfaceTexture::getCurrentCrop() const {
+    Mutex::Autolock lock(mMutex);
+    return (mCurrentScalingMode == NATIVE_WINDOW_SCALING_MODE_SCALE_CROP)
+                   ? scaleDownCrop(mCurrentCrop, mDefaultWidth, mDefaultHeight)
+                   : mCurrentCrop;
+}
+
+uint32_t SurfaceTexture::getCurrentTransform() const {
+    Mutex::Autolock lock(mMutex);
+    return mCurrentTransform;
+}
+
+uint32_t SurfaceTexture::getCurrentScalingMode() const {
+    Mutex::Autolock lock(mMutex);
+    return mCurrentScalingMode;
+}
+
+sp<Fence> SurfaceTexture::getCurrentFence() const {
+    Mutex::Autolock lock(mMutex);
+    return mCurrentFence;
+}
+
+std::shared_ptr<FenceTime> SurfaceTexture::getCurrentFenceTime() const {
+    Mutex::Autolock lock(mMutex);
+    return mCurrentFenceTime;
+}
+
+void SurfaceTexture::freeBufferLocked(int slotIndex) {
+    SFT_LOGV("freeBufferLocked: slotIndex=%d", slotIndex);
+    if (slotIndex == mCurrentTexture) {
+        mCurrentTexture = BufferQueue::INVALID_BUFFER_SLOT;
+    }
+    // The slotIndex buffer could have EGL or SkImage cache, but there is no way to tell for sure.
+    // Buffers can be freed after SurfaceTexture has detached from GL context or View.
+    mImageConsumer.onFreeBufferLocked(slotIndex);
+    mEGLConsumer.onFreeBufferLocked(slotIndex);
+    ConsumerBase::freeBufferLocked(slotIndex);
+}
+
+void SurfaceTexture::abandonLocked() {
+    SFT_LOGV("abandonLocked");
+    mEGLConsumer.onAbandonLocked();
+    ConsumerBase::abandonLocked();
+}
+
+status_t SurfaceTexture::setConsumerUsageBits(uint64_t usage) {
+    return ConsumerBase::setConsumerUsageBits(usage | DEFAULT_USAGE_FLAGS);
+}
+
+void SurfaceTexture::dumpLocked(String8& result, const char* prefix) const {
+    result.appendFormat(
+            "%smTexName=%d mCurrentTexture=%d\n"
+            "%smCurrentCrop=[%d,%d,%d,%d] mCurrentTransform=%#x\n",
+            prefix, mTexName, mCurrentTexture, prefix, mCurrentCrop.left, mCurrentCrop.top,
+            mCurrentCrop.right, mCurrentCrop.bottom, mCurrentTransform);
+
+    ConsumerBase::dumpLocked(result, prefix);
+}
+
+sk_sp<SkImage> SurfaceTexture::dequeueImage(SkMatrix& transformMatrix, android_dataspace& dataSpace,
+                                            bool* queueEmpty,
+                                            uirenderer::RenderState& renderState) {
+    Mutex::Autolock _l(mMutex);
+
+    if (mAbandoned) {
+        SFT_LOGE("dequeueImage: SurfaceTexture is abandoned!");
+        return nullptr;
+    }
+
+    if (mOpMode != OpMode::attachedToView) {
+        SFT_LOGE("dequeueImage: SurfaceTexture is not attached to a View");
+        return nullptr;
+    }
+
+    auto image = mImageConsumer.dequeueImage(queueEmpty, *this, renderState);
+    if (image.get()) {
+        uirenderer::mat4(mCurrentTransformMatrix).copyTo(transformMatrix);
+        dataSpace = mCurrentDataSpace;
+    }
+    return image;
+}
+
+};  // namespace android
diff --git a/libs/hwui/surfacetexture/SurfaceTexture.h b/libs/hwui/surfacetexture/SurfaceTexture.h
new file mode 100644
index 0000000..db392a9
--- /dev/null
+++ b/libs/hwui/surfacetexture/SurfaceTexture.h
@@ -0,0 +1,452 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <gui/BufferQueueDefs.h>
+#include <gui/ConsumerBase.h>
+
+#include <ui/FenceTime.h>
+#include <ui/GraphicBuffer.h>
+
+#include <utils/Mutex.h>
+#include <utils/String8.h>
+
+#include "EGLConsumer.h"
+#include "ImageConsumer.h"
+
+namespace android {
+
+namespace uirenderer {
+class RenderState;
+}
+
+/*
+ * SurfaceTexture consumes buffers of graphics data from a BufferQueue,
+ * and makes them available to HWUI render thread as a SkImage and to
+ * an application GL render thread as an OpenGL texture.
+ *
+ * When attached to an application GL render thread, a typical usage
+ * pattern is to set up the SurfaceTexture with the
+ * desired options, and call updateTexImage() when a new frame is desired.
+ * If a new frame is available, the texture will be updated.  If not,
+ * the previous contents are retained.
+ *
+ * When attached to a HWUI render thread, the TextureView implementation
+ * calls dequeueImage, which either pulls a new SkImage or returns the
+ * last cached SkImage if BufferQueue is empty.
+ * When attached to HWUI render thread, SurfaceTexture is compatible to
+ * both Vulkan and GL drawing pipelines.
+ */
+class ANDROID_API SurfaceTexture : public ConsumerBase {
+public:
+    enum { TEXTURE_EXTERNAL = 0x8D65 };  // GL_TEXTURE_EXTERNAL_OES
+    typedef ConsumerBase::FrameAvailableListener FrameAvailableListener;
+
+    /**
+     * SurfaceTexture constructs a new SurfaceTexture object. If the constructor with
+     * the tex parameter is used, tex indicates the name of the OpenGL ES
+     * texture to which images are to be streamed. texTarget specifies the
+     * OpenGL ES texture target to which the texture will be bound in
+     * updateTexImage. useFenceSync specifies whether fences should be used to
+     * synchronize access to buffers if that behavior is enabled at
+     * compile-time.
+     *
+     * A SurfaceTexture may be detached from one OpenGL ES context and then
+     * attached to a different context using the detachFromContext and
+     * attachToContext methods, respectively. The intention of these methods is
+     * purely to allow a SurfaceTexture to be transferred from one consumer
+     * context to another. If such a transfer is not needed there is no
+     * requirement that either of these methods be called.
+     *
+     * If the constructor with the tex parameter is used, the SurfaceTexture is
+     * created in a state where it is considered attached to an OpenGL ES
+     * context for the purposes of the attachToContext and detachFromContext
+     * methods. However, despite being considered "attached" to a context, the
+     * specific OpenGL ES context doesn't get latched until the first call to
+     * updateTexImage. After that point, all calls to updateTexImage must be
+     * made with the same OpenGL ES context current.
+     *
+     * If the constructor without the tex parameter is used, the SurfaceTexture is
+     * created in a detached state, and attachToContext must be called before
+     * calls to updateTexImage.
+     */
+    SurfaceTexture(const sp<IGraphicBufferConsumer>& bq, uint32_t tex, uint32_t texureTarget,
+                   bool useFenceSync, bool isControlledByApp);
+
+    SurfaceTexture(const sp<IGraphicBufferConsumer>& bq, uint32_t texureTarget, bool useFenceSync,
+                   bool isControlledByApp);
+
+    /**
+     * updateTexImage acquires the most recently queued buffer, and sets the
+     * image contents of the target texture to it.
+     *
+     * This call may only be made while the OpenGL ES context to which the
+     * target texture belongs is bound to the calling thread.
+     *
+     * This calls doGLFenceWait to ensure proper synchronization.
+     */
+    status_t updateTexImage();
+
+    /**
+     * releaseTexImage releases the texture acquired in updateTexImage().
+     * This is intended to be used in single buffer mode.
+     *
+     * This call may only be made while the OpenGL ES context to which the
+     * target texture belongs is bound to the calling thread.
+     */
+    status_t releaseTexImage();
+
+    /**
+     * getTransformMatrix retrieves the 4x4 texture coordinate transform matrix
+     * associated with the texture image set by the most recent call to
+     * updateTexImage.
+     *
+     * This transform matrix maps 2D homogeneous texture coordinates of the form
+     * (s, t, 0, 1) with s and t in the inclusive range [0, 1] to the texture
+     * coordinate that should be used to sample that location from the texture.
+     * Sampling the texture outside of the range of this transform is undefined.
+     *
+     * This transform is necessary to compensate for transforms that the stream
+     * content producer may implicitly apply to the content. By forcing users of
+     * a SurfaceTexture to apply this transform we avoid performing an extra
+     * copy of the data that would be needed to hide the transform from the
+     * user.
+     *
+     * The matrix is stored in column-major order so that it may be passed
+     * directly to OpenGL ES via the glLoadMatrixf or glUniformMatrix4fv
+     * functions.
+     */
+    void getTransformMatrix(float mtx[16]);
+
+    /**
+     * Computes the transform matrix documented by getTransformMatrix
+     * from the BufferItem sub parts.
+     */
+    static void computeTransformMatrix(float outTransform[16], const sp<GraphicBuffer>& buf,
+                                       const Rect& cropRect, uint32_t transform, bool filtering);
+
+    /**
+     * Scale the crop down horizontally or vertically such that it has the
+     * same aspect ratio as the buffer does.
+     */
+    static Rect scaleDownCrop(const Rect& crop, uint32_t bufferWidth, uint32_t bufferHeight);
+
+    /**
+     * getTimestamp retrieves the timestamp associated with the texture image
+     * set by the most recent call to updateTexImage.
+     *
+     * The timestamp is in nanoseconds, and is monotonically increasing. Its
+     * other semantics (zero point, etc) are source-dependent and should be
+     * documented by the source.
+     */
+    int64_t getTimestamp();
+
+    /**
+     * getDataSpace retrieves the DataSpace associated with the texture image
+     * set by the most recent call to updateTexImage.
+     */
+    android_dataspace getCurrentDataSpace();
+
+    /**
+     * getFrameNumber retrieves the frame number associated with the texture
+     * image set by the most recent call to updateTexImage.
+     *
+     * The frame number is an incrementing counter set to 0 at the creation of
+     * the BufferQueue associated with this consumer.
+     */
+    uint64_t getFrameNumber();
+
+    /**
+     * setDefaultBufferSize is used to set the size of buffers returned by
+     * requestBuffers when a with and height of zero is requested.
+     * A call to setDefaultBufferSize() may trigger requestBuffers() to
+     * be called from the client.
+     * The width and height parameters must be no greater than the minimum of
+     * GL_MAX_VIEWPORT_DIMS and GL_MAX_TEXTURE_SIZE (see: glGetIntegerv).
+     * An error due to invalid dimensions might not be reported until
+     * updateTexImage() is called.
+     */
+    status_t setDefaultBufferSize(uint32_t width, uint32_t height);
+
+    /**
+     * setFilteringEnabled sets whether the transform matrix should be computed
+     * for use with bilinear filtering.
+     */
+    void setFilteringEnabled(bool enabled);
+
+    /**
+     * getCurrentTextureTarget returns the texture target of the current
+     * texture as returned by updateTexImage().
+     */
+    uint32_t getCurrentTextureTarget() const;
+
+    /**
+     * getCurrentCrop returns the cropping rectangle of the current buffer.
+     */
+    Rect getCurrentCrop() const;
+
+    /**
+     * getCurrentTransform returns the transform of the current buffer.
+     */
+    uint32_t getCurrentTransform() const;
+
+    /**
+     * getCurrentScalingMode returns the scaling mode of the current buffer.
+     */
+    uint32_t getCurrentScalingMode() const;
+
+    /**
+     * getCurrentFence returns the fence indicating when the current buffer is
+     * ready to be read from.
+     */
+    sp<Fence> getCurrentFence() const;
+
+    /**
+     * getCurrentFence returns the FenceTime indicating when the current
+     * buffer is ready to be read from.
+     */
+    std::shared_ptr<FenceTime> getCurrentFenceTime() const;
+
+    /**
+     * setConsumerUsageBits overrides the ConsumerBase method to OR
+     * DEFAULT_USAGE_FLAGS to usage.
+     */
+    status_t setConsumerUsageBits(uint64_t usage);
+
+    /**
+     * detachFromContext detaches the SurfaceTexture from the calling thread's
+     * current OpenGL ES context.  This context must be the same as the context
+     * that was current for previous calls to updateTexImage.
+     *
+     * Detaching a SurfaceTexture from an OpenGL ES context will result in the
+     * deletion of the OpenGL ES texture object into which the images were being
+     * streamed.  After a SurfaceTexture has been detached from the OpenGL ES
+     * context calls to updateTexImage will fail returning INVALID_OPERATION
+     * until the SurfaceTexture is attached to a new OpenGL ES context using the
+     * attachToContext method.
+     */
+    status_t detachFromContext();
+
+    /**
+     * attachToContext attaches a SurfaceTexture that is currently in the
+     * 'detached' state to the current OpenGL ES context.  A SurfaceTexture is
+     * in the 'detached' state iff detachFromContext has successfully been
+     * called and no calls to attachToContext have succeeded since the last
+     * detachFromContext call.  Calls to attachToContext made on a
+     * SurfaceTexture that is not in the 'detached' state will result in an
+     * INVALID_OPERATION error.
+     *
+     * The tex argument specifies the OpenGL ES texture object name in the
+     * new context into which the image contents will be streamed.  A successful
+     * call to attachToContext will result in this texture object being bound to
+     * the texture target and populated with the image contents that were
+     * current at the time of the last call to detachFromContext.
+     */
+    status_t attachToContext(uint32_t tex);
+
+    sk_sp<SkImage> dequeueImage(SkMatrix& transformMatrix, android_dataspace& dataSpace,
+                                bool* queueEmpty, uirenderer::RenderState& renderState);
+
+    /**
+     * attachToView attaches a SurfaceTexture that is currently in the
+     * 'detached' state to HWUI View system.
+     */
+    void attachToView();
+
+    /**
+     * detachFromView detaches a SurfaceTexture from HWUI View system.
+     */
+    void detachFromView();
+
+protected:
+    /**
+     * abandonLocked overrides the ConsumerBase method to clear
+     * mCurrentTextureImage in addition to the ConsumerBase behavior.
+     */
+    virtual void abandonLocked();
+
+    /**
+     * dumpLocked overrides the ConsumerBase method to dump SurfaceTexture-
+     * specific info in addition to the ConsumerBase behavior.
+     */
+    virtual void dumpLocked(String8& result, const char* prefix) const override;
+
+    /**
+     * acquireBufferLocked overrides the ConsumerBase method to update the
+     * mEglSlots array in addition to the ConsumerBase behavior.
+     */
+    virtual status_t acquireBufferLocked(BufferItem* item, nsecs_t presentWhen,
+                                         uint64_t maxFrameNumber = 0) override;
+
+    /**
+     * releaseBufferLocked overrides the ConsumerBase method to update the
+     * mEglSlots array in addition to the ConsumerBase.
+     */
+    virtual status_t releaseBufferLocked(int slot, const sp<GraphicBuffer> graphicBuffer,
+                                         EGLDisplay display, EGLSyncKHR eglFence) override;
+
+    /**
+     * freeBufferLocked frees up the given buffer slot. If the slot has been
+     * initialized this will release the reference to the GraphicBuffer in that
+     * slot and destroy the EGLImage in that slot.  Otherwise it has no effect.
+     *
+     * This method must be called with mMutex locked.
+     */
+    virtual void freeBufferLocked(int slotIndex);
+
+    /**
+     * computeCurrentTransformMatrixLocked computes the transform matrix for the
+     * current texture.  It uses mCurrentTransform and the current GraphicBuffer
+     * to compute this matrix and stores it in mCurrentTransformMatrix.
+     * mCurrentTextureImage must not be NULL.
+     */
+    void computeCurrentTransformMatrixLocked();
+
+    /**
+     * The default consumer usage flags that SurfaceTexture always sets on its
+     * BufferQueue instance; these will be OR:d with any additional flags passed
+     * from the SurfaceTexture user. In particular, SurfaceTexture will always
+     * consume buffers as hardware textures.
+     */
+    static const uint64_t DEFAULT_USAGE_FLAGS = GraphicBuffer::USAGE_HW_TEXTURE;
+
+    /**
+     * mCurrentCrop is the crop rectangle that applies to the current texture.
+     * It gets set each time updateTexImage is called.
+     */
+    Rect mCurrentCrop;
+
+    /**
+     * mCurrentTransform is the transform identifier for the current texture. It
+     * gets set each time updateTexImage is called.
+     */
+    uint32_t mCurrentTransform;
+
+    /**
+     * mCurrentScalingMode is the scaling mode for the current texture. It gets
+     * set each time updateTexImage is called.
+     */
+    uint32_t mCurrentScalingMode;
+
+    /**
+     * mCurrentFence is the fence received from BufferQueue in updateTexImage.
+     */
+    sp<Fence> mCurrentFence;
+
+    /**
+     * The FenceTime wrapper around mCurrentFence.
+     */
+    std::shared_ptr<FenceTime> mCurrentFenceTime{FenceTime::NO_FENCE};
+
+    /**
+     * mCurrentTransformMatrix is the transform matrix for the current texture.
+     * It gets computed by computeTransformMatrix each time updateTexImage is
+     * called.
+     */
+    float mCurrentTransformMatrix[16];
+
+    /**
+     * mCurrentTimestamp is the timestamp for the current texture. It
+     * gets set each time updateTexImage is called.
+     */
+    int64_t mCurrentTimestamp;
+
+    /**
+     * mCurrentDataSpace is the dataspace for the current texture. It
+     * gets set each time updateTexImage is called.
+     */
+    android_dataspace mCurrentDataSpace;
+
+    /**
+     * mCurrentFrameNumber is the frame counter for the current texture.
+     * It gets set each time updateTexImage is called.
+     */
+    uint64_t mCurrentFrameNumber;
+
+    uint32_t mDefaultWidth, mDefaultHeight;
+
+    /**
+     * mFilteringEnabled indicates whether the transform matrix is computed for
+     * use with bilinear filtering. It defaults to true and is changed by
+     * setFilteringEnabled().
+     */
+    bool mFilteringEnabled;
+
+    /**
+     * mTexName is the name of the OpenGL texture to which streamed images will
+     * be bound when updateTexImage is called. It is set at construction time
+     * and can be changed with a call to attachToContext.
+     */
+    uint32_t mTexName;
+
+    /**
+     * mUseFenceSync indicates whether creation of the EGL_KHR_fence_sync
+     * extension should be used to prevent buffers from being dequeued before
+     * it's safe for them to be written. It gets set at construction time and
+     * never changes.
+     */
+    const bool mUseFenceSync;
+
+    /**
+     * mTexTarget is the GL texture target with which the GL texture object is
+     * associated.  It is set in the constructor and never changed.  It is
+     * almost always GL_TEXTURE_EXTERNAL_OES except for one use case in Android
+     * Browser.  In that case it is set to GL_TEXTURE_2D to allow
+     * glCopyTexSubImage to read from the texture.  This is a hack to work
+     * around a GL driver limitation on the number of FBO attachments, which the
+     * browser's tile cache exceeds.
+     */
+    const uint32_t mTexTarget;
+
+    /**
+     * mCurrentTexture is the buffer slot index of the buffer that is currently
+     * bound to the OpenGL texture. It is initialized to INVALID_BUFFER_SLOT,
+     * indicating that no buffer slot is currently bound to the texture. Note,
+     * however, that a value of INVALID_BUFFER_SLOT does not necessarily mean
+     * that no buffer is bound to the texture. A call to setBufferCount will
+     * reset mCurrentTexture to INVALID_BUFFER_SLOT.
+     */
+    int mCurrentTexture;
+
+    enum class OpMode { detached, attachedToView, attachedToGL };
+    /**
+     * mOpMode indicates whether the SurfaceTexture is currently attached to
+     * an OpenGL ES context or the HWUI view system.  For legacy reasons, this is initialized to,
+     * "attachedToGL" indicating that the SurfaceTexture is considered to be attached to
+     * whatever GL context is current at the time of the first updateTexImage call.
+     * It is set to "detached" by detachFromContext, and then set to "attachedToGL" again by
+     * attachToContext.
+     * attachToView/detachFromView are used to attach/detach from HWUI view system.
+     */
+    OpMode mOpMode;
+
+    /**
+     * mEGLConsumer has SurfaceTexture logic used when attached to GL context.
+     */
+    EGLConsumer mEGLConsumer;
+
+    /**
+     * mImageConsumer has SurfaceTexture logic used when attached to HWUI view system.
+     */
+    ImageConsumer mImageConsumer;
+
+    friend class ImageConsumer;
+    friend class EGLConsumer;
+};
+
+// ----------------------------------------------------------------------------
+};  // namespace android
diff --git a/libs/hwui/tests/common/LeakChecker.cpp b/libs/hwui/tests/common/LeakChecker.cpp
index 5b36154..d2d37dc 100644
--- a/libs/hwui/tests/common/LeakChecker.cpp
+++ b/libs/hwui/tests/common/LeakChecker.cpp
@@ -16,7 +16,6 @@
 
 #include "LeakChecker.h"
 
-#include "Caches.h"
 #include "TestUtils.h"
 
 #include <memunreachable/memunreachable.h>
@@ -71,9 +70,6 @@
     // thread-local caches so some leaks will not be properly tagged as leaks
     UnreachableMemoryInfo rtMemInfo;
     TestUtils::runOnRenderThread([&rtMemInfo](renderthread::RenderThread& thread) {
-        if (Caches::hasInstance()) {
-            Caches::getInstance().tasks.stop();
-        }
         // Check for leaks
         if (!GetUnreachableMemory(rtMemInfo)) {
             cerr << "Failed to get unreachable memory!" << endl;
diff --git a/libs/hwui/tests/common/TestUtils.cpp b/libs/hwui/tests/common/TestUtils.cpp
index 6958634..66b9b85 100644
--- a/libs/hwui/tests/common/TestUtils.cpp
+++ b/libs/hwui/tests/common/TestUtils.cpp
@@ -67,16 +67,14 @@
         renderthread::RenderThread& renderThread, uint32_t width, uint32_t height,
         const SkMatrix& transform) {
     sp<DeferredLayerUpdater> layerUpdater = createTextureLayerUpdater(renderThread);
-    layerUpdater->backingLayer()->getTransform().load(transform);
+    layerUpdater->backingLayer()->getTransform() = transform;
     layerUpdater->setSize(width, height);
     layerUpdater->setTransform(&transform);
 
     // updateLayer so it's ready to draw
-    layerUpdater->updateLayer(true, Matrix4::identity().data, HAL_DATASPACE_UNKNOWN);
-    if (layerUpdater->backingLayer()->getApi() == Layer::Api::OpenGL) {
-        static_cast<GlLayer*>(layerUpdater->backingLayer())
-                ->setRenderTarget(GL_TEXTURE_EXTERNAL_OES);
-    }
+    SkMatrix identity;
+    identity.setIdentity();
+    layerUpdater->updateLayer(true, identity, HAL_DATASPACE_UNKNOWN, nullptr);
     return layerUpdater;
 }
 
@@ -117,7 +115,6 @@
     if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaVulkan) {
         renderThread.vulkanManager().destroy();
     } else {
-        renderThread.renderState().flush(Caches::FlushMode::Full);
         renderThread.destroyGlContext();
     }
 }
diff --git a/libs/hwui/tests/common/TestUtils.h b/libs/hwui/tests/common/TestUtils.h
index 743f809..0e6582c 100644
--- a/libs/hwui/tests/common/TestUtils.h
+++ b/libs/hwui/tests/common/TestUtils.h
@@ -18,7 +18,6 @@
 
 #include <DeviceInfo.h>
 #include <DisplayList.h>
-#include <GlLayer.h>
 #include <Matrix.h>
 #include <Properties.h>
 #include <Rect.h>
diff --git a/libs/hwui/tests/unit/DeferredLayerUpdaterTests.cpp b/libs/hwui/tests/unit/DeferredLayerUpdaterTests.cpp
index f29830f..6c8775b 100644
--- a/libs/hwui/tests/unit/DeferredLayerUpdaterTests.cpp
+++ b/libs/hwui/tests/unit/DeferredLayerUpdaterTests.cpp
@@ -15,12 +15,13 @@
  */
 
 #include "DeferredLayerUpdater.h"
-#include "GlLayer.h"
 #include "Properties.h"
 
 #include "tests/common/TestUtils.h"
 
 #include <gtest/gtest.h>
+#include <SkBitmap.h>
+#include <SkImage.h>
 
 using namespace android;
 using namespace android::uirenderer;
@@ -31,10 +32,6 @@
     layerUpdater->setBlend(true);
 
     // updates are deferred so the backing layer should still be in its default state
-    if (layerUpdater->backingLayer()->getApi() == Layer::Api::OpenGL) {
-        GlLayer* glLayer = static_cast<GlLayer*>(layerUpdater->backingLayer());
-        EXPECT_EQ((uint32_t)GL_NONE, glLayer->getRenderTarget());
-    }
     EXPECT_EQ(0u, layerUpdater->backingLayer()->getWidth());
     EXPECT_EQ(0u, layerUpdater->backingLayer()->getHeight());
     EXPECT_FALSE(layerUpdater->backingLayer()->getForceFilter());
@@ -42,19 +39,13 @@
     EXPECT_EQ(Matrix4::identity(), layerUpdater->backingLayer()->getTexTransform());
 
     // push the deferred updates to the layer
-    Matrix4 scaledMatrix;
-    scaledMatrix.loadScale(0.5, 0.5, 0.0);
-    layerUpdater->updateLayer(true, scaledMatrix.data, HAL_DATASPACE_UNKNOWN);
-    if (layerUpdater->backingLayer()->getApi() == Layer::Api::OpenGL) {
-        GlLayer* glLayer = static_cast<GlLayer*>(layerUpdater->backingLayer());
-        glLayer->setRenderTarget(GL_TEXTURE_EXTERNAL_OES);
-    }
+    SkMatrix scaledMatrix = SkMatrix::MakeScale(0.5, 0.5);
+    SkBitmap bitmap;
+    bitmap.allocN32Pixels(16, 16);
+    sk_sp<SkImage> layerImage = SkImage::MakeFromBitmap(bitmap);
+    layerUpdater->updateLayer(true, scaledMatrix, HAL_DATASPACE_UNKNOWN, layerImage);
 
     // the backing layer should now have all the properties applied.
-    if (layerUpdater->backingLayer()->getApi() == Layer::Api::OpenGL) {
-        GlLayer* glLayer = static_cast<GlLayer*>(layerUpdater->backingLayer());
-        EXPECT_EQ((uint32_t)GL_TEXTURE_EXTERNAL_OES, glLayer->getRenderTarget());
-    }
     EXPECT_EQ(100u, layerUpdater->backingLayer()->getWidth());
     EXPECT_EQ(100u, layerUpdater->backingLayer()->getHeight());
     EXPECT_TRUE(layerUpdater->backingLayer()->getForceFilter());
diff --git a/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp b/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp
index 48bc8e4..2926ef3 100644
--- a/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp
+++ b/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp
@@ -537,7 +537,7 @@
     layerUpdateQueue.enqueueLayerWithDamage(child.get(),
                                             android::uirenderer::Rect(LAYER_WIDTH, LAYER_HEIGHT));
     auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
-    pipeline->renderLayersImpl(layerUpdateQueue, true, false);
+    pipeline->renderLayersImpl(layerUpdateQueue, true);
     EXPECT_EQ(1, drawCounter);  // assert index 0 is drawn on the layer
 
     RenderNodeDrawable drawable(parent.get(), surfaceLayer1->getCanvas(), true);
diff --git a/libs/hwui/tests/unit/ShaderCacheTests.cpp b/libs/hwui/tests/unit/ShaderCacheTests.cpp
index 43080a9..1433aa0 100644
--- a/libs/hwui/tests/unit/ShaderCacheTests.cpp
+++ b/libs/hwui/tests/unit/ShaderCacheTests.cpp
@@ -48,11 +48,18 @@
      */
     static void terminate(ShaderCache& cache, bool saveContent) {
         std::lock_guard<std::mutex> lock(cache.mMutex);
-        if (cache.mInitialized && cache.mBlobCache && saveContent) {
-            cache.mBlobCache->writeToFile();
-        }
+        cache.mSavePending = saveContent;
+        cache.saveToDiskLocked();
         cache.mBlobCache = NULL;
     }
+
+    /**
+     *
+     */
+    template <typename T>
+    static bool validateCache(ShaderCache& cache, std::vector<T> hash) {
+        return cache.validateCache(hash.data(), hash.size() * sizeof(T));
+    }
 };
 
 } /* namespace skiapipeline */
@@ -75,26 +82,39 @@
     return false;
 }
 
-bool checkShader(const sk_sp<SkData>& shader, const char* program) {
-    sk_sp<SkData> shader2 = SkData::MakeWithCString(program);
-    return shader->size() == shader2->size()
-            && 0 == memcmp(shader->data(), shader2->data(), shader->size());
+inline bool
+checkShader(const sk_sp<SkData>& shader1, const sk_sp<SkData>& shader2) {
+    return nullptr != shader1 && nullptr != shader2 && shader1->size() == shader2->size()
+            && 0 == memcmp(shader1->data(), shader2->data(), shader1->size());
 }
 
-bool checkShader(const sk_sp<SkData>& shader, std::vector<char>& program) {
-    sk_sp<SkData> shader2 = SkData::MakeWithCopy(program.data(), program.size());
-    return shader->size() == shader2->size()
-            && 0 == memcmp(shader->data(), shader2->data(), shader->size());
+inline bool
+checkShader(const sk_sp<SkData>& shader, const char* program) {
+    sk_sp<SkData> shader2 = SkData::MakeWithCString(program);
+    return checkShader(shader, shader2);
+}
+
+template <typename T>
+bool checkShader(const sk_sp<SkData>& shader, std::vector<T>& program) {
+    sk_sp<SkData> shader2 = SkData::MakeWithCopy(program.data(), program.size() * sizeof(T));
+    return checkShader(shader, shader2);
 }
 
 void setShader(sk_sp<SkData>& shader, const char* program) {
     shader = SkData::MakeWithCString(program);
 }
 
-void setShader(sk_sp<SkData>& shader, std::vector<char>& program) {
-    shader = SkData::MakeWithCopy(program.data(), program.size());
+template <typename T>
+void setShader(sk_sp<SkData>& shader, std::vector<T>& buffer) {
+    shader = SkData::MakeWithCopy(buffer.data(), buffer.size() * sizeof(T));
 }
 
+template <typename T>
+void genRandomData(std::vector<T>& buffer) {
+    for (auto& data : buffer) {
+        data = T(std::rand());
+    }
+}
 
 
 #define GrProgramDescTest(a) (*SkData::MakeWithCString(#a).get())
@@ -110,6 +130,7 @@
     //remove any test files from previous test run
     int deleteFile = remove(cacheFile1.c_str());
     ASSERT_TRUE(0 == deleteFile || ENOENT == errno);
+    std::srand(0);
 
     //read the cache from a file that does not exist
     ShaderCache::get().setFilename(cacheFile1.c_str());
@@ -158,10 +179,8 @@
 
     //write and read big data chunk (50K)
     size_t dataSize = 50*1024;
-    std::vector<char> dataBuffer(dataSize);
-    for (size_t i = 0; i < dataSize; i++) {
-        dataBuffer[0] = dataSize % 256;
-    }
+    std::vector<uint8_t> dataBuffer(dataSize);
+    genRandomData(dataBuffer);
     setShader(inVS, dataBuffer);
     ShaderCache::get().store(GrProgramDescTest(432), *inVS.get());
     ShaderCacheTestUtils::terminate(ShaderCache::get(), true);
@@ -173,4 +192,96 @@
     remove(cacheFile1.c_str());
 }
 
+TEST(ShaderCacheTest, testCacheValidation) {
+    if (!folderExist(getExternalStorageFolder())) {
+        //don't run the test if external storage folder is not available
+        return;
+    }
+    std::string cacheFile1 =  getExternalStorageFolder() + "/shaderCacheTest1";
+    std::string cacheFile2 =  getExternalStorageFolder() + "/shaderCacheTest2";
+
+    //remove any test files from previous test run
+    int deleteFile = remove(cacheFile1.c_str());
+    ASSERT_TRUE(0 == deleteFile || ENOENT == errno);
+    std::srand(0);
+
+    //generate identity and read the cache from a file that does not exist
+    ShaderCache::get().setFilename(cacheFile1.c_str());
+    ShaderCacheTestUtils::setSaveDelay(ShaderCache::get(), 0); //disable deferred save
+    std::vector<uint8_t> identity(1024);
+    genRandomData(identity);
+    ShaderCache::get().initShaderDiskCache(identity.data(), identity.size() *
+                                           sizeof(decltype(identity)::value_type));
+
+    // generate random content in cache and store to disk
+    constexpr size_t numBlob(10);
+    constexpr size_t keySize(1024);
+    constexpr size_t dataSize(50 * 1024);
+
+    std::vector< std::pair<sk_sp<SkData>, sk_sp<SkData>> > blobVec(numBlob);
+    for (auto& blob : blobVec) {
+        std::vector<uint8_t> keyBuffer(keySize);
+        std::vector<uint8_t> dataBuffer(dataSize);
+        genRandomData(keyBuffer);
+        genRandomData(dataBuffer);
+
+        sk_sp<SkData> key, data;
+        setShader(key, keyBuffer);
+        setShader(data, dataBuffer);
+
+        blob = std::make_pair(key, data);
+        ShaderCache::get().store(*key.get(), *data.get());
+    }
+    ShaderCacheTestUtils::terminate(ShaderCache::get(), true);
+
+    // change to a file that does not exist and verify validation fails
+    ShaderCache::get().setFilename(cacheFile2.c_str());
+    ShaderCache::get().initShaderDiskCache();
+    ASSERT_FALSE( ShaderCacheTestUtils::validateCache(ShaderCache::get(), identity) );
+    ShaderCacheTestUtils::terminate(ShaderCache::get(), false);
+
+    // restore the original file and verify validation succeeds
+    ShaderCache::get().setFilename(cacheFile1.c_str());
+    ShaderCache::get().initShaderDiskCache(identity.data(), identity.size() *
+                                           sizeof(decltype(identity)::value_type));
+    ASSERT_TRUE( ShaderCacheTestUtils::validateCache(ShaderCache::get(), identity) );
+    for (const auto& blob : blobVec) {
+        auto outVS = ShaderCache::get().load(*blob.first.get());
+        ASSERT_TRUE( checkShader(outVS, blob.second) );
+    }
+
+    // generate error identity and verify load fails
+    ShaderCache::get().initShaderDiskCache(identity.data(), -1);
+    for (const auto& blob : blobVec) {
+        ASSERT_EQ( ShaderCache::get().load(*blob.first.get()), sk_sp<SkData>() );
+    }
+    ShaderCache::get().initShaderDiskCache(nullptr, identity.size() *
+                                           sizeof(decltype(identity)::value_type));
+    for (const auto& blob : blobVec) {
+        ASSERT_EQ( ShaderCache::get().load(*blob.first.get()), sk_sp<SkData>() );
+    }
+
+    // verify the cache validation again after load fails
+    ShaderCache::get().initShaderDiskCache(identity.data(), identity.size() *
+                                           sizeof(decltype(identity)::value_type));
+    ASSERT_TRUE( ShaderCacheTestUtils::validateCache(ShaderCache::get(), identity) );
+    for (const auto& blob : blobVec) {
+        auto outVS = ShaderCache::get().load(*blob.first.get());
+        ASSERT_TRUE( checkShader(outVS, blob.second) );
+    }
+
+    // generate another identity and verify load fails
+    for (auto& data : identity) {
+        data += std::rand();
+    }
+    ShaderCache::get().initShaderDiskCache(identity.data(), identity.size() *
+                                           sizeof(decltype(identity)::value_type));
+    for (const auto& blob : blobVec) {
+        ASSERT_EQ( ShaderCache::get().load(*blob.first.get()), sk_sp<SkData>() );
+    }
+
+    ShaderCacheTestUtils::terminate(ShaderCache::get(), false);
+    remove(cacheFile1.c_str());
+}
+
 }  // namespace
diff --git a/libs/hwui/tests/unit/SkiaPipelineTests.cpp b/libs/hwui/tests/unit/SkiaPipelineTests.cpp
index a9124d9..5e5d134 100644
--- a/libs/hwui/tests/unit/SkiaPipelineTests.cpp
+++ b/libs/hwui/tests/unit/SkiaPipelineTests.cpp
@@ -50,7 +50,7 @@
     auto surface = SkSurface::MakeRasterN32Premul(1, 1);
     surface->getCanvas()->drawColor(SK_ColorBLUE, SkBlendMode::kSrcOver);
     ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
-    pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, false, contentDrawBounds,
+    pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds,
                           surface);
     ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorRED);
 }
@@ -83,7 +83,7 @@
     ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
 
     // drawFrame will crash if "SkiaPipeline::onPrepareTree" did not clean invalid VD pointer
-    pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, false, contentDrawBounds,
+    pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds,
                           surface);
     ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorRED);
 }
@@ -105,11 +105,11 @@
     auto surface = SkSurface::MakeRasterN32Premul(2, 2);
     surface->getCanvas()->drawColor(SK_ColorBLUE, SkBlendMode::kSrcOver);
     ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
-    pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, true, false, contentDrawBounds,
+    pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, true, contentDrawBounds,
                           surface);
     ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
     ASSERT_EQ(TestUtils::getColor(surface, 0, 1), SK_ColorGREEN);
-    pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, false, false, contentDrawBounds,
+    pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, false, contentDrawBounds,
                           surface);
     ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned int)SK_ColorTRANSPARENT);
     ASSERT_EQ(TestUtils::getColor(surface, 0, 1), SK_ColorGREEN);
@@ -129,7 +129,7 @@
     auto surface = SkSurface::MakeRasterN32Premul(2, 2);
     surface->getCanvas()->drawColor(SK_ColorBLUE, SkBlendMode::kSrcOver);
     ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
-    pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, true, false, contentDrawBounds,
+    pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, true, contentDrawBounds,
                           surface);
     ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
     ASSERT_EQ(TestUtils::getColor(surface, 1, 0), SK_ColorBLUE);
@@ -171,7 +171,7 @@
     lightGeometry.center = {0.0f, 0.0f, 0.0f};
     LightInfo lightInfo;
     auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
-    pipeline->renderLayers(lightGeometry, &layerUpdateQueue, opaque, false, lightInfo);
+    pipeline->renderLayers(lightGeometry, &layerUpdateQueue, opaque, lightInfo);
     ASSERT_EQ(TestUtils::getColor(surfaceLayer1, 0, 0), SK_ColorRED);
     ASSERT_EQ(TestUtils::getColor(surfaceLayer2, 0, 0), SK_ColorBLUE);
     ASSERT_EQ(TestUtils::getColor(surfaceLayer2, 0, 1), SK_ColorWHITE);
@@ -202,37 +202,37 @@
     ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
 
     // Single draw, should be white.
-    pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, false, contentDrawBounds,
+    pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds,
                           surface);
     ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorWHITE);
 
     // 1 Overdraw, should be blue blended onto white.
     renderNodes.push_back(whiteNode);
-    pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, false, contentDrawBounds,
+    pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds,
                           surface);
     ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned)0xffd0d0ff);
 
     // 2 Overdraw, should be green blended onto white
     renderNodes.push_back(whiteNode);
-    pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, false, contentDrawBounds,
+    pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds,
                           surface);
     ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned)0xffd0ffd0);
 
     // 3 Overdraw, should be pink blended onto white.
     renderNodes.push_back(whiteNode);
-    pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, false, contentDrawBounds,
+    pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds,
                           surface);
     ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned)0xffffc0c0);
 
     // 4 Overdraw, should be red blended onto white.
     renderNodes.push_back(whiteNode);
-    pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, false, contentDrawBounds,
+    pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds,
                           surface);
     ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned)0xffff8080);
 
     // 5 Overdraw, should be red blended onto white.
     renderNodes.push_back(whiteNode);
-    pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, false, contentDrawBounds,
+    pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds,
                           surface);
     ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned)0xffff8080);
 }
@@ -318,7 +318,7 @@
     SkRect dirty = SkRect::MakeWH(800, 600);
     auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
     sk_sp<DeferLayer<DeferTestCanvas>> surface(new DeferLayer<DeferTestCanvas>());
-    pipeline->renderFrame(layerUpdateQueue, dirty, nodes, true, false, contentDrawBounds, surface);
+    pipeline->renderFrame(layerUpdateQueue, dirty, nodes, true, contentDrawBounds, surface);
     EXPECT_EQ(4, surface->canvas()->mDrawCounter);
 }
 
@@ -348,7 +348,7 @@
     SkRect dirty = SkRect::MakeLTRB(10, 20, 30, 40);
     auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
     sk_sp<DeferLayer<ClippedTestCanvas>> surface(new DeferLayer<ClippedTestCanvas>());
-    pipeline->renderFrame(layerUpdateQueue, dirty, nodes, true, false,
+    pipeline->renderFrame(layerUpdateQueue, dirty, nodes, true,
                           SkRect::MakeWH(CANVAS_WIDTH, CANVAS_HEIGHT), surface);
     EXPECT_EQ(1, surface->canvas()->mDrawCounter);
 }
@@ -378,7 +378,7 @@
     SkRect dirty = SkRect::MakeLTRB(10, 10, 40, 40);
     auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
     sk_sp<DeferLayer<ClipReplaceTestCanvas>> surface(new DeferLayer<ClipReplaceTestCanvas>());
-    pipeline->renderFrame(layerUpdateQueue, dirty, nodes, true, false,
+    pipeline->renderFrame(layerUpdateQueue, dirty, nodes, true,
                           SkRect::MakeWH(CANVAS_WIDTH, CANVAS_HEIGHT), surface);
     EXPECT_EQ(1, surface->canvas()->mDrawCounter);
 }
diff --git a/libs/hwui/tests/unit/main.cpp b/libs/hwui/tests/unit/main.cpp
index 9e6d9a8..aecceb3 100644
--- a/libs/hwui/tests/unit/main.cpp
+++ b/libs/hwui/tests/unit/main.cpp
@@ -17,12 +17,13 @@
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
 
-#include "Caches.h"
 #include "debug/GlesDriver.h"
 #include "debug/NullGlesDriver.h"
 #include "hwui/Typeface.h"
 #include "Properties.h"
 #include "tests/common/LeakChecker.h"
+#include "thread/TaskProcessor.h"
+#include "thread/Task.h"
 #include "thread/TaskManager.h"
 
 #include <signal.h>
diff --git a/libs/hwui/utils/Color.cpp b/libs/hwui/utils/Color.cpp
index a3e7859..d35fe4f 100644
--- a/libs/hwui/utils/Color.cpp
+++ b/libs/hwui/utils/Color.cpp
@@ -57,6 +57,45 @@
     return false;
 }
 
+SkColorType PixelFormatToColorType(android_pixel_format pixelFormat) {
+    switch (pixelFormat) {
+        case HAL_PIXEL_FORMAT_RGBA_8888:
+        case HAL_PIXEL_FORMAT_BGRA_8888:
+            return SkColorType::kN32_SkColorType;
+        case HAL_PIXEL_FORMAT_RGBA_FP16:
+            return SkColorType::kRGBA_F16_SkColorType;
+        case HAL_PIXEL_FORMAT_RGBA_1010102:
+            return SkColorType::kRGBA_1010102_SkColorType;
+        default:
+            ALOGW("Unsupported pixel format: %d, return kN32 by default", pixelFormat);
+            return SkColorType::kN32_SkColorType;
+    }
+}
+
+SkColorSpace::Gamut DataSpaceToColorGamut(android_dataspace dataSpace) {
+    switch (dataSpace & HAL_DATASPACE_STANDARD_MASK) {
+        case HAL_DATASPACE_STANDARD_BT709:
+            return SkColorSpace::kSRGB_Gamut;
+        case HAL_DATASPACE_STANDARD_BT2020:
+            return SkColorSpace::kRec2020_Gamut;
+        case HAL_DATASPACE_STANDARD_DCI_P3:
+            return SkColorSpace::kDCIP3_D65_Gamut;
+        case HAL_DATASPACE_STANDARD_ADOBE_RGB:
+            return SkColorSpace::kAdobeRGB_Gamut;
+        case HAL_DATASPACE_STANDARD_UNSPECIFIED:
+        case HAL_DATASPACE_STANDARD_BT601_625:
+        case HAL_DATASPACE_STANDARD_BT601_625_UNADJUSTED:
+        case HAL_DATASPACE_STANDARD_BT601_525:
+        case HAL_DATASPACE_STANDARD_BT601_525_UNADJUSTED:
+        case HAL_DATASPACE_STANDARD_BT2020_CONSTANT_LUMINANCE:
+        case HAL_DATASPACE_STANDARD_BT470M:
+        case HAL_DATASPACE_STANDARD_FILM:
+        default:
+            ALOGW("Unsupported Gamut: %d, return SRGB gamut by default", dataSpace);
+            return SkColorSpace::kSRGB_Gamut;
+    }
+}
+
 sk_sp<SkColorSpace> DataSpaceToColorSpace(android_dataspace dataspace) {
 
     SkColorSpace::Gamut gamut;
diff --git a/libs/hwui/utils/Color.h b/libs/hwui/utils/Color.h
index 3c13a54..ff0e755 100644
--- a/libs/hwui/utils/Color.h
+++ b/libs/hwui/utils/Color.h
@@ -21,6 +21,7 @@
 
 #include <SkColor.h>
 #include <SkColorSpace.h>
+#include <SkImageInfo.h>
 
 namespace android {
 namespace uirenderer {
@@ -113,6 +114,10 @@
 // returns true for sRGB, gamma 2.2 and Display P3 for instance
 bool transferFunctionCloseToSRGB(const SkColorSpace* colorSpace);
 
+SkColorType PixelFormatToColorType(android_pixel_format pixelFormat);
+
+SkColorSpace::Gamut DataSpaceToColorGamut(android_dataspace dataSpace);
+
 sk_sp<SkColorSpace> DataSpaceToColorSpace(android_dataspace dataspace);
 
 struct Lab {
diff --git a/libs/hwui/utils/PaintUtils.h b/libs/hwui/utils/PaintUtils.h
index f8e8a0a..ebf2343 100644
--- a/libs/hwui/utils/PaintUtils.h
+++ b/libs/hwui/utils/PaintUtils.h
@@ -16,6 +16,7 @@
 #ifndef PAINT_UTILS_H
 #define PAINT_UTILS_H
 
+#include <GLES2/gl2.h>
 #include <utils/Blur.h>
 
 #include <SkColorFilter.h>
diff --git a/libs/hwui/utils/TestWindowContext.cpp b/libs/hwui/utils/TestWindowContext.cpp
deleted file mode 100644
index 8ac6e1f..0000000
--- a/libs/hwui/utils/TestWindowContext.cpp
+++ /dev/null
@@ -1,197 +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 "TestWindowContext.h"
-
-#include "AnimationContext.h"
-#include "IContextFactory.h"
-#include "RenderNode.h"
-#include "SkTypes.h"
-#include "gui/BufferQueue.h"
-#include "gui/CpuConsumer.h"
-#include "gui/IGraphicBufferConsumer.h"
-#include "gui/IGraphicBufferProducer.h"
-#include "gui/Surface.h"
-#include "hwui/Canvas.h"
-#include "renderthread/RenderProxy.h"
-
-#include <cutils/memory.h>
-
-namespace {
-
-/**
- * Helper class for setting up android::uirenderer::renderthread::RenderProxy.
- */
-class ContextFactory : public android::uirenderer::IContextFactory {
-public:
-    android::uirenderer::AnimationContext* createAnimationContext(
-            android::uirenderer::renderthread::TimeLord& clock) override {
-        return new android::uirenderer::AnimationContext(clock);
-    }
-};
-
-}  // anonymous namespace
-
-namespace android {
-namespace uirenderer {
-
-/**
-  Android strong pointers (android::sp) can't hold forward-declared classes,
-  so we have to use pointer-to-implementation here if we want to hide the
-  details from our non-framework users.
-*/
-
-class TestWindowContext::TestWindowData {
-public:
-    explicit TestWindowData(SkISize size) : mSize(size) {
-        android::BufferQueue::createBufferQueue(&mProducer, &mConsumer);
-        mCpuConsumer = new android::CpuConsumer(mConsumer, 1);
-        mCpuConsumer->setName(android::String8("TestWindowContext"));
-        mCpuConsumer->setDefaultBufferSize(mSize.width(), mSize.height());
-        mAndroidSurface = new android::Surface(mProducer);
-        native_window_set_buffers_dimensions(mAndroidSurface.get(), mSize.width(), mSize.height());
-        native_window_set_buffers_format(mAndroidSurface.get(), android::PIXEL_FORMAT_RGBA_8888);
-        native_window_set_usage(mAndroidSurface.get(), GRALLOC_USAGE_SW_READ_OFTEN |
-                                                               GRALLOC_USAGE_SW_WRITE_NEVER |
-                                                               GRALLOC_USAGE_HW_RENDER);
-        mRootNode.reset(new android::uirenderer::RenderNode());
-        mRootNode->incStrong(nullptr);
-        mRootNode->mutateStagingProperties().setLeftTopRightBottom(0, 0, mSize.width(),
-                                                                   mSize.height());
-        mRootNode->mutateStagingProperties().setClipToBounds(false);
-        mRootNode->setPropertyFieldsDirty(android::uirenderer::RenderNode::GENERIC);
-        ContextFactory factory;
-        mProxy.reset(new android::uirenderer::renderthread::RenderProxy(false, mRootNode.get(),
-                                                                        &factory));
-        mProxy->loadSystemProperties();
-        mProxy->initialize(mAndroidSurface.get());
-        float lightX = mSize.width() / 2.0f;
-        android::uirenderer::Vector3 lightVector{lightX, -200.0f, 800.0f};
-        mProxy->setup(800.0f, 255 * 0.075f, 255 * 0.15f);
-        mProxy->setLightCenter(lightVector);
-        mCanvas.reset(Canvas::create_recording_canvas(mSize.width(), mSize.height(), mRootNode.get()));
-    }
-
-    SkCanvas* prepareToDraw() {
-        // mCanvas->reset(mSize.width(), mSize.height());
-        mCanvas->clipRect(0, 0, mSize.width(), mSize.height(), SkClipOp::kReplace_deprecated);
-        return mCanvas->asSkCanvas();
-    }
-
-    void finishDrawing() {
-        mRootNode->setStagingDisplayList(mCanvas->finishRecording());
-        mProxy->syncAndDrawFrame();
-        // Surprisingly, calling mProxy->fence() here appears to make no difference to
-        // the timings we record.
-    }
-
-    void fence() { mProxy->fence(); }
-
-    bool capturePixels(SkBitmap* bmp) {
-        sk_sp<SkColorSpace> colorSpace = SkColorSpace::MakeSRGB();
-        SkImageInfo destinationConfig =
-                SkImageInfo::Make(mSize.width(), mSize.height(), kRGBA_8888_SkColorType,
-                                  kPremul_SkAlphaType, colorSpace);
-        bmp->allocPixels(destinationConfig);
-        android_memset32((uint32_t*)bmp->getPixels(), SK_ColorRED,
-                         mSize.width() * mSize.height() * 4);
-
-        android::CpuConsumer::LockedBuffer nativeBuffer;
-        android::status_t retval = mCpuConsumer->lockNextBuffer(&nativeBuffer);
-        if (retval == android::BAD_VALUE) {
-            SkDebugf("write_canvas_png() got no buffer; returning transparent");
-            // No buffer ready to read - commonly triggered by dm sending us
-            // a no-op source, or calling code that doesn't do anything on this
-            // backend.
-            bmp->eraseColor(SK_ColorTRANSPARENT);
-            return false;
-        } else if (retval) {
-            SkDebugf("Failed to lock buffer to read pixels: %d.", retval);
-            return false;
-        }
-
-        // Move the pixels into the destination SkBitmap
-
-        LOG_ALWAYS_FATAL_IF(nativeBuffer.format != android::PIXEL_FORMAT_RGBA_8888,
-                            "Native buffer not RGBA!");
-        SkImageInfo nativeConfig = SkImageInfo::Make(nativeBuffer.width, nativeBuffer.height,
-                                                     kRGBA_8888_SkColorType, kPremul_SkAlphaType);
-
-        // Android stride is in pixels, Skia stride is in bytes
-        SkBitmap nativeWrapper;
-        bool success = nativeWrapper.installPixels(nativeConfig, nativeBuffer.data,
-                                                   nativeBuffer.stride * 4);
-        if (!success) {
-            SkDebugf("Failed to wrap HWUI buffer in a SkBitmap");
-            return false;
-        }
-
-        LOG_ALWAYS_FATAL_IF(bmp->colorType() != kRGBA_8888_SkColorType,
-                            "Destination buffer not RGBA!");
-        success = nativeWrapper.readPixels(destinationConfig, bmp->getPixels(), bmp->rowBytes(), 0,
-                                           0);
-        if (!success) {
-            SkDebugf("Failed to extract pixels from HWUI buffer");
-            return false;
-        }
-
-        mCpuConsumer->unlockBuffer(nativeBuffer);
-
-        return true;
-    }
-
-private:
-    std::unique_ptr<android::uirenderer::RenderNode> mRootNode;
-    std::unique_ptr<android::uirenderer::renderthread::RenderProxy> mProxy;
-    std::unique_ptr<android::Canvas> mCanvas;
-    android::sp<android::IGraphicBufferProducer> mProducer;
-    android::sp<android::IGraphicBufferConsumer> mConsumer;
-    android::sp<android::CpuConsumer> mCpuConsumer;
-    android::sp<android::Surface> mAndroidSurface;
-    SkISize mSize;
-};
-
-TestWindowContext::TestWindowContext() : mData(nullptr) {}
-
-TestWindowContext::~TestWindowContext() {
-    delete mData;
-}
-
-void TestWindowContext::initialize(int width, int height) {
-    mData = new TestWindowData(SkISize::Make(width, height));
-}
-
-SkCanvas* TestWindowContext::prepareToDraw() {
-    return mData ? mData->prepareToDraw() : nullptr;
-}
-
-void TestWindowContext::finishDrawing() {
-    if (mData) {
-        mData->finishDrawing();
-    }
-}
-
-void TestWindowContext::fence() {
-    if (mData) {
-        mData->fence();
-    }
-}
-
-bool TestWindowContext::capturePixels(SkBitmap* bmp) {
-    return mData ? mData->capturePixels(bmp) : false;
-}
-
-}  // namespace uirenderer
-}  // namespace android
diff --git a/libs/hwui/utils/TestWindowContext.h b/libs/hwui/utils/TestWindowContext.h
deleted file mode 100644
index 17ad1e3..0000000
--- a/libs/hwui/utils/TestWindowContext.h
+++ /dev/null
@@ -1,64 +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 TESTWINDOWCONTEXT_H_
-#define TESTWINDOWCONTEXT_H_
-
-#include <cutils/compiler.h>
-
-class SkBitmap;
-class SkCanvas;
-
-namespace android {
-
-namespace uirenderer {
-
-/**
-  Wraps all libui/libgui classes and types that external tests depend on,
-  exposing only primitive Skia types.
-*/
-
-class ANDROID_API TestWindowContext {
-public:
-    TestWindowContext();
-    ~TestWindowContext();
-
-    /// We need to know the size of the window.
-    void initialize(int width, int height);
-
-    /// Returns a canvas to draw into; NULL if not yet initialize()d.
-    SkCanvas* prepareToDraw();
-
-    /// Flushes all drawing commands to HWUI; no-op if not yet initialize()d.
-    void finishDrawing();
-
-    /// Blocks until HWUI has processed all pending drawing commands;
-    /// no-op if not yet initialize()d.
-    void fence();
-
-    /// Returns false if not yet initialize()d.
-    bool capturePixels(SkBitmap* bmp);
-
-private:
-    /// Hidden implementation.
-    class TestWindowData;
-
-    TestWindowData* mData;
-};
-
-}  // namespace uirenderer
-}  // namespace android
-
-#endif  // TESTWINDOWCONTEXT_H_
diff --git a/libs/input/Android.bp b/libs/input/Android.bp
index 67682a0..c5a6ec5 100644
--- a/libs/input/Android.bp
+++ b/libs/input/Android.bp
@@ -36,9 +36,8 @@
 
     cflags: [
         "-Wall",
+        "-Wextra",
         "-Werror",
-        "-Wunused",
-        "-Wunreachable-code",
     ],
 
 }
diff --git a/libs/input/PointerController.h b/libs/input/PointerController.h
index 4794f3d..eb3469e 100644
--- a/libs/input/PointerController.h
+++ b/libs/input/PointerController.h
@@ -28,7 +28,6 @@
 #include <utils/BitSet.h>
 #include <utils/RefBase.h>
 #include <utils/Looper.h>
-#include <utils/String8.h>
 #include <gui/DisplayEventReceiver.h>
 
 namespace android {
diff --git a/libs/input/SpriteController.cpp b/libs/input/SpriteController.cpp
index 173cd50..eb2bc98 100644
--- a/libs/input/SpriteController.cpp
+++ b/libs/input/SpriteController.cpp
@@ -23,14 +23,10 @@
 #include <utils/String8.h>
 #include <gui/Surface.h>
 
-// ToDo: Fix code to be warning free
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wunused-parameter"
 #include <SkBitmap.h>
 #include <SkCanvas.h>
 #include <SkColor.h>
 #include <SkPaint.h>
-#pragma GCC diagnostic pop
 
 #include <android/native_window.h>
 
diff --git a/location/java/android/location/CountryDetector.java b/location/java/android/location/CountryDetector.java
index 119d1e0..ae13949 100644
--- a/location/java/android/location/CountryDetector.java
+++ b/location/java/android/location/CountryDetector.java
@@ -21,6 +21,7 @@
 import android.annotation.SystemService;
 import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
+import android.os.Build;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.RemoteException;
@@ -88,7 +89,7 @@
      *       create an instance of this class is using the factory
      *       Context.getSystemService.
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     public CountryDetector(ICountryDetector service) {
         mService = service;
         mListeners = new HashMap<CountryListener, ListenerTransport>();
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index b5d9431..6d10c2d 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -2378,4 +2378,17 @@
             throw new IllegalArgumentException("invalid geofence: " + fence);
         }
     }
+
+    /**
+     * @hide
+     */
+    @SystemApi
+    public String getNetworkProviderPackage() {
+        try {
+            return mService.getNetworkProviderPackage();
+        } catch (RemoteException e) {
+            e.rethrowFromSystemServer();
+            return null;
+        }
+    }
 }
diff --git a/media/java/android/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java
index e8bc622..f1325ce 100644
--- a/media/java/android/media/AudioAttributes.java
+++ b/media/java/android/media/AudioAttributes.java
@@ -20,6 +20,7 @@
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
 import android.annotation.UnsupportedAppUsage;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -375,11 +376,11 @@
 
     @UnsupportedAppUsage
     private int mUsage = USAGE_UNKNOWN;
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private int mContentType = CONTENT_TYPE_UNKNOWN;
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private int mSource = MediaRecorder.AudioSource.AUDIO_SOURCE_INVALID;
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private int mFlags = 0x0;
     private HashSet<String> mTags;
     @UnsupportedAppUsage
@@ -715,6 +716,7 @@
                     break;
                 case AudioSystem.STREAM_TTS:
                     mContentType = CONTENT_TYPE_SONIFICATION;
+                    mFlags |= FLAG_BEACON;
                     break;
                 case AudioSystem.STREAM_ACCESSIBILITY:
                     mContentType = CONTENT_TYPE_SPEECH;
@@ -1035,10 +1037,14 @@
             return fromGetVolumeControlStream ?
                     AudioSystem.STREAM_SYSTEM : AudioSystem.STREAM_SYSTEM_ENFORCED;
         }
-        if ((aa.getFlags() & FLAG_SCO) == FLAG_SCO) {
+        if ((aa.getAllFlags() & FLAG_SCO) == FLAG_SCO) {
             return fromGetVolumeControlStream ?
                     AudioSystem.STREAM_VOICE_CALL : AudioSystem.STREAM_BLUETOOTH_SCO;
         }
+        if ((aa.getAllFlags() & FLAG_BEACON) == FLAG_BEACON) {
+            return fromGetVolumeControlStream ?
+                    AudioSystem.STREAM_MUSIC : AudioSystem.STREAM_TTS;
+        }
 
         // usage to stream type mapping
         switch (aa.getUsage()) {
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index 39f3b31..e8fe9fe 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -882,6 +882,10 @@
     public static native int listAudioPatches(ArrayList<AudioPatch> patches, int[] generation);
     public static native int setAudioPortConfig(AudioPortConfig config);
 
+    public static native int startAudioSource(AudioPortConfig config,
+                                              AudioAttributes audioAttributes);
+    public static native int stopAudioSource(int handle);
+
     // declare this instance as having a dynamic policy callback handler
     private static native final void native_register_dynamic_policy_callback();
     // declare this instance as having a recording configuration update callback handler
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index aaf7dd7..62e58ca 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -1656,7 +1656,7 @@
     * @param timestamp a reference to a non-null AudioTimestamp instance allocated
     *        and owned by caller.
     * @return true if a timestamp is available, or false if no timestamp is available.
-    *         If a timestamp if available,
+    *         If a timestamp is available,
     *         the AudioTimestamp instance is filled in with a position in frame units, together
     *         with the estimated time when that frame was presented or is committed to
     *         be presented.
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index d45acdf..d1d605f 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -24,6 +24,7 @@
 import android.graphics.Rect;
 import android.graphics.SurfaceTexture;
 import android.media.MediaCodecInfo.CodecCapabilities;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
@@ -3580,7 +3581,7 @@
         native_init();
     }
 
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private long mNativeContext;
 
     /** @hide */
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index ef312d1..995ebb2 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -19,6 +19,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.UnsupportedAppUsage;
+import android.os.Build;
 import android.util.Log;
 import android.util.Pair;
 import android.util.Range;
@@ -1589,7 +1590,7 @@
         private VideoCapabilities() { }
 
         /** @hide */
-        @UnsupportedAppUsage
+        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
         public static VideoCapabilities create(
                 MediaFormat info, CodecCapabilities parent) {
             VideoCapabilities caps = new VideoCapabilities();
diff --git a/media/java/android/media/MediaPlayer2.java b/media/java/android/media/MediaPlayer2.java
index aa78b0d..89827bc 100644
--- a/media/java/android/media/MediaPlayer2.java
+++ b/media/java/android/media/MediaPlayer2.java
@@ -773,22 +773,6 @@
     }
 
     /**
-     * Invoke a generic method on the native player using opaque
-     * parcels for the request and reply. Both payloads' format is a
-     * convention between the java caller and the native player.
-     * Must be called after setDataSource to make sure a native player
-     * exists. On failure, a RuntimeException is thrown.
-     *
-     * @param request Parcel with the data for the extension. The
-     * caller must use {@link #newRequest()} to get one.
-     *
-     * @param reply Output parcel with the data returned by the
-     * native player.
-     * {@hide}
-     */
-    public void invoke(Parcel request, Parcel reply) { }
-
-    /**
      * Insert a task in the command queue to help the client to identify whether a batch
      * of commands has been finished. When this command is processed, a notification
      * {@code EventCallback.onCommandLabelReached} will be fired with the
diff --git a/media/java/android/media/MediaPlayer2Impl.java b/media/java/android/media/MediaPlayer2Impl.java
index c06b97b..6ae4d40 100644
--- a/media/java/android/media/MediaPlayer2Impl.java
+++ b/media/java/android/media/MediaPlayer2Impl.java
@@ -25,6 +25,10 @@
 import android.content.Context;
 import android.content.res.AssetFileDescriptor;
 import android.graphics.SurfaceTexture;
+import android.graphics.Rect;
+import android.media.MediaPlayer2Proto;
+import android.media.MediaPlayer2Proto.PlayerMessage;
+import android.media.MediaPlayer2Proto.Value;
 import android.media.SubtitleController.Anchor;
 import android.media.SubtitleTrack.RenderingWidget;
 import android.net.Uri;
@@ -49,6 +53,7 @@
 import android.view.SurfaceHolder;
 import android.widget.VideoView;
 
+import com.android.framework.protobuf.InvalidProtocolBufferException;
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.Preconditions;
 
@@ -72,6 +77,7 @@
 import java.util.Arrays;
 import java.util.BitSet;
 import java.util.HashMap;
+import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
@@ -555,28 +561,30 @@
     }
 
     /**
-     * Invoke a generic method on the native player using opaque
-     * parcels for the request and reply. Both payloads' format is a
+     * Invoke a generic method on the native player using opaque protocol
+     * buffer message for the request and reply. Both payloads' format is a
      * convention between the java caller and the native player.
-     * Must be called after setDataSource or setPlaylist to make sure a native player
-     * exists. On failure, a RuntimeException is thrown.
      *
-     * @param request Parcel with the data for the extension. The
+     * @param request PlayerMessage for the extension. The
      * caller must use {@link #newRequest()} to get one.
      *
-     * @param reply Output parcel with the data returned by the
+     * @return PlayerMessage with the data returned by the
      * native player.
-     * {@hide}
      */
-    @Override
-    public void invoke(Parcel request, Parcel reply) {
-        int retcode = native_invoke(request, reply);
-        reply.setDataPosition(0);
-        if (retcode != 0) {
-            throw new RuntimeException("failure code: " + retcode);
+    private PlayerMessage invoke(PlayerMessage msg) {
+        byte[] ret = _invoke(msg.toByteArray());
+        if (ret == null) {
+            return null;
+        }
+        try {
+            return PlayerMessage.parseFrom(ret);
+        } catch (InvalidProtocolBufferException e) {
+            return null;
         }
     }
 
+    private native byte[] _invoke(byte[] request);
+
     @Override
     public void notifyWhenCommandLabelReached(Object label) {
         addTask(new Task(CALL_COMPLETED_NOTIFY_WHEN_COMMAND_LABEL_REACHED, false) {
@@ -683,16 +691,12 @@
                     final String msg = "Scaling mode " + mode + " is not supported";
                     throw new IllegalArgumentException(msg);
                 }
-                Parcel request = Parcel.obtain();
-                Parcel reply = Parcel.obtain();
-                try {
-                    request.writeInt(INVOKE_ID_SET_VIDEO_SCALE_MODE);
-                    request.writeInt(mode);
-                    invoke(request, reply);
-                } finally {
-                    request.recycle();
-                    reply.recycle();
-                }
+                PlayerMessage request = PlayerMessage.newBuilder()
+                        .addValues(Value.newBuilder()
+                                .setInt32Value(INVOKE_ID_SET_VIDEO_SCALE_MODE))
+                        .addValues(Value.newBuilder().setInt32Value(mode))
+                        .build();
+                invoke(request);
             }
         });
     }
@@ -1799,14 +1803,6 @@
     private native void _setAuxEffectSendLevel(float level);
 
     /*
-     * @param request Parcel destinated to the media player.
-     * @param reply[out] Parcel that will contain the reply.
-     * @return The status code.
-     */
-    private native final int native_invoke(Parcel request, Parcel reply);
-
-
-    /*
      * @param update_only If true fetch only the set of metadata that have
      *                    changed since the last invocation of getMetadata.
      *                    The set is built using the unfiltered
@@ -1886,18 +1882,18 @@
         final int mTrackType;
         final MediaFormat mFormat;
 
-        TrackInfoImpl(Parcel in) {
-            mTrackType = in.readInt();
-            // TODO: parcel in the full MediaFormat; currently we are using createSubtitleFormat
+        TrackInfoImpl(Iterator<Value> in) {
+            mTrackType = in.next().getInt32Value();
+            // TODO: build the full MediaFormat; currently we are using createSubtitleFormat
             // even for audio/video tracks, meaning we only set the mime and language.
-            String mime = in.readString();
-            String language = in.readString();
+            String mime = in.next().getStringValue();
+            String language = in.next().getStringValue();
             mFormat = MediaFormat.createSubtitleFormat(mime, language);
 
             if (mTrackType == MEDIA_TRACK_TYPE_SUBTITLE) {
-                mFormat.setInteger(MediaFormat.KEY_IS_AUTOSELECT, in.readInt());
-                mFormat.setInteger(MediaFormat.KEY_IS_DEFAULT, in.readInt());
-                mFormat.setInteger(MediaFormat.KEY_IS_FORCED_SUBTITLE, in.readInt());
+                mFormat.setInteger(MediaFormat.KEY_IS_AUTOSELECT, in.next().getInt32Value());
+                mFormat.setInteger(MediaFormat.KEY_IS_DEFAULT, in.next().getInt32Value());
+                mFormat.setInteger(MediaFormat.KEY_IS_FORCED_SUBTITLE, in.next().getInt32Value());
             }
         }
 
@@ -1952,23 +1948,6 @@
             out.append("}");
             return out.toString();
         }
-
-        /**
-         * Used to read a TrackInfoImpl from a Parcel.
-         */
-        /* package private */ static final Parcelable.Creator<TrackInfoImpl> CREATOR
-                = new Parcelable.Creator<TrackInfoImpl>() {
-                    @Override
-                    public TrackInfoImpl createFromParcel(Parcel in) {
-                        return new TrackInfoImpl(in);
-                    }
-
-                    @Override
-                    public TrackInfoImpl[] newArray(int size) {
-                        return new TrackInfoImpl[size];
-                    }
-                };
-
     };
 
     // We would like domain specific classes with more informative names than the `first` and `second`
@@ -2010,17 +1989,23 @@
     }
 
     private TrackInfoImpl[] getInbandTrackInfoImpl() throws IllegalStateException {
-        Parcel request = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        try {
-            request.writeInt(INVOKE_ID_GET_TRACK_INFO);
-            invoke(request, reply);
-            TrackInfoImpl trackInfo[] = reply.createTypedArray(TrackInfoImpl.CREATOR);
-            return trackInfo;
-        } finally {
-            request.recycle();
-            reply.recycle();
+        PlayerMessage request = PlayerMessage.newBuilder()
+                .addValues(Value.newBuilder().setInt32Value(INVOKE_ID_GET_TRACK_INFO))
+                .build();
+        PlayerMessage response = invoke(request);
+        if (response == null) {
+            return null;
         }
+        Iterator<Value> in = response.getValuesList().iterator();
+        int size = in.next().getInt32Value();
+        if (size == 0) {
+            return null;
+        }
+        TrackInfoImpl trackInfo[] = new TrackInfoImpl[size];
+        for (int i = 0; i < size; ++i) {
+            trackInfo[i] = new TrackInfoImpl(in);
+        }
+        return trackInfo;
     }
 
     /*
@@ -2481,26 +2466,24 @@
             }
         }
 
-        Parcel request = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        try {
-            request.writeInt(INVOKE_ID_GET_SELECTED_TRACK);
-            request.writeInt(trackType);
-            invoke(request, reply);
-            int inbandTrackIndex = reply.readInt();
-            synchronized (mIndexTrackPairs) {
-                for (int i = 0; i < mIndexTrackPairs.size(); i++) {
-                    Pair<Integer, SubtitleTrack> p = mIndexTrackPairs.get(i);
-                    if (p.first != null && p.first == inbandTrackIndex) {
-                        return i;
-                    }
+        PlayerMessage request = PlayerMessage.newBuilder()
+                .addValues(Value.newBuilder().setInt32Value(INVOKE_ID_GET_SELECTED_TRACK))
+                .addValues(Value.newBuilder().setInt32Value(trackType))
+                .build();
+        PlayerMessage response = invoke(request);
+        if (response == null) {
+            return -1;
+        }
+        int inbandTrackIndex = response.getValues(0).getInt32Value();
+        synchronized (mIndexTrackPairs) {
+            for (int i = 0; i < mIndexTrackPairs.size(); i++) {
+                Pair<Integer, SubtitleTrack> p = mIndexTrackPairs.get(i);
+                if (p.first != null && p.first == inbandTrackIndex) {
+                    return i;
                 }
             }
-            return -1;
-        } finally {
-            request.recycle();
-            reply.recycle();
         }
+        return -1;
     }
 
     /**
@@ -2617,16 +2600,12 @@
 
     private void selectOrDeselectInbandTrack(int index, boolean select)
             throws IllegalStateException {
-        Parcel request = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        try {
-            request.writeInt(select? INVOKE_ID_SELECT_TRACK: INVOKE_ID_DESELECT_TRACK);
-            request.writeInt(index);
-            invoke(request, reply);
-        } finally {
-            request.recycle();
-            reply.recycle();
-        }
+        PlayerMessage request = PlayerMessage.newBuilder()
+                .addValues(Value.newBuilder().setInt32Value(
+                            select? INVOKE_ID_SELECT_TRACK: INVOKE_ID_DESELECT_TRACK))
+                .addValues(Value.newBuilder().setInt32Value(index))
+                .build();
+        invoke(request);
     }
 
     // Have to declare protected for finalize() since it is protected
@@ -2791,8 +2770,8 @@
             {
                 if (msg.obj == null) {
                     Log.w(TAG, "MEDIA_DRM_INFO msg.obj=NULL");
-                } else if (msg.obj instanceof Parcel) {
-                    // The parcel was parsed already in postEventFromNative
+                } else if (msg.obj instanceof byte[]) {
+                    // The PlayerMessage was parsed already in postEventFromNative
                     final DrmInfoImpl drmInfo;
 
                     synchronized (mDrmLock) {
@@ -2935,20 +2914,7 @@
 
             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_DATA_SOURCE_START:
-                        if (isCurrentSrcId) {
-                            prepareNextDataSource();
-                        }
-                        break;
-
                     case MEDIA_INFO_VIDEO_TRACK_LAGGING:
                         Log.i(TAG, "Info (" + msg.arg1 + "," + msg.arg2 + ")");
                         break;
@@ -2980,6 +2946,20 @@
                         }
                         break;
                 }
+
+                synchronized (mEventCbLock) {
+                    for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
+                        cb.first.execute(() -> cb.second.onInfo(
+                                mMediaPlayer, dsd, what, extra));
+                    }
+                }
+
+                if (msg.arg1 == MEDIA_INFO_DATA_SOURCE_START) {
+                    if (isCurrentSrcId) {
+                        prepareNextDataSource();
+                    }
+                }
+
                 // No real default action so far.
                 return;
             }
@@ -2996,10 +2976,15 @@
             case MEDIA_TIMED_TEXT:
             {
                 final TimedText text;
-                if (msg.obj instanceof Parcel) {
-                    Parcel parcel = (Parcel)msg.obj;
-                    text = new TimedText(parcel);
-                    parcel.recycle();
+                if (msg.obj instanceof byte[]) {
+                    PlayerMessage playerMsg;
+                    try {
+                        playerMsg = PlayerMessage.parseFrom((byte[]) msg.obj);
+                    } catch (InvalidProtocolBufferException e) {
+                        Log.w(TAG, "Failed to parse timed text.", e);
+                        return;
+                    }
+                    text = TimedTextUtil.parsePlayerMessage(playerMsg);
                 } else {
                     text = null;
                 }
@@ -3015,10 +3000,20 @@
 
             case MEDIA_SUBTITLE_DATA:
             {
-                if (msg.obj instanceof Parcel) {
-                    Parcel parcel = (Parcel) msg.obj;
-                    SubtitleData data = new SubtitleData(parcel);
-                    parcel.recycle();
+                if (msg.obj instanceof byte[]) {
+                    PlayerMessage playerMsg;
+                    try {
+                        playerMsg = PlayerMessage.parseFrom((byte[]) msg.obj);
+                    } catch (InvalidProtocolBufferException e) {
+                        Log.w(TAG, "Failed to parse subtitle data.", e);
+                        return;
+                    }
+                    Iterator<Value> in = playerMsg.getValuesList().iterator();
+                    SubtitleData data = new SubtitleData(
+                            in.next().getInt32Value(),  // trackIndex
+                            in.next().getInt64Value(),  // startTimeUs
+                            in.next().getInt64Value(),  // durationUs
+                            in.next().getBytesValue().toByteArray());  // data
                     synchronized (mEventCbLock) {
                         for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
                             cb.first.execute(() -> cb.second.onSubtitleData(
@@ -3032,10 +3027,18 @@
             case MEDIA_META_DATA:
             {
                 final TimedMetaData data;
-                if (msg.obj instanceof Parcel) {
-                    Parcel parcel = (Parcel) msg.obj;
-                    data = TimedMetaData.createTimedMetaDataFromParcel(parcel);
-                    parcel.recycle();
+                if (msg.obj instanceof byte[]) {
+                    PlayerMessage playerMsg;
+                    try {
+                        playerMsg = PlayerMessage.parseFrom((byte[]) msg.obj);
+                    } catch (InvalidProtocolBufferException e) {
+                        Log.w(TAG, "Failed to parse timed meta data.", e);
+                        return;
+                    }
+                    Iterator<Value> in = playerMsg.getValuesList().iterator();
+                    data = new TimedMetaData(
+                            in.next().getInt64Value(),  // timestampUs
+                            in.next().getBytesValue().toByteArray());  // metaData
                 } else {
                     data = null;
                 }
@@ -3083,7 +3086,7 @@
      * the cookie passed to native_setup().)
      */
     private static void postEventFromNative(Object mediaplayer2_ref, long srcId,
-                                            int what, int arg1, int arg2, Object obj)
+                                            int what, int arg1, int arg2, byte[] obj)
     {
         final MediaPlayer2Impl mp = (MediaPlayer2Impl)((WeakReference)mediaplayer2_ref).get();
         if (mp == null) {
@@ -3097,9 +3100,15 @@
             // notification looper so its handleMessage might process the event after prepare()
             // has returned.
             Log.v(TAG, "postEventFromNative MEDIA_DRM_INFO");
-            if (obj instanceof Parcel) {
-                Parcel parcel = (Parcel)obj;
-                DrmInfoImpl drmInfo = new DrmInfoImpl(parcel);
+            if (obj != null) {
+                PlayerMessage playerMsg;
+                try {
+                    playerMsg = PlayerMessage.parseFrom(obj);
+                } catch (InvalidProtocolBufferException e) {
+                    Log.w(TAG, "MEDIA_DRM_INFO failed to parse msg.obj " + obj);
+                    break;
+                }
+                DrmInfoImpl drmInfo = new DrmInfoImpl(playerMsg);
                 synchronized (mp.mDrmLock) {
                     mp.mDrmInfoImpl = drmInfo;
                 }
@@ -3766,22 +3775,21 @@
             supportedSchemes = SupportedSchemes;
         }
 
-        private DrmInfoImpl(Parcel parcel) {
-            Log.v(TAG, "DrmInfoImpl(" + parcel + ") size " + parcel.dataSize());
+        private DrmInfoImpl(PlayerMessage msg) {
+            Log.v(TAG, "DrmInfoImpl(" + msg + ")");
 
-            int psshsize = parcel.readInt();
-            byte[] pssh = new byte[psshsize];
-            parcel.readByteArray(pssh);
+            Iterator<Value> in = msg.getValuesList().iterator();
+            byte[] pssh = in.next().getBytesValue().toByteArray();
 
             Log.v(TAG, "DrmInfoImpl() PSSH: " + arrToHex(pssh));
-            mapPssh = parsePSSH(pssh, psshsize);
+            mapPssh = parsePSSH(pssh, pssh.length);
             Log.v(TAG, "DrmInfoImpl() PSSH: " + mapPssh);
 
-            int supportedDRMsCount = parcel.readInt();
+            int supportedDRMsCount = in.next().getInt32Value();
             supportedSchemes = new UUID[supportedDRMsCount];
             for (int i = 0; i < supportedDRMsCount; i++) {
                 byte[] uuid = new byte[16];
-                parcel.readByteArray(uuid);
+                in.next().getBytesValue().copyTo(uuid, uuid.length);
 
                 supportedSchemes[i] = bytesToUUID(uuid);
 
@@ -3789,7 +3797,7 @@
                       supportedSchemes[i]);
             }
 
-            Log.v(TAG, "DrmInfoImpl() Parcel psshsize: " + psshsize +
+            Log.v(TAG, "DrmInfoImpl() Parcel psshsize: " + pssh.length +
                   " supportedDRMsCount: " + supportedDRMsCount);
         }
 
@@ -4269,6 +4277,60 @@
                 mode == VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING);
     }
 
+    private static class TimedTextUtil {
+        // These keys must be in sync with the keys in TextDescription2.h
+        private static final int KEY_START_TIME                     = 7; // int
+        private static final int KEY_STRUCT_TEXT_POS               = 14; // TextPos
+        private static final int KEY_STRUCT_TEXT                   = 16; // Text
+        private static final int KEY_GLOBAL_SETTING               = 101;
+        private static final int KEY_LOCAL_SETTING                = 102;
+
+        private static TimedText parsePlayerMessage(PlayerMessage playerMsg) {
+            if (playerMsg.getValuesCount() == 0) {
+                return null;
+            }
+
+            String textChars = null;
+            Rect textBounds = null;
+            Iterator<Value> in = playerMsg.getValuesList().iterator();
+            int type = in.next().getInt32Value();
+            if (type == KEY_LOCAL_SETTING) {
+                type = in.next().getInt32Value();
+                if (type != KEY_START_TIME) {
+                    return null;
+                }
+                int startTimeMs = in.next().getInt32Value();
+
+                type = in.next().getInt32Value();
+                if (type != KEY_STRUCT_TEXT) {
+                    return null;
+                }
+
+                byte[] text = in.next().getBytesValue().toByteArray();
+                if (text == null || text.length == 0) {
+                    textChars = null;
+                } else {
+                    textChars = new String(text);
+                }
+
+            } else if (type != KEY_GLOBAL_SETTING) {
+                Log.w(TAG, "Invalid timed text key found: " + type);
+                return null;
+            }
+            if (in.hasNext()) {
+                type = in.next().getInt32Value();
+                if (type == KEY_STRUCT_TEXT_POS) {
+                    int top = in.next().getInt32Value();
+                    int left = in.next().getInt32Value();
+                    int bottom = in.next().getInt32Value();
+                    int right = in.next().getInt32Value();
+                    textBounds = new Rect(left, top, right, bottom);
+                }
+            }
+            return new TimedText(textChars, textBounds);
+        }
+    }
+
     /** @hide */
     static class TimeProvider implements MediaTimeProvider {
         private static final String TAG = "MTP";
diff --git a/media/java/android/media/MediaRouter.java b/media/java/android/media/MediaRouter.java
index 43bee85..ffeff4d 100644
--- a/media/java/android/media/MediaRouter.java
+++ b/media/java/android/media/MediaRouter.java
@@ -34,6 +34,7 @@
 import android.hardware.display.WifiDisplay;
 import android.hardware.display.WifiDisplayStatus;
 import android.media.session.MediaSession;
+import android.os.Build;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Process;
@@ -2064,7 +2065,7 @@
         }
 
         /** @hide */
-        @UnsupportedAppUsage
+        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
         public boolean isDefault() {
             return this == sStatic.mDefaultAudioVideo;
         }
diff --git a/media/java/android/media/MiniThumbFile.java b/media/java/android/media/MiniThumbFile.java
index 716e0cb..f704acd 100644
--- a/media/java/android/media/MiniThumbFile.java
+++ b/media/java/android/media/MiniThumbFile.java
@@ -18,9 +18,12 @@
 
 import android.annotation.UnsupportedAppUsage;
 import android.net.Uri;
+import android.os.Build;
 import android.os.Environment;
 import android.util.Log;
 
+import dalvik.system.VMRuntime;
+
 import java.io.File;
 import java.io.IOException;
 import java.io.RandomAccessFile;
@@ -42,7 +45,10 @@
  *
  * @hide This file is shared between MediaStore and MediaProvider and should remained internal use
  *       only.
+ * @deprecated thumbnails are now maintained in separate files, and this file
+ *             format is no longer used.
  */
+@Deprecated
 public class MiniThumbFile {
     private static final String TAG = "MiniThumbFile";
     private static final int MINI_THUMB_DATA_FILE_VERSION = 4;
@@ -69,6 +75,9 @@
     }
 
     public static synchronized MiniThumbFile instance(Uri uri) {
+        if (VMRuntime.getRuntime().getTargetSdkVersion() >= Build.VERSION_CODES.Q) {
+            throw new UnsupportedOperationException();
+        }
         String type = uri.getPathSegments().get(1);
         MiniThumbFile file = sThumbFiles.get(type);
         // Log.v(TAG, "get minithumbfile for type: "+type);
diff --git a/media/java/android/media/PlaybackParams.java b/media/java/android/media/PlaybackParams.java
index 6594dd7..3fe1a32 100644
--- a/media/java/android/media/PlaybackParams.java
+++ b/media/java/android/media/PlaybackParams.java
@@ -19,6 +19,7 @@
 import android.annotation.IntDef;
 import android.annotation.TestApi;
 import android.annotation.UnsupportedAppUsage;
+import android.os.Build;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -94,7 +95,7 @@
     private static final int SET_AUDIO_FALLBACK_MODE = 1 << 2;
     @UnsupportedAppUsage
     private static final int SET_AUDIO_STRETCH_MODE  = 1 << 3;
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private int mSet = 0;
 
     // params
@@ -104,7 +105,7 @@
     private int mAudioStretchMode = AUDIO_STRETCH_MODE_DEFAULT;
     @UnsupportedAppUsage
     private float mPitch = 1.0f;
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private float mSpeed = 1.0f;
 
     public PlaybackParams() {
diff --git a/media/java/android/media/SubtitleData.java b/media/java/android/media/SubtitleData.java
index 9797828..ba37b9b 100644
--- a/media/java/android/media/SubtitleData.java
+++ b/media/java/android/media/SubtitleData.java
@@ -79,6 +79,14 @@
         }
     }
 
+    /** @hide */
+    public SubtitleData(int trackIndex, long startTimeUs, long durationUs, byte[] data) {
+        mTrackIndex = trackIndex;
+        mStartTimeUs = startTimeUs;
+        mDurationUs = durationUs;
+        mData = data;
+    }
+
     /**
      * Returns the index of the MediaPlayer track which contains this subtitle data.
      * @return an index in the array returned by {@link MediaPlayer#getTrackInfo()}.
diff --git a/media/java/android/media/TimedMetaData.java b/media/java/android/media/TimedMetaData.java
index 03c8770..97e6bfa 100644
--- a/media/java/android/media/TimedMetaData.java
+++ b/media/java/android/media/TimedMetaData.java
@@ -48,6 +48,14 @@
     }
 
     /**
+     * @hide
+     */
+    public TimedMetaData(long timestampUs, byte[] metaData) {
+        mTimestampUs = timestampUs;
+        mMetaData = metaData;
+    }
+
+    /**
      * @return the timestamp associated with this metadata access unit in microseconds;
      * 0 denotes playback start.
      */
diff --git a/media/java/android/media/TimedText.java b/media/java/android/media/TimedText.java
index ebcea19..d8cdf9c 100644
--- a/media/java/android/media/TimedText.java
+++ b/media/java/android/media/TimedText.java
@@ -364,6 +364,16 @@
     }
 
     /**
+     * @param text the characters in the timed text.
+     * @param bounds the rectangle area or region for rendering the timed text.
+     * {@hide}
+     */
+    public TimedText(String text, Rect bounds) {
+        mTextChars = text;
+        mTextBounds = bounds;
+    }
+
+    /**
      * Get the characters in the timed text.
      *
      * @return the characters as a String object in the TimedText. Applications
diff --git a/media/java/android/media/audiofx/AudioEffect.java b/media/java/android/media/audiofx/AudioEffect.java
index 1a456f6..9746842 100644
--- a/media/java/android/media/audiofx/AudioEffect.java
+++ b/media/java/android/media/audiofx/AudioEffect.java
@@ -21,6 +21,7 @@
 import android.annotation.TestApi;
 import android.annotation.UnsupportedAppUsage;
 import android.app.ActivityThread;
+import android.os.Build;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
@@ -872,7 +873,7 @@
      * In case of failure, the returned value is negative and implementation specific.
      * @hide
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     public int command(int cmdCode, byte[] command, byte[] reply)
             throws IllegalStateException {
         checkState("command()");
diff --git a/media/jni/Android.bp b/media/jni/Android.bp
index de9a24b..7681cc3 100644
--- a/media/jni/Android.bp
+++ b/media/jni/Android.bp
@@ -91,6 +91,7 @@
         "android_media_Media2HTTPConnection.cpp",
         "android_media_Media2HTTPService.cpp",
         "android_media_Media2DataSource.cpp",
+        "android_media_MediaMetricsJNI.cpp",
         "android_media_MediaPlayer2.cpp",
         "android_media_SyncParams.cpp",
     ],
@@ -98,7 +99,6 @@
     shared_libs: [
         "android.hardware.cas@1.0",  // for CasManager. VNDK???
         "android.hardware.cas.native@1.0",  // CasManager. VNDK???
-        "libandroid_runtime",  // ???
         "libaudioclient",  // for use of AudioTrack, AudioSystem. to be removed
         "libbinder",
         "libgui",  // for VideoFrameScheduler
@@ -120,21 +120,19 @@
     header_libs: ["libhardware_headers"],
 
     static_libs: [
-        "libbacktrace",
         "libbase",
-        "libc_malloc_debug_backtrace",
         "libcrypto",
         "libcutils",
-        "libdexfile",
-        "liblzma",
         "libmedia_helper",
         "libmedia_player2_util",
         "libmediadrm",
         "libmediaextractor",
         "libmediametrics",
         "libmediaplayer2",
+        "libmediaplayer2-protos",
         "libmediautils",
-        "libnetd_client",
+        "libnetd_client",  // for setNetworkForUser
+        "libprotobuf-cpp-lite",
         "libstagefright_esds",
         "libstagefright_foundation",
         "libstagefright_httplive",
@@ -143,10 +141,7 @@
         "libstagefright_nuplayer2",
         "libstagefright_player2",
         "libstagefright_rtsp",
-        "libstagefright_timedtext",
-        "libunwindstack",
-        "libutilscallstack",
-        "libziparchive",
+        "libstagefright_timedtext2",
     ],
 
     group_static_libs: true,
diff --git a/media/jni/android_media_MediaMetricsJNI.cpp b/media/jni/android_media_MediaMetricsJNI.cpp
new file mode 100644
index 0000000..3ded8c2
--- /dev/null
+++ b/media/jni/android_media_MediaMetricsJNI.cpp
@@ -0,0 +1,90 @@
+/*
+ * 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.
+ */
+
+#include <jni.h>
+#include <nativehelper/JNIHelp.h>
+
+#include "android_media_MediaMetricsJNI.h"
+#include <media/MediaAnalyticsItem.h>
+
+
+// Copeid from core/jni/ (libandroid_runtime.so)
+namespace android {
+
+// place the attributes into a java PersistableBundle object
+jobject MediaMetricsJNI::writeMetricsToBundle(JNIEnv* env, MediaAnalyticsItem *item, jobject mybundle) {
+
+    jclass clazzBundle = env->FindClass("android/os/PersistableBundle");
+    if (clazzBundle==NULL) {
+        ALOGD("can't find android/os/PersistableBundle");
+        return NULL;
+    }
+    // sometimes the caller provides one for us to fill
+    if (mybundle == NULL) {
+        // create the bundle
+        jmethodID constructID = env->GetMethodID(clazzBundle, "<init>", "()V");
+        mybundle = env->NewObject(clazzBundle, constructID);
+        if (mybundle == NULL) {
+            return NULL;
+        }
+    }
+
+    // grab methods that we can invoke
+    jmethodID setIntID = env->GetMethodID(clazzBundle, "putInt", "(Ljava/lang/String;I)V");
+    jmethodID setLongID = env->GetMethodID(clazzBundle, "putLong", "(Ljava/lang/String;J)V");
+    jmethodID setDoubleID = env->GetMethodID(clazzBundle, "putDouble", "(Ljava/lang/String;D)V");
+    jmethodID setStringID = env->GetMethodID(clazzBundle, "putString", "(Ljava/lang/String;Ljava/lang/String;)V");
+
+    // env, class, method, {parms}
+    //env->CallVoidMethod(env, mybundle, setIntID, jstr, jint);
+
+    // iterate through my attributes
+    // -- get name, get type, get value
+    // -- insert appropriately into the bundle
+    for (size_t i = 0 ; i < item->mPropCount; i++ ) {
+            MediaAnalyticsItem::Prop *prop = &item->mProps[i];
+            // build the key parameter from prop->mName
+            jstring keyName = env->NewStringUTF(prop->mName);
+            // invoke the appropriate method to insert
+            switch (prop->mType) {
+                case MediaAnalyticsItem::kTypeInt32:
+                    env->CallVoidMethod(mybundle, setIntID,
+                                        keyName, (jint) prop->u.int32Value);
+                    break;
+                case MediaAnalyticsItem::kTypeInt64:
+                    env->CallVoidMethod(mybundle, setLongID,
+                                        keyName, (jlong) prop->u.int64Value);
+                    break;
+                case MediaAnalyticsItem::kTypeDouble:
+                    env->CallVoidMethod(mybundle, setDoubleID,
+                                        keyName, (jdouble) prop->u.doubleValue);
+                    break;
+                case MediaAnalyticsItem::kTypeCString:
+                    env->CallVoidMethod(mybundle, setStringID, keyName,
+                                        env->NewStringUTF(prop->u.CStringValue));
+                    break;
+                default:
+                        ALOGE("to_String bad item type: %d for %s",
+                              prop->mType, prop->mName);
+                        break;
+            }
+    }
+
+    return mybundle;
+}
+
+};  // namespace android
+
diff --git a/media/jni/android_media_MediaMetricsJNI.h b/media/jni/android_media_MediaMetricsJNI.h
new file mode 100644
index 0000000..fd621ea
--- /dev/null
+++ b/media/jni/android_media_MediaMetricsJNI.h
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+
+#ifndef _ANDROID_MEDIA_MEDIAMETRICSJNI_H_
+#define _ANDROID_MEDIA_MEDIAMETRICSJNI_H_
+
+#include <jni.h>
+#include <nativehelper/JNIHelp.h>
+#include <media/MediaAnalyticsItem.h>
+
+// Copeid from core/jni/ (libandroid_runtime.so)
+namespace android {
+
+class MediaMetricsJNI {
+public:
+    static jobject writeMetricsToBundle(JNIEnv* env, MediaAnalyticsItem *item, jobject mybundle);
+};
+
+};  // namespace android
+
+#endif //  _ANDROID_MEDIA_MEDIAMETRICSJNI_H_
diff --git a/media/jni/android_media_MediaPlayer2.cpp b/media/jni/android_media_MediaPlayer2.cpp
index 4265987..d4c84b5 100644
--- a/media/jni/android_media_MediaPlayer2.cpp
+++ b/media/jni/android_media_MediaPlayer2.cpp
@@ -56,6 +56,10 @@
 #include "android_util_Binder.h"
 #include <binder/Parcel.h>
 
+#include "mediaplayer2.pb.h"
+
+using android::media::MediaPlayer2Proto::PlayerMessage;
+
 // Modular DRM begin
 #define FIND_CLASS(var, className) \
 var = env->FindClass(className); \
@@ -157,7 +161,7 @@
     JNIMediaPlayer2Listener(JNIEnv* env, jobject thiz, jobject weak_thiz);
     ~JNIMediaPlayer2Listener();
     virtual void notify(int64_t srcId, int msg, int ext1, int ext2,
-                        const Parcel *obj = NULL) override;
+                        const PlayerMessage *obj = NULL) override;
 private:
     JNIMediaPlayer2Listener();
     jclass      mClass;     // Reference to MediaPlayer2 class
@@ -190,18 +194,21 @@
     env->DeleteGlobalRef(mClass);
 }
 
-void JNIMediaPlayer2Listener::notify(int64_t srcId, int msg, int ext1, int ext2, const Parcel *obj)
+void JNIMediaPlayer2Listener::notify(int64_t srcId, int msg, int ext1, int ext2,
+        const PlayerMessage* obj)
 {
     JNIEnv *env = JavaVMHelper::getJNIEnv();
-    if (obj && obj->dataSize() > 0) {
-        jobject jParcel = createJavaParcelObject(env);
-        if (jParcel != NULL) {
-            Parcel* nativeParcel = parcelForJavaObject(env, jParcel);
-            nativeParcel->setData(obj->data(), obj->dataSize());
-            env->CallStaticVoidMethod(mClass, fields.post_event, mObject,
-                    srcId, msg, ext1, ext2, jParcel);
-            env->DeleteLocalRef(jParcel);
-        }
+    if (obj != NULL) {
+        int size = obj->ByteSize();
+        jbyte* temp = new jbyte[size];
+        obj->SerializeToArray(temp, size);
+
+        // return the response as a byte array.
+        jbyteArray out = env->NewByteArray(size);
+        env->SetByteArrayRegion(out, 0, size, temp);
+        env->CallStaticVoidMethod(mClass, fields.post_event, mObject,
+                srcId, msg, ext1, ext2, out);
+        delete[] temp;
     } else {
         env->CallStaticVoidMethod(mClass, fields.post_event, mObject,
                 srcId, msg, ext1, ext2, NULL);
@@ -902,7 +909,7 @@
 }
 
 static jboolean
-android_media_MediaPlayer2_setParameter(JNIEnv *env, jobject thiz, jint key, jobject java_request)
+android_media_MediaPlayer2_setParameter(JNIEnv *env, jobject thiz, jint key, jobject)
 {
     ALOGV("setParameter: key %d", key);
     sp<MediaPlayer2> mp = getMediaPlayer(env, thiz);
@@ -911,6 +918,11 @@
         return false;
     }
 
+    return false;
+    // TODO: set/getParameter is temporarily disabled to remove android_runtime.so dependency.
+    //       Once JAudioTrack migration is done, the AudioAttribute jobject
+    //       should be directly passed to AudioTrack without native parcel conversion.
+    /*
     Parcel *request = parcelForJavaObject(env, java_request);
     status_t err = mp->setParameter(key, *request);
     if (err == OK) {
@@ -918,6 +930,7 @@
     } else {
         return false;
     }
+    */
 }
 
 static jobject
@@ -930,6 +943,11 @@
         return NULL;
     }
 
+    return NULL;
+    // TODO: set/getParameter is temporarily disabled to remove android_runtime.so dependency.
+    //       Once JAudioTrack migration is done, the AudioAttribute jobject
+    //       should be directly passed to AudioTrack without native parcel conversion.
+    /*
     jobject jParcel = createJavaParcelObject(env);
     if (jParcel != NULL) {
         Parcel* nativeParcel = parcelForJavaObject(env, jParcel);
@@ -940,6 +958,7 @@
         }
     }
     return jParcel;
+    */
 }
 
 static void
@@ -978,75 +997,39 @@
     process_media_player_call( env, thiz, mp->setVolume((float) leftVolume, (float) rightVolume), NULL, NULL );
 }
 
-// Sends the request and reply parcels to the media player via the
-// binder interface.
-static jint
-android_media_MediaPlayer2_invoke(JNIEnv *env, jobject thiz,
-                                 jobject java_request, jobject java_reply)
-{
+static jbyteArray
+android_media_MediaPlayer2_invoke(JNIEnv *env, jobject thiz, jbyteArray requestData) {
     sp<MediaPlayer2> media_player = getMediaPlayer(env, thiz);
-    if (media_player == NULL ) {
+    if (media_player == NULL) {
         jniThrowException(env, "java/lang/IllegalStateException", NULL);
-        return UNKNOWN_ERROR;
+        return NULL;
     }
 
-    Parcel *request = parcelForJavaObject(env, java_request);
-    Parcel *reply = parcelForJavaObject(env, java_reply);
+    // Get the byte[] pointer and data length.
+    jbyte* pData = env->GetByteArrayElements(requestData, NULL);
+    jsize pDataLen = env->GetArrayLength(requestData);
 
-    request->setDataPosition(0);
+    // Deserialize from the byte stream.
+    PlayerMessage request;
+    PlayerMessage response;
+    request.ParseFromArray(pData, pDataLen);
 
-    // Don't use process_media_player_call which use the async loop to
-    // report errors, instead returns the status.
-    return (jint) media_player->invoke(*request, reply);
-}
-
-// Sends the new filter to the client.
-static jint
-android_media_MediaPlayer2_setMetadataFilter(JNIEnv *env, jobject thiz, jobject request)
-{
-    sp<MediaPlayer2> media_player = getMediaPlayer(env, thiz);
-    if (media_player == NULL ) {
-        jniThrowException(env, "java/lang/IllegalStateException", NULL);
-        return UNKNOWN_ERROR;
+    process_media_player_call( env, thiz, media_player->invoke(request, &response),
+            "java.lang.RuntimeException", NULL );
+    if (env->ExceptionCheck()) {
+        return NULL;
     }
 
-    Parcel *filter = parcelForJavaObject(env, request);
+    int size = response.ByteSize();
+    jbyte* temp = new jbyte[size];
+    response.SerializeToArray(temp, size);
 
-    if (filter == NULL ) {
-        jniThrowException(env, "java/lang/RuntimeException", "Filter is null");
-        return UNKNOWN_ERROR;
-    }
+    // return the response as a byte array.
+    jbyteArray out = env->NewByteArray(size);
+    env->SetByteArrayRegion(out, 0, size, temp);
+    delete[] temp;
 
-    return (jint) media_player->setMetadataFilter(*filter);
-}
-
-static jboolean
-android_media_MediaPlayer2_getMetadata(JNIEnv *env, jobject thiz, jboolean update_only,
-                                      jboolean apply_filter, jobject reply)
-{
-    sp<MediaPlayer2> media_player = getMediaPlayer(env, thiz);
-    if (media_player == NULL ) {
-        jniThrowException(env, "java/lang/IllegalStateException", NULL);
-        return JNI_FALSE;
-    }
-
-    Parcel *metadata = parcelForJavaObject(env, reply);
-
-    if (metadata == NULL ) {
-        jniThrowException(env, "java/lang/RuntimeException", "Reply parcel is null");
-        return JNI_FALSE;
-    }
-
-    metadata->freeData();
-    // On return metadata is positioned at the beginning of the
-    // metadata. Note however that the parcel actually starts with the
-    // return code so you should not rewind the parcel using
-    // setDataPosition(0).
-    if (media_player->getMetadata(update_only, apply_filter, metadata) == OK) {
-        return JNI_TRUE;
-    } else {
-        return JNI_FALSE;
-    }
+    return out;
 }
 
 // This function gets some field IDs, which in turn causes class initialization.
@@ -1068,7 +1051,7 @@
     }
 
     fields.post_event = env->GetStaticMethodID(clazz, "postEventFromNative",
-                                               "(Ljava/lang/Object;JIIILjava/lang/Object;)V");
+                                               "(Ljava/lang/Object;JIII[B)V");
     if (fields.post_event == NULL) {
         return;
     }
@@ -1512,9 +1495,7 @@
     {"setLooping",          "(Z)V",                             (void *)android_media_MediaPlayer2_setLooping},
     {"isLooping",           "()Z",                              (void *)android_media_MediaPlayer2_isLooping},
     {"_setVolume",          "(FF)V",                            (void *)android_media_MediaPlayer2_setVolume},
-    {"native_invoke",       "(Landroid/os/Parcel;Landroid/os/Parcel;)I",(void *)android_media_MediaPlayer2_invoke},
-    {"native_setMetadataFilter", "(Landroid/os/Parcel;)I",      (void *)android_media_MediaPlayer2_setMetadataFilter},
-    {"native_getMetadata", "(ZZLandroid/os/Parcel;)Z",          (void *)android_media_MediaPlayer2_getMetadata},
+    {"_invoke",             "([B)[B",                           (void *)android_media_MediaPlayer2_invoke},
     {"native_init",         "()V",                              (void *)android_media_MediaPlayer2_native_init},
     {"native_setup",        "(Ljava/lang/Object;)V",            (void *)android_media_MediaPlayer2_native_setup},
     {"native_finalize",     "()V",                              (void *)android_media_MediaPlayer2_native_finalize},
diff --git a/media/proto/Android.bp b/media/proto/Android.bp
new file mode 100644
index 0000000..50d44c3
--- /dev/null
+++ b/media/proto/Android.bp
@@ -0,0 +1,20 @@
+java_library_static {
+    name: "mediaplayer2-protos",
+    host_supported: true,
+    proto: {
+        type: "lite",
+    },
+    srcs: ["mediaplayer2.proto"],
+    no_framework_libs: true,
+    jarjar_rules: "jarjar-rules.txt",
+}
+
+cc_library_static {
+    name: "libmediaplayer2-protos",
+    host_supported: true,
+    proto: {
+        export_proto_headers: true,
+        type: "lite",
+    },
+    srcs: ["mediaplayer2.proto"],
+}
diff --git a/media/proto/jarjar-rules.txt b/media/proto/jarjar-rules.txt
new file mode 100644
index 0000000..7be6e73
--- /dev/null
+++ b/media/proto/jarjar-rules.txt
@@ -0,0 +1,2 @@
+rule com.google.protobuf.** com.android.framework.protobuf.@1
+
diff --git a/media/proto/mediaplayer2.proto b/media/proto/mediaplayer2.proto
new file mode 100644
index 0000000..6287d6c
--- /dev/null
+++ b/media/proto/mediaplayer2.proto
@@ -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.
+ */
+
+syntax = "proto2";
+
+option optimize_for = LITE_RUNTIME;
+
+// C++ namespace: android::media:MediaPlayer2Proto:
+package android.media.MediaPlayer2Proto;
+
+option java_package = "android.media";
+option java_outer_classname = "MediaPlayer2Proto";
+
+message Value {
+    // The kind of value.
+    oneof kind {
+        // Represents a boolean value.
+        bool bool_value = 1;
+        // Represents an int32 value.
+        int32 int32_value = 2;
+        // Represents an uint32 value.
+        uint32 uint32_value = 3;
+        // Represents an int64 value.
+        int64 int64_value = 4;
+        // Represents an uint64 value.
+        uint64 uint64_value = 5;
+        // Represents a float value.
+        double float_value = 6;
+        // Represents a double value.
+        double double_value = 7;
+        // Represents a string value.
+        string string_value = 8;
+        // Represents a bytes value.
+        bytes bytes_value = 9;
+    }
+}
+
+message PlayerMessage {
+    repeated Value values = 1;
+}
diff --git a/native/android/Android.bp b/native/android/Android.bp
index 4fb5e74..24d003b 100644
--- a/native/android/Android.bp
+++ b/native/android/Android.bp
@@ -49,6 +49,7 @@
         "sharedmem.cpp",
         "storage_manager.cpp",
         "surface_texture.cpp",
+        "system_fonts.cpp",
         "trace.cpp",
     ],
 
@@ -64,6 +65,8 @@
         "libsensor",
         "libandroid_runtime",
         "libnetd_client",
+        "libhwui",
+        "libxml2",
     ],
 
     static_libs: [
diff --git a/native/android/libandroid.map.txt b/native/android/libandroid.map.txt
index ac5ded6..9f48bc9 100644
--- a/native/android/libandroid.map.txt
+++ b/native/android/libandroid.map.txt
@@ -212,6 +212,18 @@
     ASurfaceTexture_getTransformMatrix; # introduced=28
     ASurfaceTexture_release; # introduced=28
     ASurfaceTexture_updateTexImage; # introduced=28
+    ASystemFontIterator_open; # introduced=29
+    ASystemFontIterator_close; # introduced=29
+    ASystemFontIterator_next; # introduced=29
+    ASystemFont_close; # introduced=29
+    ASystemFont_getFontFilePath; # introduced=29
+    ASystemFont_getWeight; # introduced=29
+    ASystemFont_isItalic; # introduced=29
+    ASystemFont_getLocale; # introduced=29
+    ASystemFont_getCollectionIndex; # introduced=29
+    ASystemFont_getAxisCount; # introduced=29
+    ASystemFont_getAxisTag; # introduced=29
+    ASystemFont_getAxisValue; # introduced=29
     ATrace_beginSection; # introduced=23
     ATrace_endSection; # introduced=23
     ATrace_isEnabled; # introduced=23
diff --git a/native/android/surface_texture.cpp b/native/android/surface_texture.cpp
index b266881..ced279277 100644
--- a/native/android/surface_texture.cpp
+++ b/native/android/surface_texture.cpp
@@ -21,15 +21,16 @@
 
 #include <utils/Log.h>
 
-#include <gui/GLConsumer.h>
 #include <gui/Surface.h>
 
 #include <android_runtime/android_graphics_SurfaceTexture.h>
 
+#include "surfacetexture/SurfaceTexture.h"
+
 using namespace android;
 
 struct ASurfaceTexture {
-    sp<GLConsumer> consumer;
+    sp<SurfaceTexture> consumer;
     sp<IGraphicBufferProducer> producer;
 };
 
diff --git a/native/android/system_fonts.cpp b/native/android/system_fonts.cpp
new file mode 100644
index 0000000..b95adad
--- /dev/null
+++ b/native/android/system_fonts.cpp
@@ -0,0 +1,277 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <android/system_fonts.h>
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <libxml/tree.h>
+#include <log/log.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+struct XmlCharDeleter {
+    void operator()(xmlChar* b) { xmlFree(b); }
+};
+
+struct XmlDocDeleter {
+    void operator()(xmlDoc* d) { xmlFreeDoc(d); }
+};
+
+using XmlCharUniquePtr = std::unique_ptr<xmlChar, XmlCharDeleter>;
+using XmlDocUniquePtr = std::unique_ptr<xmlDoc, XmlDocDeleter>;
+
+struct ASystemFontIterator {
+    XmlDocUniquePtr mXmlDoc;
+    xmlNode* mFontNode;
+};
+
+struct ASystemFont {
+    std::string mFilePath;
+    std::unique_ptr<std::string> mLocale;
+    uint16_t mWeight;
+    bool mItalic;
+    uint32_t mCollectionIndex;
+    std::vector<std::pair<uint32_t, float>> mAxes;
+};
+
+namespace {
+
+std::string xmlTrim(const std::string& in) {
+    if (in.empty()) {
+        return in;
+    }
+    const char XML_SPACES[] = "\u0020\u000D\u000A\u0009";
+    const size_t start = in.find_first_not_of(XML_SPACES);  // inclusive
+    if (start == std::string::npos) {
+        return "";
+    }
+    const size_t end = in.find_last_not_of(XML_SPACES);     // inclusive
+    if (end == std::string::npos) {
+        return "";
+    }
+    return in.substr(start, end - start + 1 /* +1 since end is inclusive */);
+}
+
+const xmlChar* FAMILY_TAG = BAD_CAST("family");
+const xmlChar* FONT_TAG = BAD_CAST("font");
+
+xmlNode* firstElement(xmlNode* node, const xmlChar* tag) {
+    for (xmlNode* child = node->children; child; child = child->next) {
+        if (xmlStrEqual(child->name, tag)) {
+            return child;
+        }
+    }
+    return nullptr;
+}
+
+xmlNode* nextSibling(xmlNode* node, const xmlChar* tag) {
+    while ((node = node->next) != nullptr) {
+        if (xmlStrEqual(node->name, tag)) {
+            return node;
+        }
+    }
+    return nullptr;
+}
+
+void copyFont(ASystemFontIterator* ite, ASystemFont* out) {
+    const xmlChar* LOCALE_ATTR_NAME = BAD_CAST("lang");
+    XmlCharUniquePtr filePathStr(
+            xmlNodeListGetString(ite->mXmlDoc.get(), ite->mFontNode->xmlChildrenNode, 1));
+    out->mFilePath = "/system/fonts/" + xmlTrim(
+            std::string(filePathStr.get(), filePathStr.get() + xmlStrlen(filePathStr.get())));
+
+    const xmlChar* WEIGHT_ATTR_NAME = BAD_CAST("weight");
+    XmlCharUniquePtr weightStr(xmlGetProp(ite->mFontNode, WEIGHT_ATTR_NAME));
+    out->mWeight = weightStr ?
+            strtol(reinterpret_cast<const char*>(weightStr.get()), nullptr, 10) : 400;
+
+    const xmlChar* STYLE_ATTR_NAME = BAD_CAST("style");
+    const xmlChar* ITALIC_ATTR_VALUE = BAD_CAST("italic");
+    XmlCharUniquePtr styleStr(xmlGetProp(ite->mFontNode, STYLE_ATTR_NAME));
+    out->mItalic = styleStr ? xmlStrEqual(styleStr.get(), ITALIC_ATTR_VALUE) : false;
+
+    const xmlChar* INDEX_ATTR_NAME = BAD_CAST("index");
+    XmlCharUniquePtr indexStr(xmlGetProp(ite->mFontNode, INDEX_ATTR_NAME));
+    out->mCollectionIndex =  indexStr ?
+            strtol(reinterpret_cast<const char*>(indexStr.get()), nullptr, 10) : 0;
+
+    XmlCharUniquePtr localeStr(xmlGetProp(ite->mXmlDoc->parent, LOCALE_ATTR_NAME));
+    out->mLocale.reset(
+            localeStr ? new std::string(reinterpret_cast<const char*>(localeStr.get())) : nullptr);
+
+    const xmlChar* TAG_ATTR_NAME = BAD_CAST("tag");
+    const xmlChar* STYLEVALUE_ATTR_NAME = BAD_CAST("stylevalue");
+    const xmlChar* AXIS_TAG = BAD_CAST("axis");
+    out->mAxes.clear();
+    for (xmlNode* axis = firstElement(ite->mFontNode, AXIS_TAG); axis;
+            axis = nextSibling(axis, AXIS_TAG)) {
+        XmlCharUniquePtr tagStr(xmlGetProp(axis, TAG_ATTR_NAME));
+        if (!tagStr || xmlStrlen(tagStr.get()) != 4) {
+            continue;  // Tag value must be 4 char string
+        }
+
+        XmlCharUniquePtr styleValueStr(xmlGetProp(axis, STYLEVALUE_ATTR_NAME));
+        if (!styleValueStr) {
+            continue;
+        }
+
+        uint32_t tag =
+            static_cast<uint32_t>(tagStr.get()[0] << 24) |
+            static_cast<uint32_t>(tagStr.get()[1] << 16) |
+            static_cast<uint32_t>(tagStr.get()[2] << 8) |
+            static_cast<uint32_t>(tagStr.get()[3]);
+        float styleValue = strtod(reinterpret_cast<const char*>(styleValueStr.get()), nullptr);
+        out->mAxes.push_back(std::make_pair(tag, styleValue));
+    }
+}
+
+bool isFontFileAvailable(const std::string& filePath) {
+    std::string fullPath = filePath;
+    struct stat st = {};
+    if (stat(fullPath.c_str(), &st) != 0) {
+        return false;
+    }
+    return S_ISREG(st.st_mode);
+}
+
+xmlNode* findFirstFontNode(xmlDoc* doc) {
+    xmlNode* familySet = xmlDocGetRootElement(doc);
+    if (familySet == nullptr) {
+        return nullptr;
+    }
+    xmlNode* family = firstElement(familySet, FAMILY_TAG);
+    if (family == nullptr) {
+        return nullptr;
+    }
+
+    xmlNode* font = firstElement(family, FONT_TAG);
+    while (font == nullptr) {
+        family = nextSibling(family, FAMILY_TAG);
+        if (family == nullptr) {
+            return nullptr;
+        }
+        font = firstElement(family, FONT_TAG);
+    }
+    return font;
+}
+
+}  // namespace
+
+ASystemFontIterator* ASystemFontIterator_open() {
+    std::unique_ptr<ASystemFontIterator> ite(new ASystemFontIterator());
+    ite->mXmlDoc.reset(xmlReadFile("/system/etc/fonts.xml", nullptr, 0));
+    return ite.release();
+}
+
+void ASystemFontIterator_close(ASystemFontIterator* ite) {
+    delete ite;
+}
+
+ASystemFont* ASystemFontIterator_next(ASystemFontIterator* ite) {
+    LOG_ALWAYS_FATAL_IF(ite == nullptr, "nullptr has passed as iterator argument");
+    if (ite->mFontNode == nullptr) {
+        if (ite->mXmlDoc == nullptr) {
+            return nullptr;  // Already at the end.
+        } else {
+            // First time to query font.
+            ite->mFontNode = findFirstFontNode(ite->mXmlDoc.get());
+            if (ite->mFontNode == nullptr) {
+                ite->mXmlDoc.reset();
+                return nullptr;  // No font node found.
+            }
+            std::unique_ptr<ASystemFont> font = std::make_unique<ASystemFont>();
+            copyFont(ite, font.get());
+            return font.release();
+        }
+    } else {
+        xmlNode* nextNode = nextSibling(ite->mFontNode, FONT_TAG);
+        while (nextNode == nullptr) {
+            xmlNode* family = nextSibling(ite->mFontNode->parent, FAMILY_TAG);
+            if (family == nullptr) {
+                break;
+            }
+            nextNode = firstElement(family, FONT_TAG);
+        }
+        ite->mFontNode = nextNode;
+        if (nextNode == nullptr) {
+            ite->mXmlDoc.reset();
+            return nullptr;
+        }
+
+        std::unique_ptr<ASystemFont> font = std::make_unique<ASystemFont>();
+        copyFont(ite, font.get());
+        if (!isFontFileAvailable(font->mFilePath)) {
+            // fonts.xml intentionally contains missing font configuration. Skip it.
+            return ASystemFontIterator_next(ite);
+        }
+        return font.release();
+    }
+}
+
+void ASystemFont_close(ASystemFont* font) {
+    delete font;
+}
+
+const char* ASystemFont_getFontFilePath(const ASystemFont* font) {
+    LOG_ALWAYS_FATAL_IF(font == nullptr, "nullptr has passed as font argument");
+    return font->mFilePath.c_str();
+}
+
+uint16_t ASystemFont_getWeight(const ASystemFont* font) {
+    LOG_ALWAYS_FATAL_IF(font == nullptr, "nullptr has passed as font argument");
+    return font->mWeight;
+}
+
+bool ASystemFont_isItalic(const ASystemFont* font) {
+    LOG_ALWAYS_FATAL_IF(font == nullptr, "nullptr has passed as font argument");
+    return font->mItalic;
+}
+
+const char* ASystemFont_getLocale(const ASystemFont* font) {
+    LOG_ALWAYS_FATAL_IF(font == nullptr, "nullptr has passed to font argument");
+    return font->mLocale ? nullptr : font->mLocale->c_str();
+}
+
+size_t ASystemFont_getCollectionIndex(const ASystemFont* font) {
+    LOG_ALWAYS_FATAL_IF(font == nullptr, "nullptr has passed to font argument");
+    return font->mCollectionIndex;
+}
+
+size_t ASystemFont_getAxisCount(const ASystemFont* font) {
+    LOG_ALWAYS_FATAL_IF(font == nullptr, "nullptr has passed to font argument");
+    return font->mAxes.size();
+}
+
+uint32_t ASystemFont_getAxisTag(const ASystemFont* font, uint32_t axisIndex) {
+    LOG_ALWAYS_FATAL_IF(font == nullptr, "nullptr has passed to font argument");
+    LOG_ALWAYS_FATAL_IF(axisIndex >= font->mAxes.size(),
+                        "given axis index is out of bounds. (< %zd", font->mAxes.size());
+    return font->mAxes[axisIndex].first;
+}
+
+float ASystemFont_getAxisValue(const ASystemFont* font, uint32_t axisIndex) {
+    LOG_ALWAYS_FATAL_IF(font == nullptr, "nullptr has passed to font argument");
+    LOG_ALWAYS_FATAL_IF(axisIndex >= font->mAxes.size(),
+                        "given axis index is out of bounds. (< %zd", font->mAxes.size());
+    return font->mAxes[axisIndex].second;
+}
diff --git a/native/webview/loader/loader.cpp b/native/webview/loader/loader.cpp
index adb371d..fee2a25 100644
--- a/native/webview/loader/loader.cpp
+++ b/native/webview/loader/loader.cpp
@@ -64,7 +64,8 @@
   return JNI_TRUE;
 }
 
-jboolean DoCreateRelroFile(const char* lib, const char* relro) {
+jboolean DoCreateRelroFile(JNIEnv* env, const char* lib, const char* relro,
+                           jobject clazzLoader) {
   // Try to unlink the old file, since if this is being called, the old one is
   // obsolete.
   if (unlink(relro) != 0 && errno != ENOENT) {
@@ -82,11 +83,19 @@
     ALOGE("Failed to create temporary file %s: %s", relro_tmp, strerror(errno));
     return JNI_FALSE;
   }
+  android_namespace_t* ns =
+      android::FindNamespaceByClassLoader(env, clazzLoader);
+  if (ns == NULL) {
+    ALOGE("Failed to find classloader namespace");
+    return JNI_FALSE;
+  }
   android_dlextinfo extinfo;
-  extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS | ANDROID_DLEXT_WRITE_RELRO;
+  extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS | ANDROID_DLEXT_WRITE_RELRO |
+                  ANDROID_DLEXT_USE_NAMESPACE;
   extinfo.reserved_addr = gReservedAddress;
   extinfo.reserved_size = gReservedSize;
   extinfo.relro_fd = tmp_fd;
+  extinfo.library_namespace = ns;
   void* handle = android_dlopen_ext(lib, RTLD_NOW, &extinfo);
   int close_result = close(tmp_fd);
   if (handle == NULL) {
@@ -143,13 +152,14 @@
   return DoReserveAddressSpace(size);
 }
 
-jboolean CreateRelroFile(JNIEnv* env, jclass, jstring lib, jstring relro) {
+jboolean CreateRelroFile(JNIEnv* env, jclass, jstring lib, jstring relro,
+                         jobject clazzLoader) {
   jboolean ret = JNI_FALSE;
   const char* lib_utf8 = env->GetStringUTFChars(lib, NULL);
   if (lib_utf8 != NULL) {
     const char* relro_utf8 = env->GetStringUTFChars(relro, NULL);
     if (relro_utf8 != NULL) {
-      ret = DoCreateRelroFile(lib_utf8, relro_utf8);
+      ret = DoCreateRelroFile(env, lib_utf8, relro_utf8, clazzLoader);
       env->ReleaseStringUTFChars(relro, relro_utf8);
     }
     env->ReleaseStringUTFChars(lib, lib_utf8);
@@ -179,7 +189,7 @@
   { "nativeReserveAddressSpace", "(J)Z",
       reinterpret_cast<void*>(ReserveAddressSpace) },
   { "nativeCreateRelroFile",
-      "(Ljava/lang/String;Ljava/lang/String;)Z",
+      "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/ClassLoader;)Z",
       reinterpret_cast<void*>(CreateRelroFile) },
   { "nativeLoadWithRelroFile",
       "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/ClassLoader;)I",
diff --git a/packages/CaptivePortalLogin/Android.mk b/packages/CaptivePortalLogin/Android.mk
index 3ea3340..8c63f45 100644
--- a/packages/CaptivePortalLogin/Android.mk
+++ b/packages/CaptivePortalLogin/Android.mk
@@ -4,7 +4,6 @@
 LOCAL_MODULE_TAGS := optional
 LOCAL_USE_AAPT2 := true
 LOCAL_STATIC_ANDROID_LIBRARIES := androidx.legacy_legacy-support-v4
-LOCAL_STATIC_JAVA_LIBRARIES := services.net
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
diff --git a/packages/CarSystemUI/Android.bp b/packages/CarSystemUI/Android.bp
index f908595..86f9032 100644
--- a/packages/CarSystemUI/Android.bp
+++ b/packages/CarSystemUI/Android.bp
@@ -51,6 +51,7 @@
     libs: [
         "telephony-common",
         "android.car",
+        "android.car.user",
     ],
 
     manifest: "AndroidManifest.xml",
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/hvac/AnimatedTemperatureView.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/hvac/AnimatedTemperatureView.java
index 6473f0d..0467bff 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/hvac/AnimatedTemperatureView.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/hvac/AnimatedTemperatureView.java
@@ -177,7 +177,7 @@
                             }
                         }
                         textView.getViewTreeObserver().removeOnPreDrawListener(this);
-                        return false;
+                        return true;
                     }
                 });
         textView.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
diff --git a/packages/CarrierDefaultApp/Android.mk b/packages/CarrierDefaultApp/Android.mk
index 5068b3b..df88afd 100644
--- a/packages/CarrierDefaultApp/Android.mk
+++ b/packages/CarrierDefaultApp/Android.mk
@@ -9,8 +9,6 @@
 LOCAL_PRIVATE_PLATFORM_APIS := true
 LOCAL_CERTIFICATE := platform
 
-LOCAL_STATIC_JAVA_LIBRARIES := services.net
-
 include $(BUILD_PACKAGE)
 
 # This finds and builds the test apk as well, so a single make does both.
diff --git a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java
index b1933373..4f67350 100644
--- a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java
+++ b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java
@@ -32,7 +32,6 @@
 import android.net.Proxy;
 import android.net.TrafficStats;
 import android.net.Uri;
-import android.net.dns.ResolvUtil;
 import android.net.http.SslError;
 import android.os.Bundle;
 import android.telephony.CarrierConfigManager;
@@ -159,9 +158,9 @@
 
     private void setNetwork(Network network) {
         if (network != null) {
+            network = network.getPrivateDnsBypassingCopy();
             mCm.bindProcessToNetwork(network);
-            mCm.setProcessDefaultNetworkForHostResolution(
-                    ResolvUtil.getNetworkWithUseLocalNameserversFlag(network));
+            mCm.setProcessDefaultNetworkForHostResolution(network);
         }
         mNetwork = network;
     }
@@ -242,7 +241,6 @@
     private void testForCaptivePortal() {
         mTestingThread = new Thread(new Runnable() {
             public void run() {
-                final Network network = ResolvUtil.makeNetworkWithPrivateDnsBypass(mNetwork);
                 // Give time for captive portal to open.
                 try {
                     Thread.sleep(1000);
@@ -253,7 +251,7 @@
                 int httpResponseCode = 500;
                 int oldTag = TrafficStats.getAndSetThreadStatsTag(TrafficStats.TAG_SYSTEM_PROBE);
                 try {
-                    urlConnection = (HttpURLConnection) network.openConnection(
+                    urlConnection = (HttpURLConnection) mNetwork.openConnection(
                             new URL(mCm.getCaptivePortalServerUrl()));
                     urlConnection.setInstanceFollowRedirects(false);
                     urlConnection.setConnectTimeout(SOCKET_TIMEOUT_MS);
diff --git a/packages/DefaultContainerService/res/values-fr-rCA/strings.xml b/packages/DefaultContainerService/res/values-fr-rCA/strings.xml
index 69c4e99..353d0b4 100644
--- a/packages/DefaultContainerService/res/values-fr-rCA/strings.xml
+++ b/packages/DefaultContainerService/res/values-fr-rCA/strings.xml
@@ -20,5 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="service_name" msgid="4841491635055379553">"Aide accès au paquet"</string>
+    <string name="service_name" msgid="4841491635055379553">"Aide Accès au paquet"</string>
 </resources>
diff --git a/packages/DefaultContainerService/res/values-pt-rPT/strings.xml b/packages/DefaultContainerService/res/values-pt-rPT/strings.xml
index 8ea6a3a..647334b 100644
--- a/packages/DefaultContainerService/res/values-pt-rPT/strings.xml
+++ b/packages/DefaultContainerService/res/values-pt-rPT/strings.xml
@@ -20,5 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="service_name" msgid="4841491635055379553">"Ajuda p/ aceder a pacotes"</string>
+    <string name="service_name" msgid="4841491635055379553">"Ajuda acesso a pacotes"</string>
 </resources>
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
index 0a720a5..62207c5 100644
--- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
+++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
@@ -145,6 +145,7 @@
         }
     }
 
+    @GuardedBy("mRootsLock")
     private void updateVolumesLocked() {
         mRoots.clear();
 
diff --git a/packages/PackageInstaller/AndroidManifest.xml b/packages/PackageInstaller/AndroidManifest.xml
index 2be9311..7c81399 100644
--- a/packages/PackageInstaller/AndroidManifest.xml
+++ b/packages/PackageInstaller/AndroidManifest.xml
@@ -106,6 +106,14 @@
             </intent-filter>
         </receiver>
 
+        <receiver android:name=".PackageInstalledReceiver"
+                android:exported="true">
+            <intent-filter android:priority="1">
+                <action android:name="android.intent.action.PACKAGE_ADDED" />
+                <data android:scheme="package" />
+            </intent-filter>
+        </receiver>
+
         <activity android:name=".UninstallUninstalling"
             android:excludeFromRecents="true"
             android:exported="false" />
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstalledReceiver.java b/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstalledReceiver.java
new file mode 100644
index 0000000..67ac99f
--- /dev/null
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstalledReceiver.java
@@ -0,0 +1,34 @@
+/*
+ * 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.packageinstaller;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+/**
+ * Receive new app installed broadcast and notify user new app installed.
+ */
+public class PackageInstalledReceiver extends BroadcastReceiver {
+
+    private static final String TAG = "PackageInstalledReceiver";
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        // TODO: Add logic to handle new app installed.
+    }
+}
diff --git a/packages/SettingsLib/HelpUtils/res/values-af/strings.xml b/packages/SettingsLib/HelpUtils/res/values-af/strings.xml
new file mode 100644
index 0000000..8bf8545
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-af/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"Hulp en terugvoer"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-am/strings.xml b/packages/SettingsLib/HelpUtils/res/values-am/strings.xml
new file mode 100644
index 0000000..10a276c
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-am/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"እገዛ እና ግብረመልስ"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-ar/strings.xml b/packages/SettingsLib/HelpUtils/res/values-ar/strings.xml
new file mode 100644
index 0000000..cfbe26a
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-ar/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"المساعدة والتعليقات"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-as/strings.xml b/packages/SettingsLib/HelpUtils/res/values-as/strings.xml
new file mode 100644
index 0000000..0a3cb6d
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-as/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"সহায় আৰু প্ৰতিক্ৰিয়া"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-az/strings.xml b/packages/SettingsLib/HelpUtils/res/values-az/strings.xml
new file mode 100644
index 0000000..a7353d9
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-az/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"Yardım və rəy"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/HelpUtils/res/values-b+sr+Latn/strings.xml
new file mode 100644
index 0000000..af5aee7
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-b+sr+Latn/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"Pomoć i povratne informacije"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-be/strings.xml b/packages/SettingsLib/HelpUtils/res/values-be/strings.xml
new file mode 100644
index 0000000..87f8e74
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-be/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"Даведка і водгукі"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-bg/strings.xml b/packages/SettingsLib/HelpUtils/res/values-bg/strings.xml
new file mode 100644
index 0000000..d51626b
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-bg/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"Помощ и отзиви"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-bn/strings.xml b/packages/SettingsLib/HelpUtils/res/values-bn/strings.xml
new file mode 100644
index 0000000..57b7218
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-bn/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"সহায়তা ও মতামত"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-bs/strings.xml b/packages/SettingsLib/HelpUtils/res/values-bs/strings.xml
new file mode 100644
index 0000000..af5aee7
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-bs/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"Pomoć i povratne informacije"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-ca/strings.xml b/packages/SettingsLib/HelpUtils/res/values-ca/strings.xml
new file mode 100644
index 0000000..b62c6cd
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-ca/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"Ajuda i suggeriments"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-cs/strings.xml b/packages/SettingsLib/HelpUtils/res/values-cs/strings.xml
new file mode 100644
index 0000000..2da1b9c
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-cs/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"Nápověda a zpětná vazba"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-da/strings.xml b/packages/SettingsLib/HelpUtils/res/values-da/strings.xml
new file mode 100644
index 0000000..4f364743
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-da/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"Hjælp og feedback"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-de/strings.xml b/packages/SettingsLib/HelpUtils/res/values-de/strings.xml
new file mode 100644
index 0000000..e82e92b
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-de/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"Hilfe &amp; Feedback"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-el/strings.xml b/packages/SettingsLib/HelpUtils/res/values-el/strings.xml
new file mode 100644
index 0000000..bd41d3e
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-el/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"Βοήθεια και σχόλια"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-en-rAU/strings.xml b/packages/SettingsLib/HelpUtils/res/values-en-rAU/strings.xml
new file mode 100644
index 0000000..dce3496
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-en-rAU/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"Help &amp; feedback"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-en-rCA/strings.xml b/packages/SettingsLib/HelpUtils/res/values-en-rCA/strings.xml
new file mode 100644
index 0000000..dce3496
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-en-rCA/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"Help &amp; feedback"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-en-rGB/strings.xml b/packages/SettingsLib/HelpUtils/res/values-en-rGB/strings.xml
new file mode 100644
index 0000000..dce3496
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-en-rGB/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"Help &amp; feedback"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-en-rIN/strings.xml b/packages/SettingsLib/HelpUtils/res/values-en-rIN/strings.xml
new file mode 100644
index 0000000..dce3496
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-en-rIN/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"Help &amp; feedback"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-en-rXC/strings.xml b/packages/SettingsLib/HelpUtils/res/values-en-rXC/strings.xml
new file mode 100644
index 0000000..21084fb
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-en-rXC/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‏‏‏‎‎‏‎‎‏‏‎‎‏‏‎‎‏‎‏‏‎‎‏‎‏‏‎‎‎‏‎‏‎‎‏‎‏‎‎‎‏‏‎‎‏‏‎‏‎‎‎‎‎‎‎‏‏‏‎‎Help &amp; feedback‎‏‎‎‏‎"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-es-rUS/strings.xml b/packages/SettingsLib/HelpUtils/res/values-es-rUS/strings.xml
new file mode 100644
index 0000000..3bc97c6
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-es-rUS/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"Ayuda y comentarios"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-es/strings.xml b/packages/SettingsLib/HelpUtils/res/values-es/strings.xml
new file mode 100644
index 0000000..8567018
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-es/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"Ayuda y sugerencias"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-et/strings.xml b/packages/SettingsLib/HelpUtils/res/values-et/strings.xml
new file mode 100644
index 0000000..177c3e0
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-et/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"Abi ja tagasiside"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-eu/strings.xml b/packages/SettingsLib/HelpUtils/res/values-eu/strings.xml
new file mode 100644
index 0000000..ff22ba5
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-eu/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"Laguntza eta iritziak"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-fa/strings.xml b/packages/SettingsLib/HelpUtils/res/values-fa/strings.xml
new file mode 100644
index 0000000..d07d8f6
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-fa/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"راهنما و بازخورد"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-fi/strings.xml b/packages/SettingsLib/HelpUtils/res/values-fi/strings.xml
new file mode 100644
index 0000000..e94ebc5
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-fi/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"Ohje ja palaute"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-fr-rCA/strings.xml b/packages/SettingsLib/HelpUtils/res/values-fr-rCA/strings.xml
new file mode 100644
index 0000000..fd59425
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-fr-rCA/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"Aide et rétroaction"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-fr/strings.xml b/packages/SettingsLib/HelpUtils/res/values-fr/strings.xml
new file mode 100644
index 0000000..23f0b3b
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-fr/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"Aide et commentaires"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-gl/strings.xml b/packages/SettingsLib/HelpUtils/res/values-gl/strings.xml
new file mode 100644
index 0000000..c8cc6b6
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-gl/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"Axuda e comentarios"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-gu/strings.xml b/packages/SettingsLib/HelpUtils/res/values-gu/strings.xml
new file mode 100644
index 0000000..a53c6d2
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-gu/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"સહાય અને પ્રતિસાદ"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-hr/strings.xml b/packages/SettingsLib/HelpUtils/res/values-hr/strings.xml
new file mode 100644
index 0000000..af5aee7
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-hr/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"Pomoć i povratne informacije"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-hu/strings.xml b/packages/SettingsLib/HelpUtils/res/values-hu/strings.xml
new file mode 100644
index 0000000..bcf2734
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-hu/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"Súgó és visszajelzés"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-hy/strings.xml b/packages/SettingsLib/HelpUtils/res/values-hy/strings.xml
new file mode 100644
index 0000000..ea14fa5
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-hy/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"Օգնություն և հետադարձ կապ"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-in/strings.xml b/packages/SettingsLib/HelpUtils/res/values-in/strings.xml
new file mode 100644
index 0000000..3055c7f
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-in/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"Bantuan &amp; masukan"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-is/strings.xml b/packages/SettingsLib/HelpUtils/res/values-is/strings.xml
new file mode 100644
index 0000000..1feaf4a3
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-is/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"Hjálp og ábendingar"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-it/strings.xml b/packages/SettingsLib/HelpUtils/res/values-it/strings.xml
new file mode 100644
index 0000000..8e4d78d
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-it/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"Guida e feedback"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-iw/strings.xml b/packages/SettingsLib/HelpUtils/res/values-iw/strings.xml
new file mode 100644
index 0000000..ab52996
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-iw/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"עזרה ומשוב"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-ja/strings.xml b/packages/SettingsLib/HelpUtils/res/values-ja/strings.xml
new file mode 100644
index 0000000..8c75d32
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-ja/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"ヘルプとフィードバック"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-ka/strings.xml b/packages/SettingsLib/HelpUtils/res/values-ka/strings.xml
new file mode 100644
index 0000000..53b956f
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-ka/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"დახმარება და გამოხმაურება"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-kk/strings.xml b/packages/SettingsLib/HelpUtils/res/values-kk/strings.xml
new file mode 100644
index 0000000..ef351ac
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-kk/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"Анықтама және пікір"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-km/strings.xml b/packages/SettingsLib/HelpUtils/res/values-km/strings.xml
new file mode 100644
index 0000000..b2b0615
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-km/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"ជំនួយ និងមតិកែលម្អ"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-kn/strings.xml b/packages/SettingsLib/HelpUtils/res/values-kn/strings.xml
new file mode 100644
index 0000000..8a86559
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-kn/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"ಸಹಾಯ ಮತ್ತು ಪ್ರತಿಕ್ರಿಯೆ"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-ko/strings.xml b/packages/SettingsLib/HelpUtils/res/values-ko/strings.xml
new file mode 100644
index 0000000..f974a51
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-ko/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"도움말 및 의견"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-ky/strings.xml b/packages/SettingsLib/HelpUtils/res/values-ky/strings.xml
new file mode 100644
index 0000000..3c0cf87
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-ky/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"Жардам/Пикир билдирүү"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-lo/strings.xml b/packages/SettingsLib/HelpUtils/res/values-lo/strings.xml
new file mode 100644
index 0000000..3765d6e
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-lo/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"ຊ່ວຍເຫຼືອ ແລະ ຕິຊົມ"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-lt/strings.xml b/packages/SettingsLib/HelpUtils/res/values-lt/strings.xml
new file mode 100644
index 0000000..d7bce29
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-lt/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"Pagalba ir atsiliepimai"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-lv/strings.xml b/packages/SettingsLib/HelpUtils/res/values-lv/strings.xml
new file mode 100644
index 0000000..77496a9
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-lv/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"Palīdzība un atsauksmes"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-mk/strings.xml b/packages/SettingsLib/HelpUtils/res/values-mk/strings.xml
new file mode 100644
index 0000000..516c186
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-mk/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"Помош и повратни информации"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-ml/strings.xml b/packages/SettingsLib/HelpUtils/res/values-ml/strings.xml
new file mode 100644
index 0000000..d2a7452
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-ml/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"സഹായം &amp; ഫീഡ്‌ബാക്ക്"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-mn/strings.xml b/packages/SettingsLib/HelpUtils/res/values-mn/strings.xml
new file mode 100644
index 0000000..c3ebe8b
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-mn/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"Тусламж &amp; санал хүсэлт"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-mr/strings.xml b/packages/SettingsLib/HelpUtils/res/values-mr/strings.xml
new file mode 100644
index 0000000..7f3a881
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-mr/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"मदत आणि फीडबॅक"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-ms/strings.xml b/packages/SettingsLib/HelpUtils/res/values-ms/strings.xml
new file mode 100644
index 0000000..7c7c971
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-ms/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"Bantuan &amp; maklum balas"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-my/strings.xml b/packages/SettingsLib/HelpUtils/res/values-my/strings.xml
new file mode 100644
index 0000000..f051860
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-my/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"အကူအညီနှင့် အကြံပြုချက်"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-nb/strings.xml b/packages/SettingsLib/HelpUtils/res/values-nb/strings.xml
new file mode 100644
index 0000000..96886f6
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-nb/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"Hjelp og tilbakemelding"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-ne/strings.xml b/packages/SettingsLib/HelpUtils/res/values-ne/strings.xml
new file mode 100644
index 0000000..40508ad
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-ne/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"मद्दत र प्रतिक्रिया"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-nl/strings.xml b/packages/SettingsLib/HelpUtils/res/values-nl/strings.xml
new file mode 100644
index 0000000..a034d29
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-nl/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"Help en feedback"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-or/strings.xml b/packages/SettingsLib/HelpUtils/res/values-or/strings.xml
new file mode 100644
index 0000000..e91cb61
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-or/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"ସହାୟତା ଓ ମତାମତ"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-pa/strings.xml b/packages/SettingsLib/HelpUtils/res/values-pa/strings.xml
new file mode 100644
index 0000000..d847a59
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-pa/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"ਮਦਦ ਅਤੇ ਵਿਚਾਰ"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-pl/strings.xml b/packages/SettingsLib/HelpUtils/res/values-pl/strings.xml
new file mode 100644
index 0000000..e137a6b
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-pl/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"Pomoc i opinie"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-pt-rBR/strings.xml b/packages/SettingsLib/HelpUtils/res/values-pt-rBR/strings.xml
new file mode 100644
index 0000000..73dfc49
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-pt-rBR/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"Ajuda e feedback"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-pt-rPT/strings.xml b/packages/SettingsLib/HelpUtils/res/values-pt-rPT/strings.xml
new file mode 100644
index 0000000..baac2e8
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-pt-rPT/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"Ajuda e comentários"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-pt/strings.xml b/packages/SettingsLib/HelpUtils/res/values-pt/strings.xml
new file mode 100644
index 0000000..73dfc49
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-pt/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"Ajuda e feedback"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-ro/strings.xml b/packages/SettingsLib/HelpUtils/res/values-ro/strings.xml
new file mode 100644
index 0000000..1422912
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-ro/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"Ajutor și feedback"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-ru/strings.xml b/packages/SettingsLib/HelpUtils/res/values-ru/strings.xml
new file mode 100644
index 0000000..d7d1108
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-ru/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"Справка и отзывы"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-si/strings.xml b/packages/SettingsLib/HelpUtils/res/values-si/strings.xml
new file mode 100644
index 0000000..719d7dc
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-si/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"උදවු සහ ප්‍රතිපෝෂණ"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-sk/strings.xml b/packages/SettingsLib/HelpUtils/res/values-sk/strings.xml
new file mode 100644
index 0000000..a9eede3
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-sk/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"Pomocník a spätná väzba"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-sl/strings.xml b/packages/SettingsLib/HelpUtils/res/values-sl/strings.xml
new file mode 100644
index 0000000..81db744
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-sl/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"Pomoč in povratne informacije"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-sq/strings.xml b/packages/SettingsLib/HelpUtils/res/values-sq/strings.xml
new file mode 100644
index 0000000..fddeff6
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-sq/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"Ndihma dhe komentet"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-sr/strings.xml b/packages/SettingsLib/HelpUtils/res/values-sr/strings.xml
new file mode 100644
index 0000000..5d258060
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-sr/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"Помоћ и повратне информације"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-sv/strings.xml b/packages/SettingsLib/HelpUtils/res/values-sv/strings.xml
new file mode 100644
index 0000000..df1c891
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-sv/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"Hjälp och feedback"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-sw/strings.xml b/packages/SettingsLib/HelpUtils/res/values-sw/strings.xml
new file mode 100644
index 0000000..a4bb726
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-sw/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"Usaidizi na maoni"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-ta/strings.xml b/packages/SettingsLib/HelpUtils/res/values-ta/strings.xml
new file mode 100644
index 0000000..91e8e46
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-ta/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"உதவி &amp; கருத்து"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-te/strings.xml b/packages/SettingsLib/HelpUtils/res/values-te/strings.xml
new file mode 100644
index 0000000..753b320
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-te/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"సహాయం &amp; అభిప్రాయం"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-th/strings.xml b/packages/SettingsLib/HelpUtils/res/values-th/strings.xml
new file mode 100644
index 0000000..53d16a6
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-th/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"ความช่วยเหลือและความคิดเห็น"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-tl/strings.xml b/packages/SettingsLib/HelpUtils/res/values-tl/strings.xml
new file mode 100644
index 0000000..7edcd18
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-tl/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"Tulong at feedback"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-tr/strings.xml b/packages/SettingsLib/HelpUtils/res/values-tr/strings.xml
new file mode 100644
index 0000000..263226f
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-tr/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"Yardım ve geri bildirim"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-uk/strings.xml b/packages/SettingsLib/HelpUtils/res/values-uk/strings.xml
new file mode 100644
index 0000000..ebef521
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-uk/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"Довідка й відгуки"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-ur/strings.xml b/packages/SettingsLib/HelpUtils/res/values-ur/strings.xml
new file mode 100644
index 0000000..084bf29
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-ur/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"مدد اور تاثرات"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-uz/strings.xml b/packages/SettingsLib/HelpUtils/res/values-uz/strings.xml
new file mode 100644
index 0000000..2106bed
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-uz/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"Yordam va fikr-mulohaza"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-vi/strings.xml b/packages/SettingsLib/HelpUtils/res/values-vi/strings.xml
new file mode 100644
index 0000000..68ce6d1
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-vi/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"Trợ giúp &amp; phản hồi"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-zh-rCN/strings.xml b/packages/SettingsLib/HelpUtils/res/values-zh-rCN/strings.xml
new file mode 100644
index 0000000..a6d9f49
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-zh-rCN/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"帮助和反馈"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-zh-rHK/strings.xml b/packages/SettingsLib/HelpUtils/res/values-zh-rHK/strings.xml
new file mode 100644
index 0000000..a6eae04
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-zh-rHK/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"說明與意見反映"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-zh-rTW/strings.xml b/packages/SettingsLib/HelpUtils/res/values-zh-rTW/strings.xml
new file mode 100644
index 0000000..d66802c
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-zh-rTW/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"說明與意見回饋"</string>
+</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-zu/strings.xml b/packages/SettingsLib/HelpUtils/res/values-zu/strings.xml
new file mode 100644
index 0000000..32993ce8
--- /dev/null
+++ b/packages/SettingsLib/HelpUtils/res/values-zu/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="help_feedback_label" msgid="4550436169116444686">"Usizo nempendulo"</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index 296a135..aa96444 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Groter"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Grootste"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Gepasmaak (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"Hulp en terugvoer"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Kieslys"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Voer wagwoord in om fabriekterugstelling in demonstrasiemodus uit te voer"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Volgende"</string>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index ab52bcb..452206c 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"ተለቅ ያለ"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"በጣም ተለቅ ያለ"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"ብጁ (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"እገዛ እና ግብረመልስ"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"ምናሌ"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"የፋብሪካ ዳግም ማስጀመር በማሳያ ሁነታ ውስጥ ለማከናወን የይለፍ ቃል ያስገቡ"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"ቀጣይ"</string>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index e8811eb..e67e1ec 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"أكبر"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"أكبر مستوى"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"مخصص (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"المساعدة والتعليقات"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"القائمة"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"إدخال كلمة المرور لإعادة الضبط بحسب بيانات المصنع في الوضع التجريبي"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"التالي"</string>
diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml
index 0adac28..7311661 100644
--- a/packages/SettingsLib/res/values-as/strings.xml
+++ b/packages/SettingsLib/res/values-as/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"বৃহত্তৰ"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"সকলোতকৈ ডাঙৰ"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"নিজৰ উপযোগিতা অনুযায়ী (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"সহায় আৰু ফীডবেক"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"মেনু"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"ডেম’ ম\'ডত ফেক্টৰী ৰিছেট কৰিবলৈ পাছৱৰ্ড দিয়ক"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"পৰৱৰ্তী"</string>
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index 8f974fe..750bf5d 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Daha böyük"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Ən böyük"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Fərdi (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"Yardım və rəy"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menyu"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Demo rejimində sıfırlamaq üçün parol daxil edin"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Növbəti"</string>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index 1e3eba6..cd8096c 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Veći"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Najveći"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Prilagođeni (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"Pomoć i povratne informacije"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Meni"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Unesite lozinku da biste obavili resetovanje na fabrička podešavanja u režimu demonstracije"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Dalje"</string>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index 42fda63..072913a 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Большы"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Самы вялікі"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Карыстальніцкі (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"Даведка і водгукі"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Меню"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Каб выканаць скід да заводскіх налад у дэманстрацыйным рэжыме, увядзіце пароль"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Далей"</string>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index a309449..a5ce523 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"По-голямо"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Най-голямо"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Персонализирано (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"Помощ и отзиви"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Меню"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Въведете парола за възст. на фабр. настройки в демонстр. режим"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Напред"</string>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index ad4ef2f..c053771 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"খুব বড়"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"বৃহত্তম"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"কাস্টম (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"সহায়তা ও মতামত"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"মেনু"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"ডেমো মোডে ফ্যাক্টরি রিসেট করতে পাসওয়ার্ড দিন"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"পরবর্তী"</string>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index 4332682..764bc19 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Vrlo veliko"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Najveći"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Prilagodi (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"Pomoć i povratne informacije"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Meni"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Unesite lozinku da izvršite vraćanje na fabričke postavke u načinu demonstracije"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Naprijed"</string>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index 7750ef2..8309c41a 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Més gran"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Més grans possible"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Personalitzat (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"Ajuda i suggeriments"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menú"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Introdueix la contrasenya per restablir les dades de fàbrica en mode de demostració"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Següent"</string>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index 72b3389..bd8bc2b 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Větší"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Největší"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Vlastní (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"Nápověda a zpětná vazba"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Nabídka"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Chcete-li v ukázkovém režimu obnovit zařízení do továrního nastavení, zadejte heslo"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Další"</string>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index ca96070..ab81346 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -196,7 +196,7 @@
     <string name="bugreport_in_power_summary" msgid="1778455732762984579">"Vis en knap til oprettelse af fejlrapporter i menu for slukknap"</string>
     <string name="keep_screen_on" msgid="1146389631208760344">"Lås ikke"</string>
     <string name="keep_screen_on_summary" msgid="2173114350754293009">"Skærmen går ikke i dvale under opladning"</string>
-    <string name="bt_hci_snoop_log" msgid="3340699311158865670">"Aktivér Bluetooth HCI snoop log"</string>
+    <string name="bt_hci_snoop_log" msgid="3340699311158865670">"Aktivér Bluetooth HCI spionlog"</string>
     <string name="bt_hci_snoop_log_summary" msgid="366083475849911315">"Gem alle Bluetooth HCI-pakker i en fil (slå Bluetooth fra og til igen, når du har ændret denne indstilling)"</string>
     <string name="oem_unlock_enable" msgid="6040763321967327691">"OEM-oplåsning"</string>
     <string name="oem_unlock_enable_summary" msgid="4720281828891618376">"Tillad, at startindlæseren låses op"</string>
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Større"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Størst"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Tilpasset (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"Hjælp og feedback"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menu"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Angiv adgangskode for at gendanne fabriksdata i demotilstand"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Næste"</string>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index 9db490b..2432a10 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Größer"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Am größten"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Benutzerdefiniert (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"Hilfe &amp; Feedback"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menü"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Passwort eingeben, um Gerät im Demomodus auf Werkseinstellungen zurückzusetzen"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Weiter"</string>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index 2ba543e..6f2889c 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Πιο μεγάλα"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Μεγαλύτερα"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Προσαρμοσμένη (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"Βοήθεια και σχόλια"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Μενού"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Εισαγάγετε κωδικό πρόσβασης για επαναφορά εργοστασιακών ρυθμίσεων στη λειτουργία επίδειξης"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Επόμενο"</string>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index 747fdc7..154aa7d9 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Larger"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Largest"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Custom (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"Help &amp; feedback"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menu"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Enter password to perform factory reset in demo mode"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Next"</string>
diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml
index 747fdc7..154aa7d9 100644
--- a/packages/SettingsLib/res/values-en-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-en-rCA/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Larger"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Largest"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Custom (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"Help &amp; feedback"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menu"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Enter password to perform factory reset in demo mode"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Next"</string>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index 747fdc7..154aa7d9 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Larger"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Largest"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Custom (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"Help &amp; feedback"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menu"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Enter password to perform factory reset in demo mode"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Next"</string>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index 747fdc7..154aa7d9 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Larger"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Largest"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Custom (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"Help &amp; feedback"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menu"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Enter password to perform factory reset in demo mode"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Next"</string>
diff --git a/packages/SettingsLib/res/values-en-rXC/strings.xml b/packages/SettingsLib/res/values-en-rXC/strings.xml
index 33b9f1d..e9746c0 100644
--- a/packages/SettingsLib/res/values-en-rXC/strings.xml
+++ b/packages/SettingsLib/res/values-en-rXC/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‎‎‏‎‏‎‏‎‎‏‏‎‏‎‏‏‎‎‎‎‏‎‏‏‏‎‏‎‎‎‏‏‎‏‎‏‏‏‎‎‏‎‎‎‏‏‏‎‎‎‏‏‎‎‏‏‎‎‏‏‎Larger‎‏‎‎‏‎"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎‎‏‎‎‏‏‎‎‏‎‎‏‎‎‎‏‎‏‎‏‏‏‎‏‏‎‎‏‏‎‎‏‏‎‏‏‎‏‎‏‎‏‎‏‏‎‏‏‎‎‎‎‏‏‎Largest‎‏‎‎‏‎"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‏‏‎‏‏‏‏‎‎‎‎‏‏‏‎‎‎‎‎‏‏‏‏‏‎‎‏‏‏‏‏‎‏‏‏‏‏‏‎‎‎‎‏‏‏‏‏‏‏‎‎‏‏‎‏‏‏‏‏‏‎Custom (‎‏‎‎‏‏‎<xliff:g id="DENSITYDPI">%d</xliff:g>‎‏‎‎‏‏‏‎)‎‏‎‎‏‎"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‏‏‏‎‏‎‎‏‎‎‏‏‏‏‏‎‎‎‏‏‎‏‎‏‏‏‏‏‏‎‎‏‎‏‎‎‏‏‏‎‏‏‏‏‎‎‎‎‏‏‏‏‎‎‏‏‎‎‎‏‎Help &amp; feedback‎‏‎‎‏‎"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‎‎‎‏‏‎‎‎‏‏‏‎‎‏‏‎‏‎‏‎‏‎‎‏‏‏‎‏‏‏‏‏‏‏‏‏‏‏‎‎‎‏‏‎‎‎‎‏‎‏‎‏‎‎‏‎‎‎‏‎‎Menu‎‏‎‎‏‎"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‎‎‏‏‏‎‏‎‎‏‎‏‏‏‏‏‎‏‏‎‎‎‏‏‎‏‎‎‏‎‏‏‎‎‎‏‎‎‎‎‏‎‎‏‏‏‎‏‏‎‎‏‏‏‏‎‎‎‎‏‎Enter password to perform factory reset in demo mode‎‏‎‎‏‎"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‎‎‏‏‏‏‏‏‏‎‎‏‎‎‎‏‎‎‏‎‏‏‏‏‏‏‎‎‎‏‏‏‏‏‏‎‏‎‎‎‎‏‎‎‎‎‎‎‎‎‎‏‏‏‎‎‎‎‏‏‎Next‎‏‎‎‏‎"</string>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index f665b77..706e1d3 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Más grande"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Máximo"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Personalizado (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"Ayuda y comentarios"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menú"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Ingresa contraseña y restablece en demo"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Siguiente"</string>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index 9cdde92..f9eddd9 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -242,7 +242,7 @@
     <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>
-    <string name="select_logpersist_title" msgid="7530031344550073166">"Guardar datos de forma continua"</string>
+    <string name="select_logpersist_title" msgid="7530031344550073166">"Guardar datos de registro de forma continua"</string>
     <string name="select_logpersist_dialog_title" msgid="4003400579973269060">"Seleccionar búferes de registro para guardarlos de forma continua en dispositivo"</string>
     <string name="select_usb_configuration_title" msgid="2649938511506971843">"Seleccionar configuración de USB"</string>
     <string name="select_usb_configuration_dialog_title" msgid="6385564442851599963">"Seleccionar configuración de USB"</string>
@@ -396,7 +396,7 @@
     <string name="battery_info_status_full" msgid="2824614753861462808">"Completa"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Controlada por el administrador"</string>
     <string name="enabled_by_admin" msgid="5302986023578399263">"Habilitada por el administrador"</string>
-    <string name="disabled_by_admin" msgid="8505398946020816620">"Inhabilitada por el administrador"</string>
+    <string name="disabled_by_admin" msgid="8505398946020816620">"Inhabilitado por el administrador"</string>
     <string name="disabled" msgid="9206776641295849915">"Inhabilitada"</string>
     <string name="external_source_trusted" msgid="2707996266575928037">"Autorizadas"</string>
     <string name="external_source_untrusted" msgid="2677442511837596726">"No autorizadas"</string>
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Más grande"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Lo más grande posible"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Personalizado (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"Ayuda y sugerencias"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menú"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Escribe una contraseña para restablecer estado de fábrica en modo demostración"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Siguiente"</string>
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index 2b44321..ac31880 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Suurem"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Suurim"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Kohandatud (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"Abi ja tagasiside"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menüü"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Sisestage parool, et demorežiimis tehaseseadetele lähtestada"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Järgmine"</string>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index 4ad60b3..2eee948 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Oso handia"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Handiena"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Pertsonalizatua (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"Laguntza eta iritziak"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menua"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Idatzi pasahitza jatorrizko ezarpenak demo moduan berrezartzeko"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Hurrengoa"</string>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index 1d08821..6efd4fe 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"بزرگ‌تر"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"بزرگ‌ترین"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"سفارشی (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"راهنما و بازخورد"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"منو"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"برای انجام بازنشانی کارخانه‌ای در حالت نمایشی، گذرواژه را وارد کنید"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"بعدی"</string>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index 7c253fc..4d64e81 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Suurempi"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Suurin"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Muokattu (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"Ohje ja palaute"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Valikko"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Palauta tehdasasetukset antamalla salasana"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Seuraava"</string>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index 99906ca..8e813ea 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Plus grande"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"La plus grande"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Personnalisée (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"Aide et commentaires"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menu"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Entrez m. passe pour réinit. en mode démo"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Suivant"</string>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index 7a51faa..baf8ed0 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -246,7 +246,7 @@
     <string name="select_logpersist_dialog_title" msgid="4003400579973269060">"Sélectionner les mémoires tampon journal à stocker en permanence sur l\'appareil"</string>
     <string name="select_usb_configuration_title" msgid="2649938511506971843">"Sélectionner une configuration USB"</string>
     <string name="select_usb_configuration_dialog_title" msgid="6385564442851599963">"Sélectionner une configuration USB"</string>
-    <string name="allow_mock_location" msgid="2787962564578664888">"Positions fictives"</string>
+    <string name="allow_mock_location" msgid="2787962564578664888">"Autoriser les positions fictives"</string>
     <string name="allow_mock_location_summary" msgid="317615105156345626">"Autoriser les positions fictives"</string>
     <string name="debug_view_attributes" msgid="6485448367803310384">"Activer inspect. attribut affich."</string>
     <string name="mobile_data_always_on_summary" msgid="8149773901431697910">"Maintenir les données mobiles à l\'état actif, même lorsque le Wi‑Fi est actif (pour changer rapidement de réseau)"</string>
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Très grand"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Extrêmement grand"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Personnalisé (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"Aide et commentaires"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menu"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Saisir mot de passe pour rétablir conf. d\'usine en mode démo."</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Suivant"</string>
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index 5bc6163..dc22b25 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Máis grande"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"O máis grande"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Personalizado (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"Axuda e comentarios"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menú"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Insire contrasinal para restablec. en demostración"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Seguinte"</string>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index b523ae2..7943d51 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"વધુ મોટું"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"સૌથી મોટું"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"કસ્ટમ (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"સહાય અને પ્રતિસાદ"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"મેનુ"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"ડેમો મોડમાં ફેક્ટરી રીસેટ પાસવર્ડ દાખલ કરો"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"આગલું"</string>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index cd12f21..3ec7e58 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"अधिक बड़ा"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"सबसे बड़ा"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"कस्टम (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"सहायता और फ़ीडबैक"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"मेन्यू"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"डेमो मोड में फ़ैक्टरी रीसेट के लिए पासवर्ड डालें"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"आगे"</string>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index 9c83640..ce8e6ec 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Veće"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Najveće"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Prilagođeno (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"Pomoć i povratne informacije"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Izbornik"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Unesite zaporku za resetiranje u demo načinu"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Dalje"</string>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index 25d11aa..1c79199 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Nagyobb"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Legnagyobb"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Egyéni (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"Súgó és visszajelzés"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menü"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Írja be a jelszót a visszaállításhoz"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Következő"</string>
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index f811312c..84ee039 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Ավելի մեծ"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Ամենամեծ"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Հատուկ (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"Օգնություն և հետադարձ կապ"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Ընտրացանկ"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Մուտքագրեք գաղտնաբառը՝ ցուցադրական ռեժիմում գործարանային վերակայում կատարելու համար"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Հաջորդը"</string>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index 39a88e5..9356c85 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -281,7 +281,7 @@
     <string name="strict_mode_summary" msgid="142834318897332338">"Kedipkan layar saat apl beroperasi lama pada utas utama"</string>
     <string name="pointer_location" msgid="6084434787496938001">"Lokasi penunjuk"</string>
     <string name="pointer_location_summary" msgid="840819275172753713">"Hamparan layar menampilkan data sentuhan saat ini"</string>
-    <string name="show_touches" msgid="2642976305235070316">"Tampilkan ketukan"</string>
+    <string name="show_touches" msgid="2642976305235070316">"Tampilkan tap"</string>
     <string name="show_touches_summary" msgid="6101183132903926324">"Tampilkan masukan visual untuk ketukan"</string>
     <string name="show_screen_updates" msgid="5470814345876056420">"Lihat pembaruan permukaan"</string>
     <string name="show_screen_updates_summary" msgid="2569622766672785529">"Sorot seluruh permukaan jendela saat diperbarui"</string>
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Lebih besar"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Terbesar"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"(<xliff:g id="DENSITYDPI">%d</xliff:g>) khusus"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"Bantuan &amp; masukan"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menu"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Masukkan sandi untuk mengembalikan ke setelan pabrik dalam mode demo"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Berikutnya"</string>
diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml
index afb10a9..ca5e1f5 100644
--- a/packages/SettingsLib/res/values-is/strings.xml
+++ b/packages/SettingsLib/res/values-is/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Stærra"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Stærst"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Sérsniðið (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"Hjálp og ábendingar"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Valmynd"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Sláðu inn aðgangsorð til að framkvæma núllstillingu í sýnisútgáfu"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Áfram"</string>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index 24eef7a..88a5bb8 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Più grande"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Massimo"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Personalizzato (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"Guida e feedback"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menu"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Inserisci la password per eseguire il ripristino dei dati di fabbrica in modalità demo"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Avanti"</string>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index e9c44c9..cec35cf 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"יותר גדול"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"הכי גדול"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"מותאם אישית (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"עזרה ומשוב"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"תפריט"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"הזן סיסמה כדי לבצע איפוס להגדרות היצרן במצב הדגמה"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"הבא"</string>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index 0cc2d17..9cfdadc 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"特大"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"最大"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"カスタム(<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"ヘルプとフィードバック"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"メニュー"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"デモモードで初期状態にリセットするには、パスワードを入力してください"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"次へ"</string>
diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml
index daca5b9..1083025 100644
--- a/packages/SettingsLib/res/values-ka/strings.xml
+++ b/packages/SettingsLib/res/values-ka/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"უფრო დიდი"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"უდიდესი"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"მორგებული (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"დახმარება და გამოხმაურება"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"მენიუ"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"შეიყვანეთ პაროლი დემო-რეჟიმში ქარხნულ მდგომარეობაზე დასაბრუნებლად"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"შემდეგი"</string>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index b95d6e9e..a122d91 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Үлкенірек"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Ең үлкен"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Арнаулы (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"Анықтама және пікір"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Mәзір"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Демо режимде зауыттық мәндерге қайтару үшін құпия сөзді енгізу"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Келесі"</string>
diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index 5bf38c0..7ffd766 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"ធំជាង"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"ធំបំផុត"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"ផ្ទាល់ខ្លួន (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"ជំនួយ និងមតិស្ថាបនា"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"ម៉ឺនុយ"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"បញ្ចូល​ពាក្យ​សម្ងាត់ ដើម្បី​កំណត់ឧបករណ៍​​ឡើង​វិញ​ដូចពេលចេញ​ពី​រោងចក្រ នៅក្នុង​មុខងារ​សាកល្បង"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"បន្ទាប់"</string>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index 923547f..e12cbd2 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"ಸ್ವಲ್ಪ ದೊಡ್ಡ"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"ದೊಡ್ಡ"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"ಕಸ್ಟಮ್ (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"ಸಹಾಯ ಮತ್ತು ಪ್ರತಿಕ್ರಿಯೆ"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"ಮೆನು"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"ಫ್ಯಾಕ್ಟರಿ ರಿಸೆಟ್‌ಗೆ ಪಾಸ್‌ವರ್ಡ್ ನಮೂದಿಸಿ"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"ಮುಂದೆ"</string>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index 9bac29d..d29bd65 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -135,7 +135,7 @@
     <string name="tether_settings_title_usb_bluetooth" msgid="5355828977109785001">"테더링"</string>
     <string name="tether_settings_title_all" msgid="8356136101061143841">"테더링 및 휴대용 핫스팟"</string>
     <string name="managed_user_title" msgid="8109605045406748842">"모든 직장 앱"</string>
-    <string name="user_guest" msgid="8475274842845401871">"손님"</string>
+    <string name="user_guest" msgid="8475274842845401871">"게스트"</string>
     <string name="unknown" msgid="1592123443519355854">"알 수 없음"</string>
     <string name="running_process_item_user_label" msgid="3129887865552025943">"사용자: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
     <string name="launch_defaults_some" msgid="313159469856372621">"일부 기본값이 설정됨"</string>
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"더 크게"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"가장 크게"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"맞춤(<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"고객센터"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"메뉴"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"데모 모드에서 초기화하려면 비밀번호 입력"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"다음"</string>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index 523fabe..56b5da1 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Чоңураак"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Эң чоң"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Ыңгайлаштырылган (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"Жардам жана пикир билдирүү"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Меню"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Демо режиминде демейки жөндөөлөргө кайтаруу үчүн сырсөздү киргизиңиз"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Кийинки"</string>
diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml
index f85a691..eb27f02 100644
--- a/packages/SettingsLib/res/values-lo/strings.xml
+++ b/packages/SettingsLib/res/values-lo/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"ໃຫຍ່ກວ່າ"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"ໃຫຍ່ທີ່ສຸດ"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"ປັບແຕ່ງເອງ (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"ຊ່ວຍເຫຼືອ &amp; ຄຳຕິຊົມ"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"ເມນູ"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Enter password to perform factory reset in demo mode"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"ຕໍ່ໄປ"</string>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index fc2924f..44b532b 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Didesnis"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Didžiausias"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Tinkintas (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"Pagalba ir atsiliepimai"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Meniu"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Įv. slapt. ir atk. gam. nust. dem. rež."</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Kitas"</string>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index 6ce5e8e..ba87d07 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Lielāks"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Vislielākais"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Pielāgots (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"Palīdzība un atsauksmes"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Izvēlne"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Iev. paroli, lai atiest. rūpnīcas iest. dem. režīmā"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Tālāk"</string>
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index c6c508e..0c5c94a 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Поголем"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Најголем"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Приспособен (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"Помош и повратни информации"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Мени"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Внесете лозинка за фаб. ресет. во демо"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Следно"</string>
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index 6b6462c..1a208e62 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"കൂടുതൽ വലുത്"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"ഏറ്റവും വലുത്"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"ഇഷ്ടാനുസൃതം ( <xliff:g id="DENSITYDPI">%d</xliff:g> )"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"സഹായവും പ്രതികരണവും"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"മെനു"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"ഡെമോ ‌മോഡിൽ ഫാക്ടറി റീസെറ്റിന് പാസ്‌വേഡ് നൽകുക"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"അടുത്തത്"</string>
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index 56f1cc0..809e82e 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Илүү том"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Хамгийн том"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Тогтмол утга (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"Тусламж, санал хүсэлт"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Цэс"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Үйлдвэрийн тохиргоог демо горимд ажиллуулахын тулд нууц үг оруулна уу"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Дараагийн"</string>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index 7485886..dfa6d2f 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"आणखी मोठा"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"सर्वात मोठा"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"कस्टम करा (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"मदत आणि अभिप्राय"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"मेनू"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"डेमो मोडमध्ये फॅक्टरी रीसेट करण्यासाठी पासवर्ड एंटर करा"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"पुढील"</string>
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index fdb8702..b4ed016 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Lebih besar"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Terbesar"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Tersuai (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"Bantuan &amp; maklum balas"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menu"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Mskkn kta laluan utk ttpn sml kilang dlm mod demo"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Seterusnya"</string>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index dc5d924..c1ffd28 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"ပိုကြီး"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"အကြီးဆုံး"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"စိတ်ကြိုက် (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"အကူအညီနှင့် အကြံပြုချက်"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"မီနူး"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"ဒီမိုမုဒ်၌မူလဆက်တင်ထားရန် စကားဝှက်ထည့်ပါ"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"ရှေ့သို့"</string>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index 460eb57..5a8e01e 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Større"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Størst"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Egendefinert (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"Hjelp og tilbakemelding"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Meny"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Skriv inn passordet for å tilbakestille til fabrikkstandard i demomodus"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Neste"</string>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index 763b60c..72a9abb 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"अझ ठूलो"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"सबैभन्दा ठूलो"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"आफू अनुकूल (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"मद्दत र प्रतिक्रिया"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"मेनु"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"डेमो मोडमा फ्याक्ट्री रिसेट गर्न पासवर्ड प्रविष्ट गर्नुहोस्"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"अर्को"</string>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index 264427e..f341717 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Groter"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Grootst"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Aangepast (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"Help en feedback"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menu"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Geef wachtwoord op om terug te zetten op fabrieksinstellingen in demomodus"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Volgende"</string>
diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml
index ecdc49e..a7761e9 100644
--- a/packages/SettingsLib/res/values-or/strings.xml
+++ b/packages/SettingsLib/res/values-or/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"ବୃହତ୍ତମ"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"ବୃହତ୍ତମ"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"କଷ୍ଟମ୍‌ (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"ସହାୟତା ଓ ମତାମତ"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"ମେନୁ"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"ଡେମୋ ମୋଡ୍‌ରେ ଫ୍ୟାକ୍ଟୋରୀ ରିସେଟ୍‌ କରିବାକୁ ପାସ୍‌ୱାର୍ଡ ଲେଖନ୍ତୁ"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"ପରବର୍ତ୍ତୀ"</string>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index 63c88cd..c7ab379 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"ਥੋੜ੍ਹਾ ਵੱਡੀ"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"ਸਭ ਤੋਂ ਵੱਡੀ"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"ਵਿਉਂਂਤੀ (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"ਮਦਦ &amp; ਫੀਡਬੈਕ"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"ਮੀਨੂ"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"ਡੈਮੋ ਮੋਡ \'ਚ ਫੈਕਟਰੀ ਰੀਸੈੱਟ ਲਈ ਪਾਸਵਰਡ ਦਿਓ"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"ਅੱਗੇ"</string>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index 7c3da21..effa59a 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Większy"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Największy"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Niestandardowe (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"Pomoc i opinie"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menu"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Wpisz hasło, by przywrócić ustawienia fabryczne w trybie demonstracyjnym"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Dalej"</string>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index 192e532..afefeda 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -77,7 +77,7 @@
     <string name="bluetooth_profile_pbap_summary" msgid="6605229608108852198">"Usar para compartilhamento de contatos"</string>
     <string name="bluetooth_profile_pan_nap" msgid="8429049285027482959">"Compartilhamento de conexão à Internet"</string>
     <string name="bluetooth_profile_map" msgid="1019763341565580450">"Mensagens de texto"</string>
-    <string name="bluetooth_profile_sap" msgid="5764222021851283125">"Acesso SIM"</string>
+    <string name="bluetooth_profile_sap" msgid="5764222021851283125">"Acesso ao chip"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Áudio HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Áudio HD"</string>
     <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Aparelho auditivo"</string>
@@ -93,7 +93,7 @@
     <string name="bluetooth_pan_nap_profile_summary_connected" msgid="1322694224800769308">"Compartilhamento de conexão local de Internet c/ disposit."</string>
     <string name="bluetooth_pan_profile_summary_use_for" msgid="5736111170225304239">"Usar para acesso à Internet"</string>
     <string name="bluetooth_map_profile_summary_use_for" msgid="5154200119919927434">"Usar para mapa"</string>
-    <string name="bluetooth_sap_profile_summary_use_for" msgid="7085362712786907993">"Use para acesso SIM"</string>
+    <string name="bluetooth_sap_profile_summary_use_for" msgid="7085362712786907993">"Use para acesso ao chip"</string>
     <string name="bluetooth_a2dp_profile_summary_use_for" msgid="4630849022250168427">"Usar para áudio de mídia"</string>
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Usar para áudio do smartphone"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Usado para transferência de arquivo"</string>
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Muito grande"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Maior"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Personalizada (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"Ajuda e feedback"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menu"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Digite a senha para redef. p/ configuração original em modo demo"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Próxima"</string>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index 01bc0fc..4ee4521d 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Maior"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"O maior"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Personalizado (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"Ajuda e comentários"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menu"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Introduzir palavra-passe para efetuar a reposição de fábrica no modo demo"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Próximo"</string>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index 192e532..afefeda 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -77,7 +77,7 @@
     <string name="bluetooth_profile_pbap_summary" msgid="6605229608108852198">"Usar para compartilhamento de contatos"</string>
     <string name="bluetooth_profile_pan_nap" msgid="8429049285027482959">"Compartilhamento de conexão à Internet"</string>
     <string name="bluetooth_profile_map" msgid="1019763341565580450">"Mensagens de texto"</string>
-    <string name="bluetooth_profile_sap" msgid="5764222021851283125">"Acesso SIM"</string>
+    <string name="bluetooth_profile_sap" msgid="5764222021851283125">"Acesso ao chip"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Áudio HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Áudio HD"</string>
     <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Aparelho auditivo"</string>
@@ -93,7 +93,7 @@
     <string name="bluetooth_pan_nap_profile_summary_connected" msgid="1322694224800769308">"Compartilhamento de conexão local de Internet c/ disposit."</string>
     <string name="bluetooth_pan_profile_summary_use_for" msgid="5736111170225304239">"Usar para acesso à Internet"</string>
     <string name="bluetooth_map_profile_summary_use_for" msgid="5154200119919927434">"Usar para mapa"</string>
-    <string name="bluetooth_sap_profile_summary_use_for" msgid="7085362712786907993">"Use para acesso SIM"</string>
+    <string name="bluetooth_sap_profile_summary_use_for" msgid="7085362712786907993">"Use para acesso ao chip"</string>
     <string name="bluetooth_a2dp_profile_summary_use_for" msgid="4630849022250168427">"Usar para áudio de mídia"</string>
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Usar para áudio do smartphone"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Usado para transferência de arquivo"</string>
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Muito grande"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Maior"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Personalizada (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"Ajuda e feedback"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menu"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Digite a senha para redef. p/ configuração original em modo demo"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Próxima"</string>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index cc74bd3..f42363e 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Mai mare"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Cel mai mare"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Personalizat (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"Ajutor și feedback"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Meniu"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Introduceți parola pentru a reveni la setările din fabrică în modul demo"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Înainte"</string>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index 5e1869f..451c710 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Очень крупный"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Максимальный"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Другой (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"Справка/отзыв"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Меню"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Чтобы сбросить настройки в деморежиме, введите пароль."</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Далее"</string>
diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml
index 1be890b..d9e69ce 100644
--- a/packages/SettingsLib/res/values-si/strings.xml
+++ b/packages/SettingsLib/res/values-si/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"වඩා විශාල"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"විශාලතම"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"අභිරුචි (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"උදව් සහ ප්‍රතිපෝෂණ"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"මෙනුව"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"ආදර්ශන ප්‍රකාර කර්මාන්තශාලා යළි සැකසීමට මුරපදය ඇ. ක."</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"ඊළඟ"</string>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index d1ec450..a0c1062 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Väčšie"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Najväčšie"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Vlastné (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"Pomocník a spätná väzba"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Ponuka"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Zadajte heslo na obnovenie továrenských nastavení v režime ukážky"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Ďalej"</string>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index 4632550..3088d0f 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Večje"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Največje"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Po meri (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"Pomoč in povratne informacije"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Meni"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Geslo za tovar. nast. v predstav. načinu"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Naprej"</string>
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index 24cdcb1..8e31013 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Më i madh"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Më i madhi"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"I personalizuar (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"Ndihma dhe komentet"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menyja"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Fut fjalëkalimin për të kryer rivendosje në gjendje fabrike në modalitetin e demonstrimit"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Përpara"</string>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index ebefc65..fe97119 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Већи"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Највећи"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Прилагођени (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"Помоћ и повратне информације"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Мени"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Унесите лозинку да бисте обавили ресетовање на фабричка подешавања у режиму демонстрације"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Даље"</string>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index 040aea6..11f446c 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Större"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Störst"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Anpassad (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"Hjälp och feedback"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Meny"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Ange lösenord och utför fabriksåterställning i demoläge"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Nästa"</string>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index 8be74ea..ba3aaba 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Kubwa kiasi"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Kubwa zaidi"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Kiwango maalum (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"Usaidizi na maoni"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menyu"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Weka nenosiri ili urejeshe mipangilio ya kiwandani ikiwa katika hali ya onyesho."</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Inayofuata"</string>
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index 225005d..63d5e75 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"கொஞ்சம் பெரியது"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"மிகப் பெரியது"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"தனிப்பயன் (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"உதவி &amp; கருத்து"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"மெனு"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"டெமோ பயன்முறையில் ஆரம்பநிலை மீட்டமைவைச் செயல்படுத்த, கடவுச்சொல்லை உள்ளிடவும்"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"அடுத்து"</string>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index 531001c..4af461d0 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"చాలా పెద్దగా"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"అతి పెద్దగా"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"అనుకూలం (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"సహాయం &amp; అభిప్రాయం"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"మెను"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"డెమో మోడ్‌లో ఫ్యాక్టరీ రీసెట్‌ను నిర్వహించడానికి పాస్‌వర్డ్‌ను నమోదు చేయండి"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"తర్వాత"</string>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index cf214e1..9cc5c73 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"ใหญ่ขึ้น"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"ใหญ่ที่สุด"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"กำหนดเอง (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"ความช่วยเหลือและความคิดเห็น"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"เมนู"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"ป้อนรหัสผ่านเพื่อรีเซ็ตค่าในโหมดสาธิต"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"ถัดไป"</string>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index aee95ea..49abe42 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Mas malaki"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Pinakamalaki"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Custom (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"Tulong at feedback"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menu"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Ilagay ang password upang mag-factory reset sa demo mode"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Susunod"</string>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index e4b23f96..23a96d9 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Daha büyük"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"En büyük"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Özel (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"Yardım ve geri bildirim"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menü"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Demo modunda sıfırlamak için şifreyi girin"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Sonraki"</string>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index 958a3d2..cea870a4 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Більші елементи"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Найбільші елементи"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Спеціальний масштаб (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"Довідка й відгуки"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Меню"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Введіть пароль, щоб скинути налаштування в демо-режимі"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Далі"</string>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index 31f0a33..0fb60d9 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"قدرے بڑا"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"سب سے بڑا"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"حسب ضرورت (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"مدد اور تاثرات"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"مینو"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"ڈیمو موڈ میں فیکٹری ری سیٹ کیلئے پاس ورڈ درج کریں"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"اگلا"</string>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index 7ff4588..4690db3 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Kattaroq"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Eng katta"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Moslashtirilgan (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"Yordam va fikr-mulohaza"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menyu"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Demo rejimda zavod holatiga qaytarish uchun parolni kiriting"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Keyingisi"</string>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index daa9335..937b37d 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Lớn hơn"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Lớn nhất"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Tùy chỉnh (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"Trợ giúp và phản hồi"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menu"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Nhập mật khẩu để tiến hành khôi phục cài đặt gốc ở chế độ trình diễn"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Tiếp theo"</string>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index 6cb27e9..47753fd 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"较大"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"最大"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"自定义 (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"帮助和反馈"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"菜单"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"输入密码即可在演示模式下恢复出厂设置"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"下一步"</string>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index 16039c1..4cbf5a6 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"較大"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"最大"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"自訂 (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"說明和意見反映"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"選單"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"輸入密碼即可在示範模式下重設原廠設定"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"下一步"</string>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index ed68638..cecc6ac 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"較大"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"最大"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"自訂 (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"說明與意見回饋"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"選單"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"如要在示範模式中恢復原廠設定,請輸入密碼"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"下一步"</string>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index 957584a..94c3abf 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -415,7 +415,6 @@
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Okukhulu kakhulu"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Okukhulu kakhulu"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Ngokwezifiso (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
-    <string name="help_feedback_label" msgid="6815040660801785649">"Usizo nempendulo"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Imenyu"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Faka iphasiwedi ukuze wenze ukusetha kwefekthri kumodi yedemo"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Okulandelayo"</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/CustomDialogPreference.java b/packages/SettingsLib/src/com/android/settingslib/CustomDialogPreference.java
index 3bade25..192a40c 100644
--- a/packages/SettingsLib/src/com/android/settingslib/CustomDialogPreference.java
+++ b/packages/SettingsLib/src/com/android/settingslib/CustomDialogPreference.java
@@ -26,6 +26,12 @@
 import androidx.preference.DialogPreference;
 import androidx.preference.PreferenceDialogFragment;
 
+/**
+ * Framework version is deprecated, use the compat version instead.
+ *
+ * @deprecated
+ */
+@Deprecated
 public class CustomDialogPreference extends DialogPreference {
 
     private CustomPreferenceDialogFragment mFragment;
diff --git a/packages/SettingsLib/src/com/android/settingslib/CustomEditTextPreference.java b/packages/SettingsLib/src/com/android/settingslib/CustomEditTextPreference.java
index dfaff61..3caa0bb 100644
--- a/packages/SettingsLib/src/com/android/settingslib/CustomEditTextPreference.java
+++ b/packages/SettingsLib/src/com/android/settingslib/CustomEditTextPreference.java
@@ -31,6 +31,12 @@
 import androidx.preference.EditTextPreference;
 import androidx.preference.EditTextPreferenceDialogFragment;
 
+/**
+ * Framework version is deprecated, use the compat version instead.
+ *
+ * @deprecated
+ */
+@Deprecated
 public class CustomEditTextPreference extends EditTextPreference {
 
     private CustomPreferenceDialogFragment mFragment;
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
index 663b1f5..240a192 100644
--- a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
@@ -675,6 +675,7 @@
                 if (!mResumed) {
                     mResumed = true;
                     mSessionsChanged = true;
+                    doPauseLocked();
                     doResumeIfNeededLocked();
                 }
             }
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpSinkProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpSinkProfile.java
index 0c4e02b..e13e566 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpSinkProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpSinkProfile.java
@@ -33,7 +33,6 @@
 
 final class A2dpSinkProfile implements LocalBluetoothProfile {
     private static final String TAG = "A2dpSinkProfile";
-    private static boolean V = true;
 
     private BluetoothA2dpSink mService;
     private boolean mIsProfileReady;
@@ -56,7 +55,7 @@
             implements BluetoothProfile.ServiceListener {
 
         public void onServiceConnected(int profile, BluetoothProfile proxy) {
-            if (V) Log.d(TAG,"Bluetooth service connected");
+            Log.d(TAG, "Bluetooth service connected");
             mService = (BluetoothA2dpSink) proxy;
             // We just bound to the service, so refresh the UI for any connected A2DP devices.
             List<BluetoothDevice> deviceList = mService.getConnectedDevices();
@@ -75,7 +74,7 @@
         }
 
         public void onServiceDisconnected(int profile) {
-            if (V) Log.d(TAG,"Bluetooth service disconnected");
+            Log.d(TAG, "Bluetooth service disconnected");
             mIsProfileReady=false;
         }
     }
@@ -106,7 +105,9 @@
     }
 
     public List<BluetoothDevice> getConnectedDevices() {
-        if (mService == null) return new ArrayList<BluetoothDevice>(0);
+        if (mService == null) {
+            return new ArrayList<BluetoothDevice>(0);
+        }
         return mService.getDevicesMatchingConnectionStates(
               new int[] {BluetoothProfile.STATE_CONNECTED,
                          BluetoothProfile.STATE_CONNECTING,
@@ -114,24 +115,18 @@
     }
 
     public boolean connect(BluetoothDevice device) {
-        if (mService == null) return false;
-        List<BluetoothDevice> srcs = getConnectedDevices();
-        if (srcs != null) {
-            for (BluetoothDevice src : srcs) {
-                if (src.equals(device)) {
-                    // Connect to same device, Ignore it
-                    Log.d(TAG,"Ignoring Connect");
-                    return true;
-                }
-            }
+        if (mService == null) {
+            return false;
         }
         return mService.connect(device);
     }
 
     public boolean disconnect(BluetoothDevice device) {
-        if (mService == null) return false;
+        if (mService == null) {
+            return false;
+        }
         // Downgrade priority as user is disconnecting the headset.
-        if (mService.getPriority(device) > BluetoothProfile.PRIORITY_ON){
+        if (mService.getPriority(device) > BluetoothProfile.PRIORITY_ON) {
             mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
         }
         return mService.disconnect(device);
@@ -145,17 +140,23 @@
     }
 
     public boolean isPreferred(BluetoothDevice device) {
-        if (mService == null) return false;
+        if (mService == null) {
+            return false;
+        }
         return mService.getPriority(device) > BluetoothProfile.PRIORITY_OFF;
     }
 
     public int getPreferred(BluetoothDevice device) {
-        if (mService == null) return BluetoothProfile.PRIORITY_OFF;
+        if (mService == null) {
+            return BluetoothProfile.PRIORITY_OFF;
+        }
         return mService.getPriority(device);
     }
 
     public void setPreferred(BluetoothDevice device, boolean preferred) {
-        if (mService == null) return;
+        if (mService == null) {
+            return;
+        }
         if (preferred) {
             if (mService.getPriority(device) < BluetoothProfile.PRIORITY_ON) {
                 mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
@@ -166,7 +167,9 @@
     }
 
     boolean isA2dpPlaying() {
-        if (mService == null) return false;
+        if (mService == null) {
+            return false;
+        }
         List<BluetoothDevice> srcs = mService.getConnectedDevices();
         if (!srcs.isEmpty()) {
             if (mService.isA2dpPlaying(srcs.get(0))) {
@@ -208,7 +211,7 @@
     }
 
     protected void finalize() {
-        if (V) Log.d(TAG, "finalize()");
+        Log.d(TAG, "finalize()");
         if (mService != null) {
             try {
                 BluetoothAdapter.getDefaultAdapter().closeProfileProxy(BluetoothProfile.A2DP_SINK,
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index 649900b..b9f7323 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -78,12 +78,6 @@
 
     private final static String MESSAGE_REJECTION_COUNT_PREFS_NAME = "bluetooth_message_reject";
 
-    /**
-     * When we connect to multiple profiles, we only want to display a single
-     * error even if they all fail. This tracks that state.
-     */
-    private boolean mIsConnectingErrorPossible;
-
     public long getHiSyncId() {
         return mHiSyncId;
     }
@@ -230,9 +224,6 @@
             return;
         }
 
-        // Reset the only-show-one-error-dialog tracking variable
-        mIsConnectingErrorPossible = true;
-
         int preferredProfiles = 0;
         for (LocalBluetoothProfile profile : mProfiles) {
             if (connectAllProfiles ? profile.isConnectable() : profile.isAutoConnectable()) {
@@ -253,8 +244,6 @@
         if (!ensurePaired()) {
             return;
         }
-        // Reset the only-show-one-error-dialog tracking variable
-        mIsConnectingErrorPossible = true;
 
         for (LocalBluetoothProfile profile : mProfiles) {
             if (profile.isAutoConnectable()) {
@@ -271,8 +260,6 @@
      */
     public void connectProfile(LocalBluetoothProfile profile) {
         mConnectAttempted = SystemClock.elapsedRealtime();
-        // Reset the only-show-one-error-dialog tracking variable
-        mIsConnectingErrorPossible = true;
         connectInt(profile);
         // Refresh the UI based on profile.connect() call
         refresh();
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HfpClientProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HfpClientProfile.java
index f9f6233..4b6a22c 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HfpClientProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HfpClientProfile.java
@@ -36,7 +36,6 @@
  */
 final class HfpClientProfile implements LocalBluetoothProfile {
     private static final String TAG = "HfpClientProfile";
-    private static boolean V = false;
 
     private BluetoothHeadsetClient mService;
     private boolean mIsProfileReady;
@@ -60,7 +59,7 @@
 
         @Override
         public void onServiceConnected(int profile, BluetoothProfile proxy) {
-            if (V) Log.d(TAG,"Bluetooth service connected");
+            Log.d(TAG, "Bluetooth service connected");
             mService = (BluetoothHeadsetClient) proxy;
             // We just bound to the service, so refresh the UI for any connected HFP devices.
             List<BluetoothDevice> deviceList = mService.getConnectedDevices();
@@ -81,7 +80,7 @@
 
         @Override
         public void onServiceDisconnected(int profile) {
-            if (V) Log.d(TAG,"Bluetooth service disconnected");
+            Log.d(TAG, "Bluetooth service disconnected");
             mIsProfileReady=false;
         }
     }
@@ -115,7 +114,9 @@
     }
 
     public List<BluetoothDevice> getConnectedDevices() {
-        if (mService == null) return new ArrayList<BluetoothDevice>(0);
+        if (mService == null) {
+            return new ArrayList<BluetoothDevice>(0);
+        }
         return mService.getDevicesMatchingConnectionStates(
               new int[] {BluetoothProfile.STATE_CONNECTED,
                          BluetoothProfile.STATE_CONNECTING,
@@ -124,23 +125,17 @@
 
     @Override
     public boolean connect(BluetoothDevice device) {
-        if (mService == null) return false;
-        List<BluetoothDevice> srcs = getConnectedDevices();
-        if (srcs != null) {
-            for (BluetoothDevice src : srcs) {
-                if (src.equals(device)) {
-                    // Connect to same device, Ignore it
-                    Log.d(TAG,"Ignoring Connect");
-                    return true;
-                }
-            }
+        if (mService == null) {
+            return false;
         }
         return mService.connect(device);
     }
 
     @Override
     public boolean disconnect(BluetoothDevice device) {
-        if (mService == null) return false;
+        if (mService == null) {
+            return false;
+        }
         // Downgrade priority as user is disconnecting the headset.
         if (mService.getPriority(device) > BluetoothProfile.PRIORITY_ON){
             mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
@@ -158,19 +153,25 @@
 
     @Override
     public boolean isPreferred(BluetoothDevice device) {
-        if (mService == null) return false;
+        if (mService == null) {
+            return false;
+        }
         return mService.getPriority(device) > BluetoothProfile.PRIORITY_OFF;
     }
 
     @Override
     public int getPreferred(BluetoothDevice device) {
-        if (mService == null) return BluetoothProfile.PRIORITY_OFF;
+        if (mService == null) {
+            return BluetoothProfile.PRIORITY_OFF;
+        }
         return mService.getPriority(device);
     }
 
     @Override
     public void setPreferred(BluetoothDevice device, boolean preferred) {
-        if (mService == null) return;
+        if (mService == null) {
+            return;
+        }
         if (preferred) {
             if (mService.getPriority(device) < BluetoothProfile.PRIORITY_ON) {
                 mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
@@ -216,7 +217,7 @@
     }
 
     protected void finalize() {
-        if (V) Log.d(TAG, "finalize()");
+        Log.d(TAG, "finalize()");
         if (mService != null) {
             try {
                 BluetoothAdapter.getDefaultAdapter().closeProfileProxy(
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
index 36d209e..7000f9d 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
@@ -97,8 +97,6 @@
     private PanProfile mPanProfile;
     private PbapClientProfile mPbapClientProfile;
     private PbapServerProfile mPbapProfile;
-    private final boolean mUsePbapPce;
-    private final boolean mUseMapClient;
     private HearingAidProfile mHearingAidProfile;
 
     /**
@@ -115,9 +113,6 @@
 
         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)
         adapter.setProfileManager(this);
 
@@ -130,17 +125,17 @@
     void updateLocalProfiles() {
         List<Integer> supportedList = BluetoothAdapter.getDefaultAdapter().getSupportedProfiles();
         if (CollectionUtils.isEmpty(supportedList)) {
-            if(DEBUG) Log.d(TAG, "supportedList is null");
+            if (DEBUG) Log.d(TAG, "supportedList is null");
             return;
         }
         if (mA2dpProfile == null && supportedList.contains(BluetoothProfile.A2DP)) {
-            if(DEBUG) Log.d(TAG, "Adding local A2DP profile");
+            if (DEBUG) Log.d(TAG, "Adding local A2DP profile");
             mA2dpProfile = new A2dpProfile(mContext, mDeviceManager, this);
             addProfile(mA2dpProfile, A2dpProfile.NAME,
                     BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED);
         }
         if (mA2dpSinkProfile == null && supportedList.contains(BluetoothProfile.A2DP_SINK)) {
-            if(DEBUG) Log.d(TAG, "Adding local A2DP SINK profile");
+            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);
@@ -154,66 +149,63 @@
                     BluetoothHeadset.STATE_AUDIO_DISCONNECTED);
         }
         if (mHfpClientProfile == null && supportedList.contains(BluetoothProfile.HEADSET_CLIENT)) {
-            if(DEBUG) Log.d(TAG, "Adding local HfpClient profile");
+            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, mDeviceManager,this);
-                addProfile(mMapClientProfile, MapClientProfile.NAME,
-                        BluetoothMapClient.ACTION_CONNECTION_STATE_CHANGED);
-            }
-        } else if (mMapProfile == null && supportedList.contains(BluetoothProfile.MAP)) {
-            if(DEBUG) Log.d(TAG, "Adding local MAP profile");
+        if (mMapClientProfile == null && supportedList.contains(BluetoothProfile.MAP_CLIENT)) {
+            if (DEBUG) Log.d(TAG, "Adding local MAP CLIENT profile");
+            mMapClientProfile = new MapClientProfile(mContext, mDeviceManager,this);
+            addProfile(mMapClientProfile, MapClientProfile.NAME,
+                    BluetoothMapClient.ACTION_CONNECTION_STATE_CHANGED);
+        }
+        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);
         }
         if (mOppProfile == null && supportedList.contains(BluetoothProfile.OPP)) {
-            if(DEBUG) Log.d(TAG, "Adding local OPP profile");
+            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);
         }
         if (mHearingAidProfile == null && supportedList.contains(BluetoothProfile.HEARING_AID)) {
-            if(DEBUG) Log.d(TAG, "Adding local Hearing Aid profile");
+            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);
         }
         if (mHidProfile == null && supportedList.contains(BluetoothProfile.HID_HOST)) {
-            if(DEBUG) Log.d(TAG, "Adding local HID_HOST profile");
+            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");
+            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");
+            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");
+            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");
+        if (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);
@@ -544,7 +536,9 @@
             removedProfiles.remove(mMapClientProfile);
         }
 
-        if (mUsePbapPce) {
+        if ((mPbapClientProfile != null) &&
+                BluetoothUuid.isUuidPresent(localUuids, BluetoothUuid.PBAP_PCE) &&
+                BluetoothUuid.containsAnyUuid(uuids, PbapClientProfile.SRC_UUIDS)) {
             profiles.add(mPbapClientProfile);
             removedProfiles.remove(mPbapClientProfile);
         }
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/MapProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/MapProfile.java
index 689669f..caea04f 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/MapProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/MapProfile.java
@@ -32,11 +32,10 @@
 import java.util.List;
 
 /**
- * MapProfile handles Bluetooth MAP profile.
+ * MapProfile handles the Bluetooth MAP MSE role
  */
 public class MapProfile implements LocalBluetoothProfile {
     private static final String TAG = "MapProfile";
-    private static boolean V = true;
 
     private BluetoothMap mService;
     private boolean mIsProfileReady;
@@ -59,7 +58,7 @@
             implements BluetoothProfile.ServiceListener {
 
         public void onServiceConnected(int profile, BluetoothProfile proxy) {
-            if (V) Log.d(TAG,"Bluetooth service connected");
+            Log.d(TAG, "Bluetooth service connected");
             mService = (BluetoothMap) proxy;
             // We just bound to the service, so refresh the UI for any connected MAP devices.
             List<BluetoothDevice> deviceList = mService.getConnectedDevices();
@@ -81,14 +80,14 @@
         }
 
         public void onServiceDisconnected(int profile) {
-            if (V) Log.d(TAG,"Bluetooth service disconnected");
+            Log.d(TAG, "Bluetooth service disconnected");
             mProfileManager.callServiceDisconnectedListeners();
             mIsProfileReady=false;
         }
     }
 
     public boolean isProfileReady() {
-        if(V) Log.d(TAG,"isProfileReady(): "+ mIsProfileReady);
+        Log.d(TAG, "isProfileReady(): " + mIsProfileReady);
         return mIsProfileReady;
     }
 
@@ -114,45 +113,45 @@
     }
 
     public boolean connect(BluetoothDevice device) {
-        if(V)Log.d(TAG,"connect() - should not get called");
+        Log.d(TAG, "connect() - should not get called");
         return false; // MAP never connects out
     }
 
     public boolean disconnect(BluetoothDevice device) {
-        if (mService == null) return false;
-        List<BluetoothDevice> deviceList = mService.getConnectedDevices();
-        if (!deviceList.isEmpty() && deviceList.get(0).equals(device)) {
-            if (mService.getPriority(device) > BluetoothProfile.PRIORITY_ON) {
-                mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
-            }
-            return mService.disconnect(device);
-        } else {
+        if (mService == null) {
             return false;
         }
+        if (mService.getPriority(device) > BluetoothProfile.PRIORITY_ON) {
+            mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+        }
+        return mService.disconnect(device);
     }
 
     public int getConnectionStatus(BluetoothDevice device) {
-        if (mService == null) return BluetoothProfile.STATE_DISCONNECTED;
-        List<BluetoothDevice> deviceList = mService.getConnectedDevices();
-        if(V) Log.d(TAG,"getConnectionStatus: status is: "+ mService.getConnectionState(device));
-
-        return !deviceList.isEmpty() && deviceList.get(0).equals(device)
-                ? mService.getConnectionState(device)
-                : BluetoothProfile.STATE_DISCONNECTED;
+        if (mService == null) {
+            return BluetoothProfile.STATE_DISCONNECTED;
+        }
+        return mService.getConnectionState(device);
     }
 
     public boolean isPreferred(BluetoothDevice device) {
-        if (mService == null) return false;
+        if (mService == null) {
+            return false;
+        }
         return mService.getPriority(device) > BluetoothProfile.PRIORITY_OFF;
     }
 
     public int getPreferred(BluetoothDevice device) {
-        if (mService == null) return BluetoothProfile.PRIORITY_OFF;
+        if (mService == null) {
+            return BluetoothProfile.PRIORITY_OFF;
+        }
         return mService.getPriority(device);
     }
 
     public void setPreferred(BluetoothDevice device, boolean preferred) {
-        if (mService == null) return;
+        if (mService == null) {
+            return;
+        }
         if (preferred) {
             if (mService.getPriority(device) < BluetoothProfile.PRIORITY_ON) {
                 mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
@@ -163,7 +162,9 @@
     }
 
     public List<BluetoothDevice> getConnectedDevices() {
-        if (mService == null) return new ArrayList<BluetoothDevice>(0);
+        if (mService == null) {
+            return new ArrayList<BluetoothDevice>(0);
+        }
         return mService.getDevicesMatchingConnectionStates(
               new int[] {BluetoothProfile.STATE_CONNECTED,
                          BluetoothProfile.STATE_CONNECTING,
@@ -201,7 +202,7 @@
     }
 
     protected void finalize() {
-        if (V) Log.d(TAG, "finalize()");
+        Log.d(TAG, "finalize()");
         if (mService != null) {
             try {
                 BluetoothAdapter.getDefaultAdapter().closeProfileProxy(BluetoothProfile.MAP,
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawable/UserIconDrawable.java b/packages/SettingsLib/src/com/android/settingslib/drawable/UserIconDrawable.java
index 2213db8..274696b 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawable/UserIconDrawable.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawable/UserIconDrawable.java
@@ -172,11 +172,13 @@
 
     public UserIconDrawable setBadgeIfManagedUser(Context context, int userId) {
         Drawable badge = null;
-        boolean isManaged = context.getSystemService(DevicePolicyManager.class)
-                .getProfileOwnerAsUser(userId) != null;
-        if (isManaged) {
-            badge = getDrawableForDisplayDensity(
-                    context, com.android.internal.R.drawable.ic_corp_badge_case);
+        if (userId != UserHandle.USER_NULL) {
+            boolean isManaged = context.getSystemService(DevicePolicyManager.class)
+                    .getProfileOwnerAsUser(userId) != null;
+            if (isManaged) {
+                badge = getDrawableForDisplayDensity(
+                        context, com.android.internal.R.drawable.ic_corp_badge_case);
+            }
         }
         return setBadge(badge);
     }
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/ChartDataLoader.java b/packages/SettingsLib/src/com/android/settingslib/net/ChartDataLoader.java
index 223c055..60d22a0 100644
--- a/packages/SettingsLib/src/com/android/settingslib/net/ChartDataLoader.java
+++ b/packages/SettingsLib/src/com/android/settingslib/net/ChartDataLoader.java
@@ -34,8 +34,11 @@
 import com.android.settingslib.AppItem;
 
 /**
- * Loader for historical chart data for both network and UID details.
+ * Framework loader is deprecated, use the compat version instead.
+ *
+ * @deprecated
  */
+@Deprecated
 public class ChartDataLoader extends AsyncTaskLoader<ChartData> {
     private static final String KEY_TEMPLATE = "template";
     private static final String KEY_APP = "app";
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/SummaryForAllUidLoader.java b/packages/SettingsLib/src/com/android/settingslib/net/SummaryForAllUidLoader.java
index 572bae1..649aeff 100644
--- a/packages/SettingsLib/src/com/android/settingslib/net/SummaryForAllUidLoader.java
+++ b/packages/SettingsLib/src/com/android/settingslib/net/SummaryForAllUidLoader.java
@@ -24,6 +24,12 @@
 import android.os.Bundle;
 import android.os.RemoteException;
 
+/**
+ * Framework loader is deprecated, use the compat version instead.
+ *
+ * @deprecated
+ */
+@Deprecated
 public class SummaryForAllUidLoader extends AsyncTaskLoader<NetworkStats> {
     private static final String KEY_TEMPLATE = "template";
     private static final String KEY_START = "start";
diff --git a/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionControllerMixin.java b/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionControllerMixin.java
index 6597daa..b0e987e 100644
--- a/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionControllerMixin.java
+++ b/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionControllerMixin.java
@@ -32,8 +32,11 @@
 import java.util.List;
 
 /**
- * Manages IPC communication to SettingsIntelligence for suggestion related services.
+ * Framework mixin is deprecated, use the compat version instead.
+ *
+ * @deprecated
  */
+@Deprecated
 public class SuggestionControllerMixin implements SuggestionController.ServiceConnectionListener,
         androidx.lifecycle.LifecycleObserver, LoaderManager.LoaderCallbacks<List<Suggestion>> {
 
@@ -65,7 +68,7 @@
         mContext = context.getApplicationContext();
         mHost = host;
         mSuggestionController = new SuggestionController(mContext, componentName,
-                    this /* serviceConnectionListener */);
+                this /* serviceConnectionListener */);
         if (lifecycle != null) {
             lifecycle.addObserver(this);
         }
diff --git a/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionLoader.java b/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionLoader.java
index 9c1af1e..8011424 100644
--- a/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionLoader.java
+++ b/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionLoader.java
@@ -24,6 +24,12 @@
 
 import java.util.List;
 
+/**
+ * Framework loader is deprecated, use the compat version instead.
+ *
+ * @deprecated
+ */
+@Deprecated
 public class SuggestionLoader extends AsyncLoader<List<Suggestion>> {
 
     public static final int LOADER_ID_SUGGESTIONS = 42;
diff --git a/packages/SettingsLib/src/com/android/settingslib/utils/AsyncLoader.java b/packages/SettingsLib/src/com/android/settingslib/utils/AsyncLoader.java
index 06770ac..64b9ffe 100644
--- a/packages/SettingsLib/src/com/android/settingslib/utils/AsyncLoader.java
+++ b/packages/SettingsLib/src/com/android/settingslib/utils/AsyncLoader.java
@@ -29,7 +29,9 @@
  * This loader is based on the MailAsyncTaskLoader from the AOSP EmailUnified repo.
  *
  * @param <T> the data type to be loaded.
+ * @deprecated Framework loader is deprecated, use the compat version instead.
  */
+@Deprecated
 public abstract class AsyncLoader<T> extends AsyncTaskLoader<T> {
     private T mResult;
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/utils/StringUtil.java b/packages/SettingsLib/src/com/android/settingslib/utils/StringUtil.java
index 88be2b0..3e3c039 100644
--- a/packages/SettingsLib/src/com/android/settingslib/utils/StringUtil.java
+++ b/packages/SettingsLib/src/com/android/settingslib/utils/StringUtil.java
@@ -27,7 +27,6 @@
 import android.text.SpannableStringBuilder;
 import android.text.Spanned;
 import android.text.style.TtsSpan;
-import android.util.Log;
 
 import com.android.settingslib.R;
 
@@ -37,8 +36,6 @@
 /** Utility class for generally useful string methods **/
 public class StringUtil {
 
-    private static final String TAG = "StringUtil";
-
     public static final int SECONDS_PER_MINUTE = 60;
     public static final int SECONDS_PER_HOUR = 60 * 60;
     public static final int SECONDS_PER_DAY = 24 * 60 * 60;
@@ -97,7 +94,6 @@
         final Locale locale = context.getResources().getConfiguration().locale;
         final MeasureFormat measureFormat = MeasureFormat.getInstance(
                 locale, FormatWidth.SHORT);
-        Log.i(TAG, "Locale is: " + locale);
         sb.append(measureFormat.formatMeasures(measureArray));
 
         if (measureArray.length == 1 && MeasureUnit.MINUTE.equals(measureArray[0].getUnit())) {
@@ -150,7 +146,6 @@
                 null /* default NumberFormat */,
                 RelativeDateTimeFormatter.Style.LONG,
                 android.icu.text.DisplayContext.CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE);
-        Log.i(TAG, "Locale is: " + locale);
 
         return formatter.format(value, RelativeDateTimeFormatter.Direction.LAST, unit);
     }
diff --git a/packages/SettingsLib/src/com/android/settingslib/widget/FooterPreferenceMixin.java b/packages/SettingsLib/src/com/android/settingslib/widget/FooterPreferenceMixin.java
index 2987c15..fcf2363 100644
--- a/packages/SettingsLib/src/com/android/settingslib/widget/FooterPreferenceMixin.java
+++ b/packages/SettingsLib/src/com/android/settingslib/widget/FooterPreferenceMixin.java
@@ -25,6 +25,12 @@
 import com.android.settingslib.core.lifecycle.LifecycleObserver;
 import com.android.settingslib.core.lifecycle.events.SetPreferenceScreen;
 
+/**
+ * Framework mixin is deprecated, use the compat version instead.
+ *
+ * @deprecated
+ */
+@Deprecated
 public class FooterPreferenceMixin implements LifecycleObserver, SetPreferenceScreen {
 
     private final PreferenceFragment mFragment;
diff --git a/packages/SettingsLib/tests/robotests/config/robolectric.properties b/packages/SettingsLib/tests/robotests/config/robolectric.properties
index 34a2a1a..6b5b8e5 100644
--- a/packages/SettingsLib/tests/robotests/config/robolectric.properties
+++ b/packages/SettingsLib/tests/robotests/config/robolectric.properties
@@ -1,2 +1,5 @@
 manifest=frameworks/base/packages/SettingsLib/tests/robotests/AndroidManifest.xml
-sdk=NEWEST_SDK
\ No newline at end of file
+sdk=NEWEST_SDK
+
+shadows=\
+   com.android.settingslib.testutils.shadow.ShadowXmlUtils
\ No newline at end of file
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpSinkProfileTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpSinkProfileTest.java
new file mode 100644
index 0000000..274fff8
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpSinkProfileTest.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.settingslib.bluetooth;
+
+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.when;
+import static org.mockito.Mockito.verify;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothA2dpSink;
+import android.bluetooth.BluetoothProfile;
+
+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.annotation.Config;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.shadow.api.Shadow;
+
+@RunWith(SettingsLibRobolectricTestRunner.class)
+@Config(shadows = {ShadowBluetoothAdapter.class})
+public class A2dpSinkProfileTest {
+
+    @Mock
+    private CachedBluetoothDeviceManager mDeviceManager;
+    @Mock
+    private LocalBluetoothProfileManager mProfileManager;
+    @Mock
+    private BluetoothA2dpSink mService;
+    @Mock
+    private CachedBluetoothDevice mCachedBluetoothDevice;
+    @Mock
+    private BluetoothDevice mBluetoothDevice;
+    private BluetoothProfile.ServiceListener mServiceListener;
+    private A2dpSinkProfile mProfile;
+    private ShadowBluetoothAdapter mShadowBluetoothAdapter;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mShadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter());
+        mProfile = new A2dpSinkProfile(RuntimeEnvironment.application,
+                mDeviceManager, mProfileManager);
+        mServiceListener = mShadowBluetoothAdapter.getServiceListener();
+        mServiceListener.onServiceConnected(BluetoothProfile.A2DP_SINK, mService);
+    }
+
+    @Test
+    public void connect_shouldConnectBluetoothA2dpSink() {
+        mProfile.connect(mBluetoothDevice);
+        verify(mService).connect(mBluetoothDevice);
+    }
+
+    @Test
+    public void disconnect_shouldDisconnectBluetoothA2dpSink() {
+        mProfile.disconnect(mBluetoothDevice);
+        verify(mService).disconnect(mBluetoothDevice);
+    }
+
+    @Test
+    public void getConnectionStatus_shouldReturnConnectionState() {
+        when(mService.getConnectionState(mBluetoothDevice)).
+                thenReturn(BluetoothProfile.STATE_CONNECTED);
+        assertThat(mProfile.getConnectionStatus(mBluetoothDevice)).
+                isEqualTo(BluetoothProfile.STATE_CONNECTED);
+    }
+}
\ No newline at end of file
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HfpClientProfileTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HfpClientProfileTest.java
new file mode 100644
index 0000000..187be0b
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HfpClientProfileTest.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.settingslib.bluetooth;
+
+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.when;
+import static org.mockito.Mockito.verify;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothHeadsetClient;
+import android.bluetooth.BluetoothProfile;
+
+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.annotation.Config;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.shadow.api.Shadow;
+
+@RunWith(SettingsLibRobolectricTestRunner.class)
+@Config(shadows = {ShadowBluetoothAdapter.class})
+public class HfpClientProfileTest {
+
+    @Mock
+    private CachedBluetoothDeviceManager mDeviceManager;
+    @Mock
+    private LocalBluetoothProfileManager mProfileManager;
+    @Mock
+    private BluetoothHeadsetClient mService;
+    @Mock
+    private CachedBluetoothDevice mCachedBluetoothDevice;
+    @Mock
+    private BluetoothDevice mBluetoothDevice;
+    private BluetoothProfile.ServiceListener mServiceListener;
+    private HfpClientProfile mProfile;
+    private ShadowBluetoothAdapter mShadowBluetoothAdapter;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mShadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter());
+        mProfile = new HfpClientProfile(RuntimeEnvironment.application,
+                mDeviceManager, mProfileManager);
+        mServiceListener = mShadowBluetoothAdapter.getServiceListener();
+        mServiceListener.onServiceConnected(BluetoothProfile.HEADSET_CLIENT, mService);
+    }
+
+    @Test
+    public void connect_shouldConnectBluetoothHeadsetClient() {
+        mProfile.connect(mBluetoothDevice);
+        verify(mService).connect(mBluetoothDevice);
+    }
+
+    @Test
+    public void disconnect_shouldDisconnectBluetoothHeadsetClient() {
+        mProfile.disconnect(mBluetoothDevice);
+        verify(mService).disconnect(mBluetoothDevice);
+    }
+
+    @Test
+    public void getConnectionStatus_shouldReturnConnectionState() {
+        when(mService.getConnectionState(mBluetoothDevice)).
+                thenReturn(BluetoothProfile.STATE_CONNECTED);
+        assertThat(mProfile.getConnectionStatus(mBluetoothDevice)).
+                isEqualTo(BluetoothProfile.STATE_CONNECTED);
+    }
+}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/testutils/shadow/ShadowXmlUtils.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/testutils/shadow/ShadowXmlUtils.java
new file mode 100644
index 0000000..3455765
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/testutils/shadow/ShadowXmlUtils.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.settingslib.testutils.shadow;
+
+import static org.robolectric.shadow.api.Shadow.directlyOn;
+
+import com.android.internal.util.XmlUtils;
+
+import org.robolectric.Robolectric;
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+import org.robolectric.util.ReflectionHelpers;
+
+@Implements(XmlUtils.class)
+public class ShadowXmlUtils {
+
+    @Implementation
+    public static final int convertValueToInt(CharSequence charSeq, int defaultValue) {
+        final Class<?> xmlUtilsClass = ReflectionHelpers.loadClass(
+                Robolectric.class.getClassLoader(), "com.android.internal.util.XmlUtils");
+        try {
+            return directlyOn(xmlUtilsClass, "convertValueToInt",
+                    ReflectionHelpers.ClassParameter.from(CharSequence.class, charSeq),
+                    ReflectionHelpers.ClassParameter.from(int.class, new Integer(defaultValue)));
+        } catch (NumberFormatException e) {
+            return defaultValue;
+        }
+    }
+}
\ No newline at end of file
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/GenerationRegistry.java b/packages/SettingsProvider/src/com/android/providers/settings/GenerationRegistry.java
index 3e6c3f2..044ec86 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/GenerationRegistry.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/GenerationRegistry.java
@@ -111,6 +111,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     private MemoryIntArray getBackingStoreLocked() {
         if (mBackingStore == null) {
             // One for the global table, two for system and secure tables for a
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index c6ea480..bd21b83 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -1617,6 +1617,12 @@
         dumpSetting(s, p,
                 Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES,
                 SecureSettingsProto.Accessibility.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES);
+        dumpSetting(s, p,
+                Settings.Secure.ACCESSIBILITY_MINIMUM_UI_TIMEOUT_ENABLED,
+                SecureSettingsProto.Accessibility.MINIMUM_UI_TIMEOUT_ENABLED);
+        dumpSetting(s, p,
+                Settings.Secure.ACCESSIBILITY_MINIMUM_UI_TIMEOUT_MS,
+                SecureSettingsProto.Accessibility.MINIMUM_UI_TIMEOUT_MS);
         p.end(accessibilityToken);
 
         dumpSetting(s, p,
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 500199f..290a4f8 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -722,6 +722,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     private void dumpForUserLocked(int userId, PrintWriter pw) {
         if (userId == UserHandle.USER_SYSTEM) {
             pw.println("GLOBAL SETTINGS (user " + userId + ")");
@@ -1179,6 +1180,7 @@
                 && UserHandle.getAppId(Binder.getCallingUid()) >= Process.FIRST_APPLICATION_UID;
     }
 
+    @GuardedBy("mLock")
     private Setting getSsaidSettingLocked(PackageInfo callingPkg, int owningUserId) {
         // Get uid of caller (key) used to store ssaid value
         String name = Integer.toString(
@@ -1709,6 +1711,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     private List<String> getSettingsNamesLocked(int settingsType, int userId) {
         // Don't enforce the instant app whitelist for now -- its too prone to unintended breakage
         // in the current form.
@@ -1801,6 +1804,7 @@
      *
      * @returns whether the enabled location providers changed.
      */
+    @GuardedBy("mLock")
     private boolean updateLocationProvidersAllowedLocked(String value, String tag,
             int owningUserId, boolean makeDefault, boolean forceNotify) {
         if (TextUtils.isEmpty(value)) {
@@ -2718,6 +2722,7 @@
             }
         }
 
+        @GuardedBy("secureSettings.mLock")
         private void ensureSecureSettingAndroidIdSetLocked(SettingsState secureSettings) {
             Setting value = secureSettings.getSettingLocked(Settings.Secure.ANDROID_ID);
 
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
index e57483a..389d627 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
@@ -274,6 +274,7 @@
     }
 
     // The settings provider must hold its lock when calling here.
+    @GuardedBy("mLock")
     public int getVersionLocked() {
         return mVersion;
     }
@@ -283,6 +284,7 @@
     }
 
     // The settings provider must hold its lock when calling here.
+    @GuardedBy("mLock")
     public void setVersionLocked(int version) {
         if (version == mVersion) {
             return;
@@ -293,6 +295,7 @@
     }
 
     // The settings provider must hold its lock when calling here.
+    @GuardedBy("mLock")
     public void removeSettingsForPackageLocked(String packageName) {
         boolean removedSomething = false;
 
@@ -317,6 +320,7 @@
     }
 
     // The settings provider must hold its lock when calling here.
+    @GuardedBy("mLock")
     public List<String> getSettingNamesLocked() {
         ArrayList<String> names = new ArrayList<>();
         final int settingsCount = mSettings.size();
@@ -328,6 +332,7 @@
     }
 
     // The settings provider must hold its lock when calling here.
+    @GuardedBy("mLock")
     public Setting getSettingLocked(String name) {
         if (TextUtils.isEmpty(name)) {
             return mNullSetting;
@@ -350,6 +355,7 @@
     }
 
     // The settings provider must hold its lock when calling here.
+    @GuardedBy("mLock")
     public void resetSettingDefaultValueLocked(String name) {
         Setting oldSetting = getSettingLocked(name);
         if (oldSetting != null && !oldSetting.isNull() && oldSetting.getDefaultValue() != null) {
@@ -366,6 +372,7 @@
     }
 
     // The settings provider must hold its lock when calling here.
+    @GuardedBy("mLock")
     public boolean insertSettingLocked(String name, String value, String tag,
             boolean makeDefault, String packageName) {
         if (TextUtils.isEmpty(name)) {
@@ -407,6 +414,7 @@
     }
 
     // The settings provider must hold its lock when calling here.
+    @GuardedBy("mLock")
     public boolean deleteSettingLocked(String name) {
         if (TextUtils.isEmpty(name) || !hasSettingLocked(name)) {
             return false;
@@ -429,6 +437,7 @@
     }
 
     // The settings provider must hold its lock when calling here.
+    @GuardedBy("mLock")
     public boolean resetSettingLocked(String name) {
         if (TextUtils.isEmpty(name) || !hasSettingLocked(name)) {
             return false;
@@ -458,6 +467,7 @@
     }
 
     // The settings provider must hold its lock when calling here.
+    @GuardedBy("mLock")
     public void destroyLocked(Runnable callback) {
         mHandler.removeMessages(MyHandler.MSG_PERSIST_SETTINGS);
         if (callback != null) {
@@ -471,6 +481,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     private void addHistoricalOperationLocked(String type, Setting setting) {
         if (mHistoricalOperations == null) {
             return;
@@ -553,6 +564,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     private void updateMemoryUsagePerPackageLocked(String packageName, String oldValue,
             String newValue, String oldDefaultValue, String newDefaultValue) {
         if (mMaxBytesPerAppPackage == MAX_BYTES_PER_APP_PACKAGE_UNLIMITED) {
@@ -588,10 +600,12 @@
         mPackageToMemoryUsage.put(packageName, newSize);
     }
 
+    @GuardedBy("mLock")
     private boolean hasSettingLocked(String name) {
         return mSettings.indexOfKey(name) >= 0;
     }
 
+    @GuardedBy("mLock")
     private void scheduleWriteIfNeededLocked() {
         // If dirty then we have a write already scheduled.
         if (!mDirty) {
@@ -600,6 +614,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     private void writeStateAsyncLocked() {
         final long currentTimeMillis = SystemClock.uptimeMillis();
 
@@ -771,6 +786,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     private void readStateSyncLocked() {
         FileInputStream in;
         try {
@@ -820,6 +836,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     private void parseSettingsLocked(XmlPullParser parser)
             throws IOException, XmlPullParserException {
 
diff --git a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsProviderTest.java b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsProviderTest.java
index b6f51bc..95569dc 100644
--- a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsProviderTest.java
+++ b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsProviderTest.java
@@ -613,7 +613,7 @@
             final String name, final String value, final int userId) throws Exception {
         ContentResolver contentResolver = getContext().getContentResolver();
 
-        final Uri settingUri = getBaseUriForType(type);
+        final Uri settingUri = getBaseUriForType(type).buildUpon().appendPath(name).build();
 
         final AtomicBoolean success = new AtomicBoolean();
 
@@ -640,20 +640,22 @@
 
             final long startTimeMillis = SystemClock.uptimeMillis();
             synchronized (mLock) {
-                if (success.get()) {
-                    return;
-                }
-                final long elapsedTimeMillis = SystemClock.uptimeMillis() - startTimeMillis;
-                if (elapsedTimeMillis > WAIT_FOR_SETTING_URI_CHANGE_TIMEOUT_MILLIS) {
-                    fail("Could not change setting for "
-                            + WAIT_FOR_SETTING_URI_CHANGE_TIMEOUT_MILLIS + " ms");
-                }
-                final long remainingTimeMillis = WAIT_FOR_SETTING_URI_CHANGE_TIMEOUT_MILLIS
-                        - elapsedTimeMillis;
-                try {
-                    mLock.wait(remainingTimeMillis);
-                } catch (InterruptedException ie) {
-                    /* ignore */
+                while (true) {
+                    if (success.get()) {
+                        return;
+                    }
+                    final long elapsedTimeMillis = SystemClock.uptimeMillis() - startTimeMillis;
+                    if (elapsedTimeMillis > WAIT_FOR_SETTING_URI_CHANGE_TIMEOUT_MILLIS) {
+                        fail("Could not change setting for "
+                                + WAIT_FOR_SETTING_URI_CHANGE_TIMEOUT_MILLIS + " ms");
+                    }
+                    final long remainingTimeMillis = WAIT_FOR_SETTING_URI_CHANGE_TIMEOUT_MILLIS
+                            - elapsedTimeMillis;
+                    try {
+                        mLock.wait(remainingTimeMillis);
+                    } catch (InterruptedException ie) {
+                        /* ignore */
+                    }
                 }
             }
         } finally {
@@ -689,39 +691,50 @@
     }
 
     @Test
-    public void testUpdateLocationProvidersAllowedLocked_enableProviders() throws Exception {
-        setSettingViaFrontEndApiAndAssertSuccessfulChange(
+    public void testLocationModeChanges_viaFrontEndApi() throws Exception {
+        setStringViaFrontEndApiSetting(
                 SETTING_TYPE_SECURE,
                 Settings.Secure.LOCATION_MODE,
                 String.valueOf(Settings.Secure.LOCATION_MODE_OFF),
                 UserHandle.USER_SYSTEM);
-
-        // Enable one provider
-        updateStringViaProviderApiSetting(
-                SETTING_TYPE_SECURE, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "+gps");
-
         assertEquals(
                 "Wrong location providers",
-                "gps",
-                queryStringViaProviderApi(
-                        SETTING_TYPE_SECURE, Settings.Secure.LOCATION_PROVIDERS_ALLOWED));
+                "",
+                getStringViaFrontEndApiSetting(
+                        SETTING_TYPE_SECURE,
+                        Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
+                        UserHandle.USER_SYSTEM));
 
-        // Enable a list of providers, including the one that is already enabled
-        updateStringViaProviderApiSetting(
+        setStringViaFrontEndApiSetting(
                 SETTING_TYPE_SECURE,
-                Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
-                "+gps,+network,+network");
+                Settings.Secure.LOCATION_MODE,
+                String.valueOf(Settings.Secure.LOCATION_MODE_BATTERY_SAVING),
+                UserHandle.USER_SYSTEM);
+        assertEquals(
+                "Wrong location providers",
+                "network",
+                getStringViaFrontEndApiSetting(
+                        SETTING_TYPE_SECURE,
+                        Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
+                        UserHandle.USER_SYSTEM));
 
+        setStringViaFrontEndApiSetting(
+                SETTING_TYPE_SECURE,
+                Settings.Secure.LOCATION_MODE,
+                String.valueOf(Settings.Secure.LOCATION_MODE_HIGH_ACCURACY),
+                UserHandle.USER_SYSTEM);
         assertEquals(
                 "Wrong location providers",
                 "gps,network",
-                queryStringViaProviderApi(
-                        SETTING_TYPE_SECURE, Settings.Secure.LOCATION_PROVIDERS_ALLOWED));
+                getStringViaFrontEndApiSetting(
+                        SETTING_TYPE_SECURE,
+                        Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
+                        UserHandle.USER_SYSTEM));
     }
 
     @Test
-    public void testUpdateLocationProvidersAllowedLocked_disableProviders() throws Exception {
-        setSettingViaFrontEndApiAndAssertSuccessfulChange(
+    public void testLocationProvidersAllowed_disableProviders() throws Exception {
+        setStringViaFrontEndApiSetting(
                 SETTING_TYPE_SECURE,
                 Settings.Secure.LOCATION_MODE,
                 String.valueOf(Settings.Secure.LOCATION_MODE_HIGH_ACCURACY),
@@ -732,7 +745,6 @@
                 SETTING_TYPE_SECURE,
                 Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
                 "-gps,-network");
-
         assertEquals(
                 "Wrong location providers",
                 "",
@@ -744,7 +756,6 @@
                 SETTING_TYPE_SECURE,
                 Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
                 "-test");
-
         assertEquals(
                 "Wrong location providers",
                 "",
@@ -753,8 +764,8 @@
     }
 
     @Test
-    public void testUpdateLocationProvidersAllowedLocked_enableAndDisable() throws Exception {
-        setSettingViaFrontEndApiAndAssertSuccessfulChange(
+    public void testLocationProvidersAllowed_enableAndDisable() throws Exception {
+        setStringViaFrontEndApiSetting(
                 SETTING_TYPE_SECURE,
                 Settings.Secure.LOCATION_MODE,
                 String.valueOf(Settings.Secure.LOCATION_MODE_OFF),
@@ -775,8 +786,8 @@
     }
 
     @Test
-    public void testUpdateLocationProvidersAllowedLocked_invalidInput() throws Exception {
-        setSettingViaFrontEndApiAndAssertSuccessfulChange(
+    public void testLocationProvidersAllowedLocked_invalidInput() throws Exception {
+        setStringViaFrontEndApiSetting(
                 SETTING_TYPE_SECURE,
                 Settings.Secure.LOCATION_MODE,
                 String.valueOf(Settings.Secure.LOCATION_MODE_OFF),
diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java
index 4fc190d..ec35b3d 100644
--- a/packages/Shell/src/com/android/shell/BugreportProgressService.java
+++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java
@@ -16,6 +16,8 @@
 
 package com.android.shell;
 
+import static android.content.pm.PackageManager.FEATURE_LEANBACK;
+import static android.content.pm.PackageManager.FEATURE_TELEVISION;
 import static android.os.Process.THREAD_PRIORITY_BACKGROUND;
 
 import static com.android.shell.BugreportPrefs.STATE_HIDE;
@@ -235,6 +237,7 @@
     private static final Bundle sNotificationBundle = new Bundle();
 
     private boolean mIsWatch;
+    private boolean mIsTv;
 
     private int mLastProgressPercent;
 
@@ -255,6 +258,9 @@
         final Configuration conf = mContext.getResources().getConfiguration();
         mIsWatch = (conf.uiMode & Configuration.UI_MODE_TYPE_MASK) ==
                 Configuration.UI_MODE_TYPE_WATCH;
+        PackageManager packageManager = getPackageManager();
+        mIsTv = packageManager.hasSystemFeature(FEATURE_LEANBACK)
+                || packageManager.hasSystemFeature(FEATURE_TELEVISION);
         NotificationManager nm = NotificationManager.from(mContext);
         nm.createNotificationChannel(
                 new NotificationChannel(NOTIFICATION_CHANNEL_ID,
@@ -500,8 +506,8 @@
                 .setProgress(info.max, info.progress, false)
                 .setOngoing(true);
 
-        // Wear bugreport doesn't need the bug info dialog, screenshot and cancel action.
-        if (!mIsWatch) {
+        // Wear and ATV bugreport doesn't need the bug info dialog, screenshot and cancel action.
+        if (!(mIsWatch || mIsTv)) {
             final Action cancelAction = new Action.Builder(null, mContext.getString(
                     com.android.internal.R.string.cancel), newCancelIntent(mContext, info)).build();
             final Intent infoIntent = new Intent(mContext, BugreportProgressService.class);
diff --git a/packages/Shell/src/com/android/shell/BugreportStorageProvider.java b/packages/Shell/src/com/android/shell/BugreportStorageProvider.java
index 0734e0d..4fbc226 100644
--- a/packages/Shell/src/com/android/shell/BugreportStorageProvider.java
+++ b/packages/Shell/src/com/android/shell/BugreportStorageProvider.java
@@ -20,6 +20,7 @@
 import android.database.MatrixCursor;
 import android.database.MatrixCursor.RowBuilder;
 import android.net.Uri;
+import android.os.Bundle;
 import android.os.CancellationSignal;
 import android.os.FileUtils;
 import android.os.ParcelFileDescriptor;
@@ -68,6 +69,18 @@
     }
 
     @Override
+    public Cursor queryChildDocuments(
+            String parentDocumentId, String[] projection, String sortOrder)
+            throws FileNotFoundException {
+        final Cursor c = super.queryChildDocuments(parentDocumentId, projection, sortOrder);
+        final Bundle extras = new Bundle();
+        extras.putCharSequence(DocumentsContract.EXTRA_INFO,
+                getContext().getText(R.string.bugreport_confirm));
+        c.setExtras(extras);
+        return c;
+    }
+
+    @Override
     public Cursor queryDocument(String documentId, String[] projection)
             throws FileNotFoundException {
         if (DOC_ID_ROOT.equals(documentId)) {
diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp
index 0913503..9c33116 100644
--- a/packages/SystemUI/Android.bp
+++ b/packages/SystemUI/Android.bp
@@ -66,6 +66,7 @@
     libs: [
         "telephony-common",
         "android.car",
+        "android.car.user",
     ],
 
     aaptflags: [
@@ -119,6 +120,7 @@
         "android.test.runner",
         "telephony-common",
         "android.car",
+        "android.car.user",
         "android.test.base",
     ],
     aaptflags: [
@@ -144,6 +146,7 @@
     libs: [
         "telephony-common",
         "android.car",
+        "android.car.user",
     ],
 
     dxflags: ["--multi-dex"],
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSIconView.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSIconView.java
index c268d32..0cdb509a 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSIconView.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSIconView.java
@@ -29,7 +29,7 @@
         super(context);
     }
 
-    public abstract void setIcon(State state);
+    public abstract void setIcon(State state, boolean allowAnimations);
     public abstract void disableAnimation();
     public abstract View getIconView();
 }
diff --git a/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml b/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml
index 862b964a..90f46ce 100644
--- a/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml
@@ -22,9 +22,9 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_name" msgid="3171996292755059205">"Bloqueio do teclado"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3420548423949593123">"Insira o código PIN"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="670683628782925409">"Digite o PUK do SIM e o novo código PIN."</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3747778500166059332">"Código PUK do SIM"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="8188243197504453830">"Novo código PIN do SIM"</string>
+    <string name="keyguard_password_enter_puk_code" msgid="670683628782925409">"Digite o PUK do chip e o novo código PIN."</string>
+    <string name="keyguard_password_enter_puk_prompt" msgid="3747778500166059332">"Código PUK do chip"</string>
+    <string name="keyguard_password_enter_pin_prompt" msgid="8188243197504453830">"Novo código PIN do chip"</string>
     <string name="keyguard_password_entry_touch_hint" msgid="5790410752696806482"><font size="17">"Toque para inserir a senha"</font></string>
     <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>
@@ -40,20 +40,20 @@
     <string name="keyguard_low_battery" msgid="9218432555787624490">"Conecte o seu carregador."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8566679946700751371">"Pressione Menu para desbloquear."</string>
     <string name="keyguard_network_locked_message" msgid="6743537524631420759">"Rede bloqueada"</string>
-    <string name="keyguard_missing_sim_message_short" msgid="6327533369959764518">"Sem cartão SIM"</string>
-    <string name="keyguard_missing_sim_message" product="tablet" msgid="4550152848200783542">"Não há um cartão SIM no tablet."</string>
-    <string name="keyguard_missing_sim_message" product="default" msgid="6585414237800161146">"Não há um cartão SIM no smartphone."</string>
-    <string name="keyguard_missing_sim_instructions" msgid="7350295932015220392">"Insira um cartão SIM."</string>
-    <string name="keyguard_missing_sim_instructions_long" msgid="589889372883904477">"O cartão SIM não foi inserido ou não é possível lê-lo. Insira um cartão SIM."</string>
-    <string name="keyguard_permanent_disabled_sim_message_short" msgid="654102080186420706">"Cartão SIM inutilizável."</string>
-    <string name="keyguard_permanent_disabled_sim_instructions" msgid="4683178224791318347">"O cartão SIM foi desativado permanentemente.\nEntre em contato com seu provedor de serviços sem fio para receber outro cartão SIM."</string>
-    <string name="keyguard_sim_locked_message" msgid="953766009432168127">"O cartão SIM está bloqueado."</string>
-    <string name="keyguard_sim_puk_locked_message" msgid="1772789643694942073">"O cartão SIM está bloqueado pelo PUK."</string>
-    <string name="keyguard_sim_unlock_progress_dialog_message" msgid="3586601150825821675">"Desbloqueando o cartão SIM…"</string>
+    <string name="keyguard_missing_sim_message_short" msgid="6327533369959764518">"Sem chip"</string>
+    <string name="keyguard_missing_sim_message" product="tablet" msgid="4550152848200783542">"Não há um chip no tablet."</string>
+    <string name="keyguard_missing_sim_message" product="default" msgid="6585414237800161146">"Não há um chip no smartphone."</string>
+    <string name="keyguard_missing_sim_instructions" msgid="7350295932015220392">"Insira um chip."</string>
+    <string name="keyguard_missing_sim_instructions_long" msgid="589889372883904477">"O chip não foi inserido ou não é possível lê-lo. Insira um chip."</string>
+    <string name="keyguard_permanent_disabled_sim_message_short" msgid="654102080186420706">"Chip inutilizável."</string>
+    <string name="keyguard_permanent_disabled_sim_instructions" msgid="4683178224791318347">"O chip foi desativado permanentemente.\nEntre em contato com seu provedor de serviços sem fio para receber outro chip."</string>
+    <string name="keyguard_sim_locked_message" msgid="953766009432168127">"O chip está bloqueado."</string>
+    <string name="keyguard_sim_puk_locked_message" msgid="1772789643694942073">"O chip está bloqueado pelo PUK."</string>
+    <string name="keyguard_sim_unlock_progress_dialog_message" msgid="3586601150825821675">"Desbloqueando o chip…"</string>
     <string name="keyguard_accessibility_pin_area" msgid="703175752097279029">"Área do PIN"</string>
     <string name="keyguard_accessibility_password" msgid="7695303207740941101">"Senha do dispositivo"</string>
-    <string name="keyguard_accessibility_sim_pin_area" msgid="912702510825058921">"Área do PIN SIM"</string>
-    <string name="keyguard_accessibility_sim_puk_area" msgid="136979425761438705">"Área do PUK SIM"</string>
+    <string name="keyguard_accessibility_sim_pin_area" msgid="912702510825058921">"Área do PIN do chip"</string>
+    <string name="keyguard_accessibility_sim_puk_area" msgid="136979425761438705">"Área do PUK do chip"</string>
     <string name="keyguard_accessibility_next_alarm" msgid="5835196989158584991">"Próximo alarme definido para <xliff:g id="ALARM">%1$s</xliff:g>"</string>
     <string name="keyboardview_keycode_delete" msgid="6883116827512721630">"Excluir"</string>
     <string name="disable_carrier_button_text" msgid="6914341927421916114">"Desativar eSIM"</string>
@@ -69,19 +69,19 @@
       <item quantity="other">Tente novamente em <xliff:g id="NUMBER">%d</xliff:g> segundos.</item>
     </plurals>
     <string name="kg_pattern_instructions" msgid="5547646893001491340">"Desenhe seu padrão"</string>
-    <string name="kg_sim_pin_instructions" msgid="6389000973113699187">"Informe o PIN do cartão SIM."</string>
-    <string name="kg_sim_pin_instructions_multi" msgid="1643757228644271861">"Informe o PIN do cartão SIM para \"<xliff:g id="CARRIER">%1$s</xliff:g>\"."</string>
+    <string name="kg_sim_pin_instructions" msgid="6389000973113699187">"Informe o PIN do chip."</string>
+    <string name="kg_sim_pin_instructions_multi" msgid="1643757228644271861">"Informe o PIN do chip para \"<xliff:g id="CARRIER">%1$s</xliff:g>\"."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="4416732549172148542">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Desative o eSIM para usar o dispositivo sem serviço móvel."</string>
     <string name="kg_pin_instructions" msgid="4069609316644030034">"Digite o PIN"</string>
     <string name="kg_password_instructions" msgid="136952397352976538">"Digite a senha"</string>
-    <string name="kg_puk_enter_puk_hint" msgid="2288964170039899277">"O SIM foi desativado. Insira o código PUK para continuar. Entre em contato com a operadora para mais detalhes."</string>
-    <string name="kg_puk_enter_puk_hint_multi" msgid="1373131883510840794">"O SIM \"<xliff:g id="CARRIER">%1$s</xliff:g>\" foi desativado. Informe o código PUK para continuar. Entre em contato com a operadora para saber mais detalhes."</string>
+    <string name="kg_puk_enter_puk_hint" msgid="2288964170039899277">"O chip foi desativado. Insira o código PUK para continuar. Entre em contato com a operadora para mais detalhes."</string>
+    <string name="kg_puk_enter_puk_hint_multi" msgid="1373131883510840794">"O chip \"<xliff:g id="CARRIER">%1$s</xliff:g>\" foi desativado. Informe o código PUK para continuar. Entre em contato com a operadora para saber mais detalhes."</string>
     <string name="kg_puk_enter_pin_hint" msgid="3137789674920391087">"Digite o código PIN desejado"</string>
     <string name="kg_enter_confirm_pin_hint" msgid="3089485999116759671">"Confirme o código PIN desejado"</string>
-    <string name="kg_sim_unlock_progress_dialog_message" msgid="4471738151810900114">"Desbloqueando o cartão SIM…"</string>
+    <string name="kg_sim_unlock_progress_dialog_message" msgid="4471738151810900114">"Desbloqueando o chip…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="3057533256729513335">"Digite um PIN com 4 a 8 números."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="6003602401368264144">"O código PUK deve ter oito números ou mais."</string>
-    <string name="kg_invalid_puk" msgid="5399287873762592502">"Introduza novamente o código PUK correto. Muitas tentativas malsucedidas desativarão permanentemente o SIM."</string>
+    <string name="kg_invalid_puk" msgid="5399287873762592502">"Introduza novamente o código PUK correto. Muitas tentativas malsucedidas desativarão permanentemente o chip."</string>
     <string name="kg_invalid_confirm_pin_hint" product="default" msgid="5672736555427444330">"Os códigos PIN não coincidem"</string>
     <string name="kg_login_too_many_attempts" msgid="6604574268387867255">"Muitas tentativas de padrão"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8637788033282252027">"Você digitou seu PIN incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. \n\nTente novamente em <xliff:g id="NUMBER_1">%2$d</xliff:g> segundos."</string>
@@ -101,18 +101,18 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="8476407539834855">"Você tentou desbloquear o smartphone incorretamente <xliff:g id="NUMBER">%d</xliff:g> vezes. O perfil de trabalho será removido, o que excluirá todos os dados do perfil."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="956706236554092172">"Você desenhou sua sequência de desbloqueio incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. Se fizer mais <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativas incorretas, será solicitado que você use o login do Google para desbloquear seu tablet.\n\n Tente novamente em <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="8364140853305528449">"Você desenhou sua sequência de desbloqueio incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. Se fizer mais <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativas incorretas, será solicitado que você use o login do Google para desbloquear.\n\n Tente novamente em <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
-    <string name="kg_password_wrong_pin_code_pukked" msgid="3389829202093674267">"Código PIN do SIM incorreto. Entre em contato com a operadora para desbloquear o dispositivo."</string>
+    <string name="kg_password_wrong_pin_code_pukked" msgid="3389829202093674267">"Código PIN do chip incorreto. Entre em contato com a operadora para desbloquear o dispositivo."</string>
     <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="4314341367727055967">
-      <item quantity="one">Código PIN do SIM incorreto. Tentativas restantes: <xliff:g id="NUMBER_1">%d</xliff:g>.</item>
-      <item quantity="other">Código PIN do SIM incorreto. Tentativas restantes: <xliff:g id="NUMBER_1">%d</xliff:g>.</item>
+      <item quantity="one">Código PIN do chip incorreto. Tentativas restantes: <xliff:g id="NUMBER_1">%d</xliff:g>.</item>
+      <item quantity="other">Código PIN do chip incorreto. Tentativas restantes: <xliff:g id="NUMBER_1">%d</xliff:g>.</item>
     </plurals>
-    <string name="kg_password_wrong_puk_code_dead" msgid="3329017604125179374">"O SIM está inutilizável. Entre em contato com a operadora."</string>
+    <string name="kg_password_wrong_puk_code_dead" msgid="3329017604125179374">"O chip não pode ser utilizado. Entre em contato com a operadora."</string>
     <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="2287504898931957513">
-      <item quantity="one">Código PUK do SIM incorreto. Tentativas restantes: <xliff:g id="NUMBER_1">%d</xliff:g>. Caso o código correto não seja digitado, o SIM se tornará permanentemente inutilizável.</item>
-      <item quantity="other">Código PUK do SIM incorreto. Tentativas restantes: <xliff:g id="NUMBER_1">%d</xliff:g>. Caso o código correto não seja digitado, o SIM se tornará permanentemente inutilizável.</item>
+      <item quantity="one">Código PUK do chip incorreto. Tentativas restantes: <xliff:g id="NUMBER_1">%d</xliff:g>. Caso o código correto não seja digitado, o chip se tornará permanentemente inutilizável.</item>
+      <item quantity="other">Código PUK do chip incorreto. Tentativas restantes: <xliff:g id="NUMBER_1">%d</xliff:g>. Caso o código correto não seja digitado, o chip se tornará permanentemente inutilizável.</item>
     </plurals>
-    <string name="kg_password_pin_failed" msgid="8769990811451236223">"Falha na operação de PIN do SIM."</string>
-    <string name="kg_password_puk_failed" msgid="1331621440873439974">"Falha na operação de PUK do SIM."</string>
+    <string name="kg_password_pin_failed" msgid="8769990811451236223">"Falha na operação de PIN do chip."</string>
+    <string name="kg_password_puk_failed" msgid="1331621440873439974">"Falha na operação de PUK do chip."</string>
     <string name="kg_pin_accepted" msgid="7637293533973802143">"Código aceito."</string>
     <string name="keyguard_carrier_default" msgid="4274828292998453695">"Sem serviço."</string>
     <string name="accessibility_ime_switch_button" msgid="2695096475319405612">"Alterar o método de entrada"</string>
@@ -143,11 +143,11 @@
     <string name="kg_fingerprint_not_recognized" msgid="7854413849848459418">"Não reconhecido"</string>
     <string name="kg_face_not_recognized" msgid="6382535088345875294">"Não reconhecido"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="3739658416797652781">
-      <item quantity="one">Informe o PIN do SIM. Você tem <xliff:g id="NUMBER_1">%d</xliff:g> tentativa restante.</item>
-      <item quantity="other">Informe o PIN do SIM. Você tem <xliff:g id="NUMBER_1">%d</xliff:g> tentativas restantes.</item>
+      <item quantity="one">Informe o PIN do chip. Você tem <xliff:g id="NUMBER_1">%d</xliff:g> tentativa restante.</item>
+      <item quantity="other">Informe o PIN do chip. Você tem <xliff:g id="NUMBER_1">%d</xliff:g> tentativas restantes.</item>
     </plurals>
     <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352">
-      <item quantity="one">O SIM agora está desativado. Informe o código PUK para continuar. Você tem <xliff:g id="_NUMBER_1">%d</xliff:g> tentativa restante antes de o SIM se tornar permanentemente inutilizável. Entre em contato com a operadora para saber mais detalhes.</item>
-      <item quantity="other">O SIM agora está desativado. Informe o código PUK para continuar. Você tem <xliff:g id="_NUMBER_1">%d</xliff:g> tentativas restantes antes de o SIM se tornar permanentemente inutilizável. Entre em contato com a operadora para saber mais detalhes.</item>
+      <item quantity="one">O chip agora está desativado. Informe o código PUK para continuar. Você tem <xliff:g id="_NUMBER_1">%d</xliff:g> tentativa restante antes de o chip se tornar permanentemente inutilizável. Entre em contato com a operadora para saber mais detalhes.</item>
+      <item quantity="other">O chip agora está desativado. Informe o código PUK para continuar. Você tem <xliff:g id="_NUMBER_1">%d</xliff:g> tentativas restantes antes de o chip se tornar permanentemente inutilizável. Entre em contato com a operadora para saber mais detalhes.</item>
     </plurals>
 </resources>
diff --git a/packages/SystemUI/res-keyguard/values-pt/strings.xml b/packages/SystemUI/res-keyguard/values-pt/strings.xml
index 862b964a..90f46ce 100644
--- a/packages/SystemUI/res-keyguard/values-pt/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-pt/strings.xml
@@ -22,9 +22,9 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_name" msgid="3171996292755059205">"Bloqueio do teclado"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3420548423949593123">"Insira o código PIN"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="670683628782925409">"Digite o PUK do SIM e o novo código PIN."</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3747778500166059332">"Código PUK do SIM"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="8188243197504453830">"Novo código PIN do SIM"</string>
+    <string name="keyguard_password_enter_puk_code" msgid="670683628782925409">"Digite o PUK do chip e o novo código PIN."</string>
+    <string name="keyguard_password_enter_puk_prompt" msgid="3747778500166059332">"Código PUK do chip"</string>
+    <string name="keyguard_password_enter_pin_prompt" msgid="8188243197504453830">"Novo código PIN do chip"</string>
     <string name="keyguard_password_entry_touch_hint" msgid="5790410752696806482"><font size="17">"Toque para inserir a senha"</font></string>
     <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>
@@ -40,20 +40,20 @@
     <string name="keyguard_low_battery" msgid="9218432555787624490">"Conecte o seu carregador."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8566679946700751371">"Pressione Menu para desbloquear."</string>
     <string name="keyguard_network_locked_message" msgid="6743537524631420759">"Rede bloqueada"</string>
-    <string name="keyguard_missing_sim_message_short" msgid="6327533369959764518">"Sem cartão SIM"</string>
-    <string name="keyguard_missing_sim_message" product="tablet" msgid="4550152848200783542">"Não há um cartão SIM no tablet."</string>
-    <string name="keyguard_missing_sim_message" product="default" msgid="6585414237800161146">"Não há um cartão SIM no smartphone."</string>
-    <string name="keyguard_missing_sim_instructions" msgid="7350295932015220392">"Insira um cartão SIM."</string>
-    <string name="keyguard_missing_sim_instructions_long" msgid="589889372883904477">"O cartão SIM não foi inserido ou não é possível lê-lo. Insira um cartão SIM."</string>
-    <string name="keyguard_permanent_disabled_sim_message_short" msgid="654102080186420706">"Cartão SIM inutilizável."</string>
-    <string name="keyguard_permanent_disabled_sim_instructions" msgid="4683178224791318347">"O cartão SIM foi desativado permanentemente.\nEntre em contato com seu provedor de serviços sem fio para receber outro cartão SIM."</string>
-    <string name="keyguard_sim_locked_message" msgid="953766009432168127">"O cartão SIM está bloqueado."</string>
-    <string name="keyguard_sim_puk_locked_message" msgid="1772789643694942073">"O cartão SIM está bloqueado pelo PUK."</string>
-    <string name="keyguard_sim_unlock_progress_dialog_message" msgid="3586601150825821675">"Desbloqueando o cartão SIM…"</string>
+    <string name="keyguard_missing_sim_message_short" msgid="6327533369959764518">"Sem chip"</string>
+    <string name="keyguard_missing_sim_message" product="tablet" msgid="4550152848200783542">"Não há um chip no tablet."</string>
+    <string name="keyguard_missing_sim_message" product="default" msgid="6585414237800161146">"Não há um chip no smartphone."</string>
+    <string name="keyguard_missing_sim_instructions" msgid="7350295932015220392">"Insira um chip."</string>
+    <string name="keyguard_missing_sim_instructions_long" msgid="589889372883904477">"O chip não foi inserido ou não é possível lê-lo. Insira um chip."</string>
+    <string name="keyguard_permanent_disabled_sim_message_short" msgid="654102080186420706">"Chip inutilizável."</string>
+    <string name="keyguard_permanent_disabled_sim_instructions" msgid="4683178224791318347">"O chip foi desativado permanentemente.\nEntre em contato com seu provedor de serviços sem fio para receber outro chip."</string>
+    <string name="keyguard_sim_locked_message" msgid="953766009432168127">"O chip está bloqueado."</string>
+    <string name="keyguard_sim_puk_locked_message" msgid="1772789643694942073">"O chip está bloqueado pelo PUK."</string>
+    <string name="keyguard_sim_unlock_progress_dialog_message" msgid="3586601150825821675">"Desbloqueando o chip…"</string>
     <string name="keyguard_accessibility_pin_area" msgid="703175752097279029">"Área do PIN"</string>
     <string name="keyguard_accessibility_password" msgid="7695303207740941101">"Senha do dispositivo"</string>
-    <string name="keyguard_accessibility_sim_pin_area" msgid="912702510825058921">"Área do PIN SIM"</string>
-    <string name="keyguard_accessibility_sim_puk_area" msgid="136979425761438705">"Área do PUK SIM"</string>
+    <string name="keyguard_accessibility_sim_pin_area" msgid="912702510825058921">"Área do PIN do chip"</string>
+    <string name="keyguard_accessibility_sim_puk_area" msgid="136979425761438705">"Área do PUK do chip"</string>
     <string name="keyguard_accessibility_next_alarm" msgid="5835196989158584991">"Próximo alarme definido para <xliff:g id="ALARM">%1$s</xliff:g>"</string>
     <string name="keyboardview_keycode_delete" msgid="6883116827512721630">"Excluir"</string>
     <string name="disable_carrier_button_text" msgid="6914341927421916114">"Desativar eSIM"</string>
@@ -69,19 +69,19 @@
       <item quantity="other">Tente novamente em <xliff:g id="NUMBER">%d</xliff:g> segundos.</item>
     </plurals>
     <string name="kg_pattern_instructions" msgid="5547646893001491340">"Desenhe seu padrão"</string>
-    <string name="kg_sim_pin_instructions" msgid="6389000973113699187">"Informe o PIN do cartão SIM."</string>
-    <string name="kg_sim_pin_instructions_multi" msgid="1643757228644271861">"Informe o PIN do cartão SIM para \"<xliff:g id="CARRIER">%1$s</xliff:g>\"."</string>
+    <string name="kg_sim_pin_instructions" msgid="6389000973113699187">"Informe o PIN do chip."</string>
+    <string name="kg_sim_pin_instructions_multi" msgid="1643757228644271861">"Informe o PIN do chip para \"<xliff:g id="CARRIER">%1$s</xliff:g>\"."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="4416732549172148542">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Desative o eSIM para usar o dispositivo sem serviço móvel."</string>
     <string name="kg_pin_instructions" msgid="4069609316644030034">"Digite o PIN"</string>
     <string name="kg_password_instructions" msgid="136952397352976538">"Digite a senha"</string>
-    <string name="kg_puk_enter_puk_hint" msgid="2288964170039899277">"O SIM foi desativado. Insira o código PUK para continuar. Entre em contato com a operadora para mais detalhes."</string>
-    <string name="kg_puk_enter_puk_hint_multi" msgid="1373131883510840794">"O SIM \"<xliff:g id="CARRIER">%1$s</xliff:g>\" foi desativado. Informe o código PUK para continuar. Entre em contato com a operadora para saber mais detalhes."</string>
+    <string name="kg_puk_enter_puk_hint" msgid="2288964170039899277">"O chip foi desativado. Insira o código PUK para continuar. Entre em contato com a operadora para mais detalhes."</string>
+    <string name="kg_puk_enter_puk_hint_multi" msgid="1373131883510840794">"O chip \"<xliff:g id="CARRIER">%1$s</xliff:g>\" foi desativado. Informe o código PUK para continuar. Entre em contato com a operadora para saber mais detalhes."</string>
     <string name="kg_puk_enter_pin_hint" msgid="3137789674920391087">"Digite o código PIN desejado"</string>
     <string name="kg_enter_confirm_pin_hint" msgid="3089485999116759671">"Confirme o código PIN desejado"</string>
-    <string name="kg_sim_unlock_progress_dialog_message" msgid="4471738151810900114">"Desbloqueando o cartão SIM…"</string>
+    <string name="kg_sim_unlock_progress_dialog_message" msgid="4471738151810900114">"Desbloqueando o chip…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="3057533256729513335">"Digite um PIN com 4 a 8 números."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="6003602401368264144">"O código PUK deve ter oito números ou mais."</string>
-    <string name="kg_invalid_puk" msgid="5399287873762592502">"Introduza novamente o código PUK correto. Muitas tentativas malsucedidas desativarão permanentemente o SIM."</string>
+    <string name="kg_invalid_puk" msgid="5399287873762592502">"Introduza novamente o código PUK correto. Muitas tentativas malsucedidas desativarão permanentemente o chip."</string>
     <string name="kg_invalid_confirm_pin_hint" product="default" msgid="5672736555427444330">"Os códigos PIN não coincidem"</string>
     <string name="kg_login_too_many_attempts" msgid="6604574268387867255">"Muitas tentativas de padrão"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8637788033282252027">"Você digitou seu PIN incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. \n\nTente novamente em <xliff:g id="NUMBER_1">%2$d</xliff:g> segundos."</string>
@@ -101,18 +101,18 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="8476407539834855">"Você tentou desbloquear o smartphone incorretamente <xliff:g id="NUMBER">%d</xliff:g> vezes. O perfil de trabalho será removido, o que excluirá todos os dados do perfil."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="956706236554092172">"Você desenhou sua sequência de desbloqueio incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. Se fizer mais <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativas incorretas, será solicitado que você use o login do Google para desbloquear seu tablet.\n\n Tente novamente em <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="8364140853305528449">"Você desenhou sua sequência de desbloqueio incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. Se fizer mais <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativas incorretas, será solicitado que você use o login do Google para desbloquear.\n\n Tente novamente em <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
-    <string name="kg_password_wrong_pin_code_pukked" msgid="3389829202093674267">"Código PIN do SIM incorreto. Entre em contato com a operadora para desbloquear o dispositivo."</string>
+    <string name="kg_password_wrong_pin_code_pukked" msgid="3389829202093674267">"Código PIN do chip incorreto. Entre em contato com a operadora para desbloquear o dispositivo."</string>
     <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="4314341367727055967">
-      <item quantity="one">Código PIN do SIM incorreto. Tentativas restantes: <xliff:g id="NUMBER_1">%d</xliff:g>.</item>
-      <item quantity="other">Código PIN do SIM incorreto. Tentativas restantes: <xliff:g id="NUMBER_1">%d</xliff:g>.</item>
+      <item quantity="one">Código PIN do chip incorreto. Tentativas restantes: <xliff:g id="NUMBER_1">%d</xliff:g>.</item>
+      <item quantity="other">Código PIN do chip incorreto. Tentativas restantes: <xliff:g id="NUMBER_1">%d</xliff:g>.</item>
     </plurals>
-    <string name="kg_password_wrong_puk_code_dead" msgid="3329017604125179374">"O SIM está inutilizável. Entre em contato com a operadora."</string>
+    <string name="kg_password_wrong_puk_code_dead" msgid="3329017604125179374">"O chip não pode ser utilizado. Entre em contato com a operadora."</string>
     <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="2287504898931957513">
-      <item quantity="one">Código PUK do SIM incorreto. Tentativas restantes: <xliff:g id="NUMBER_1">%d</xliff:g>. Caso o código correto não seja digitado, o SIM se tornará permanentemente inutilizável.</item>
-      <item quantity="other">Código PUK do SIM incorreto. Tentativas restantes: <xliff:g id="NUMBER_1">%d</xliff:g>. Caso o código correto não seja digitado, o SIM se tornará permanentemente inutilizável.</item>
+      <item quantity="one">Código PUK do chip incorreto. Tentativas restantes: <xliff:g id="NUMBER_1">%d</xliff:g>. Caso o código correto não seja digitado, o chip se tornará permanentemente inutilizável.</item>
+      <item quantity="other">Código PUK do chip incorreto. Tentativas restantes: <xliff:g id="NUMBER_1">%d</xliff:g>. Caso o código correto não seja digitado, o chip se tornará permanentemente inutilizável.</item>
     </plurals>
-    <string name="kg_password_pin_failed" msgid="8769990811451236223">"Falha na operação de PIN do SIM."</string>
-    <string name="kg_password_puk_failed" msgid="1331621440873439974">"Falha na operação de PUK do SIM."</string>
+    <string name="kg_password_pin_failed" msgid="8769990811451236223">"Falha na operação de PIN do chip."</string>
+    <string name="kg_password_puk_failed" msgid="1331621440873439974">"Falha na operação de PUK do chip."</string>
     <string name="kg_pin_accepted" msgid="7637293533973802143">"Código aceito."</string>
     <string name="keyguard_carrier_default" msgid="4274828292998453695">"Sem serviço."</string>
     <string name="accessibility_ime_switch_button" msgid="2695096475319405612">"Alterar o método de entrada"</string>
@@ -143,11 +143,11 @@
     <string name="kg_fingerprint_not_recognized" msgid="7854413849848459418">"Não reconhecido"</string>
     <string name="kg_face_not_recognized" msgid="6382535088345875294">"Não reconhecido"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="3739658416797652781">
-      <item quantity="one">Informe o PIN do SIM. Você tem <xliff:g id="NUMBER_1">%d</xliff:g> tentativa restante.</item>
-      <item quantity="other">Informe o PIN do SIM. Você tem <xliff:g id="NUMBER_1">%d</xliff:g> tentativas restantes.</item>
+      <item quantity="one">Informe o PIN do chip. Você tem <xliff:g id="NUMBER_1">%d</xliff:g> tentativa restante.</item>
+      <item quantity="other">Informe o PIN do chip. Você tem <xliff:g id="NUMBER_1">%d</xliff:g> tentativas restantes.</item>
     </plurals>
     <plurals name="kg_password_default_puk_message" formatted="false" msgid="8744416410184198352">
-      <item quantity="one">O SIM agora está desativado. Informe o código PUK para continuar. Você tem <xliff:g id="_NUMBER_1">%d</xliff:g> tentativa restante antes de o SIM se tornar permanentemente inutilizável. Entre em contato com a operadora para saber mais detalhes.</item>
-      <item quantity="other">O SIM agora está desativado. Informe o código PUK para continuar. Você tem <xliff:g id="_NUMBER_1">%d</xliff:g> tentativas restantes antes de o SIM se tornar permanentemente inutilizável. Entre em contato com a operadora para saber mais detalhes.</item>
+      <item quantity="one">O chip agora está desativado. Informe o código PUK para continuar. Você tem <xliff:g id="_NUMBER_1">%d</xliff:g> tentativa restante antes de o chip se tornar permanentemente inutilizável. Entre em contato com a operadora para saber mais detalhes.</item>
+      <item quantity="other">O chip agora está desativado. Informe o código PUK para continuar. Você tem <xliff:g id="_NUMBER_1">%d</xliff:g> tentativas restantes antes de o chip se tornar permanentemente inutilizável. Entre em contato com a operadora para saber mais detalhes.</item>
     </plurals>
 </resources>
diff --git a/packages/SystemUI/res/layout/notification_info.xml b/packages/SystemUI/res/layout/notification_info.xml
index e1e812b..7a38899 100644
--- a/packages/SystemUI/res/layout/notification_info.xml
+++ b/packages/SystemUI/res/layout/notification_info.xml
@@ -154,6 +154,7 @@
                 style="@style/TextAppearance.NotificationInfo.Button" />
             <TextView
                 android:id="@+id/keep"
+                android:minWidth="48dp"
                 android:text="@string/inline_keep_button"
                 android:layout_width="wrap_content"
                 android:layout_height="match_parent"
diff --git a/packages/SystemUI/res/layout/operator_name.xml b/packages/SystemUI/res/layout/operator_name.xml
index c4f75e9..015e30a 100644
--- a/packages/SystemUI/res/layout/operator_name.xml
+++ b/packages/SystemUI/res/layout/operator_name.xml
@@ -27,5 +27,6 @@
         android:maxLength="20"
         android:gravity="center_vertical|start"
         android:textAppearance="?android:attr/textAppearanceSmall"
-        android:singleLine="true" />
+        android:singleLine="true"
+        android:paddingEnd="5dp" />
 </com.android.systemui.statusbar.AlphaOptimizedFrameLayout>
diff --git a/packages/SystemUI/res/layout/quick_settings_header_info.xml b/packages/SystemUI/res/layout/quick_settings_header_info.xml
index 0892f73..967e13f 100644
--- a/packages/SystemUI/res/layout/quick_settings_header_info.xml
+++ b/packages/SystemUI/res/layout/quick_settings_header_info.xml
@@ -38,7 +38,7 @@
         android:layout_height="wrap_content"
         android:layout_gravity="center_horizontal|bottom"
         android:gravity="center_vertical"
-        android:visibility="invisible">
+        android:alpha="0">
 
         <ImageView
             android:id="@+id/next_alarm_icon"
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 6bfd9b2..44691c2 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -426,9 +426,11 @@
     <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_limit_reached_title" msgid="7374910700117359177">"Gebruikerlimiet is bereik"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="other">Jy kan tot <xliff:g id="COUNT">%d</xliff:g> gebruikers byvoeg.</item>
+      <item quantity="one">Net een gebruiker kan geskep word.</item>
+    </plurals>
     <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>
@@ -732,8 +734,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"Hou en sleep om teëls te herrangskik"</string>
     <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>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 43a27f0..966e4d7 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -426,9 +426,11 @@
     <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_limit_reached_title" msgid="7374910700117359177">"የተጠቃሚ ገደብ ላይ ተደርሷል"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> ተጠቃሚዎች ብቻ ናቸው ሊፈጠሩ የሚችሉት።</item>
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> ተጠቃሚዎች ብቻ ናቸው ሊፈጠሩ የሚችሉት።</item>
+    </plurals>
     <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>
@@ -732,8 +734,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"ሰድሮችን ዳግም ለማስተካከል ይያዙ እና ይጎትቱ።"</string>
     <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>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 598d822..278b00a 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -438,9 +438,15 @@
     <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_limit_reached_title" msgid="7374910700117359177">"تم الوصول إلى أقصى عدد للمستخدمين"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="zero">يمكنك إضافة ما يصل إلى <xliff:g id="COUNT">%d</xliff:g> مستخدم.</item>
+      <item quantity="two">يمكنك إضافة ما يصل إلى مستخدمينِ (<xliff:g id="COUNT">%d</xliff:g>).</item>
+      <item quantity="few">يمكنك إضافة ما يصل إلى <xliff:g id="COUNT">%d</xliff:g> مستخدمين.</item>
+      <item quantity="many">يمكنك إضافة ما يصل إلى <xliff:g id="COUNT">%d</xliff:g> مستخدمًا.</item>
+      <item quantity="other">يمكنك إضافة ما يصل إلى <xliff:g id="COUNT">%d</xliff:g> مستخدم.</item>
+      <item quantity="one">يمكن إنشاء مستخدم واحد فقط.</item>
+    </plurals>
     <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>
@@ -752,8 +758,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"اضغط باستمرار مع السحب لإعادة ترتيب المربّعات."</string>
     <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>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index 84d178b..8912f15 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -426,9 +426,11 @@
     <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_limit_reached_title" msgid="7374910700117359177">"অধিকতম ব্যৱহাৰকাৰী সৃষ্টি কৰা হ’ল"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="one">আপুনি <xliff:g id="COUNT">%d</xliff:g> জনলৈকে ব্যৱহাৰকাৰী যোগ কৰিব পাৰে।</item>
+      <item quantity="other">আপুনি <xliff:g id="COUNT">%d</xliff:g> জনলৈকে ব্যৱহাৰকাৰী যোগ কৰিব পাৰে।</item>
+    </plurals>
     <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>
@@ -732,8 +734,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"টাইলসমূহ পুনৰ সজাবলৈ ধৰি টানক"</string>
     <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>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index bbc67a5..f0779fb 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -209,7 +209,7 @@
     <string name="accessibility_quick_settings_airplane_changed_off" msgid="66846307818850664">"Təyyarə rejimi deaktiv edildi."</string>
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"Təyyarə rejimi aktiv edildi."</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="2960643943620637020">"tam sakitlik"</string>
-    <string name="accessibility_quick_settings_dnd_alarms_on" msgid="3357131899365865386">"yalnız siqnallar"</string>
+    <string name="accessibility_quick_settings_dnd_alarms_on" msgid="3357131899365865386">"yalnız alarmlar"</string>
     <string name="accessibility_quick_settings_dnd" msgid="6607873236717185815">"Narahat etməyin."</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"\"Narahat etməyin\" qeyri-aktivdir."</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"\"Narahat etməyin\" aktivdir."</string>
@@ -426,9 +426,11 @@
     <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_limit_reached_title" msgid="7374910700117359177">"İstifadəçi limitinə çatmısınız"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="other">Maksimum <xliff:g id="COUNT">%d</xliff:g> istifadəçi əlavə edə bilərsiniz.</item>
+      <item quantity="one">Yalnız bir istifadəçi yaradıla bilər.</item>
+    </plurals>
     <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>
@@ -732,8 +734,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"Mozaikaları yenidən təşkil etmək üçün basıb saxlayın və çəkin"</string>
     <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>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index 679fdde..9dc6460 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -429,9 +429,12 @@
     <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_limit_reached_title" msgid="7374910700117359177">"Dostignut maksimalni broj korisnika"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="one">Možete da dodate najviše <xliff:g id="COUNT">%d</xliff:g> korisnika.</item>
+      <item quantity="few">Možete da dodate najviše <xliff:g id="COUNT">%d</xliff:g> korisnika.</item>
+      <item quantity="other">Možete da dodate najviše <xliff:g id="COUNT">%d</xliff:g> korisnika.</item>
+    </plurals>
     <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>
@@ -737,8 +740,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"Zadržite i prevucite da biste promenili raspored pločica"</string>
     <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>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index d26b322..9898dbd 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -434,9 +434,13 @@
     <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_limit_reached_title" msgid="7374910700117359177">"Дасягнуты ліміт карыстальнікаў"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="one">Можна дадаць <xliff:g id="COUNT">%d</xliff:g> карыстальніка.</item>
+      <item quantity="few">Можна дадаць <xliff:g id="COUNT">%d</xliff:g> карыстальнікаў.</item>
+      <item quantity="many">Можна дадаць <xliff:g id="COUNT">%d</xliff:g> карыстальнікаў.</item>
+      <item quantity="other">Можна дадаць <xliff:g id="COUNT">%d</xliff:g> карыстальніка.</item>
+    </plurals>
     <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>
@@ -744,8 +748,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"Каб змяніць парадак плітак, утрымлівайце і перацягвайце іх"</string>
     <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>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 2bd6cc4..a5506a3 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -426,9 +426,11 @@
     <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_limit_reached_title" msgid="7374910700117359177">"Достигнахте огранич. за потребители"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="other">Можете да добавите до <xliff:g id="COUNT">%d</xliff:g> потребители.</item>
+      <item quantity="one">Може да бъде създаден само един потребител.</item>
+    </plurals>
     <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>
@@ -732,8 +734,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"Задръжте и плъзнете, за да пренаредите плочките"</string>
     <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>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index 866deae..5d52103 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -426,9 +426,11 @@
     <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_limit_reached_title" msgid="7374910700117359177">"আর কোনও প্রোফাইল যোগ করা যাবে না"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="one">আপনি <xliff:g id="COUNT">%d</xliff:g> জন পর্যন্ত ব্যবহারকারীর প্রোফাইল যোগ করতে পারেন।</item>
+      <item quantity="other">আপনি <xliff:g id="COUNT">%d</xliff:g> জন পর্যন্ত ব্যবহারকারীর প্রোফাইল যোগ করতে পারেন।</item>
+    </plurals>
     <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>
@@ -732,8 +734,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"টাইলগুলি আবার সাজানোর জন্য ধরে থেকে টেনে আনুন"</string>
     <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>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index 57089b8..4527e9a 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -429,9 +429,12 @@
     <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_limit_reached_title" msgid="7374910700117359177">"Dostignut limit za broj korisnika"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="one">Možete dodati najviše <xliff:g id="COUNT">%d</xliff:g> korisnika.</item>
+      <item quantity="few">Možete dodati najviše <xliff:g id="COUNT">%d</xliff:g> korisnika.</item>
+      <item quantity="other">Možete dodati najviše <xliff:g id="COUNT">%d</xliff:g> korisnika.</item>
+    </plurals>
     <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>
@@ -739,8 +742,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"Držite i prevucite da preuredite polja"</string>
     <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>
@@ -851,7 +853,7 @@
     <string name="touch_filtered_warning" msgid="8671693809204767551">"Postavke ne mogu potvrditi vaš odgovor jer aplikacija zaklanja zahtjev za odobrenje."</string>
     <string name="slice_permission_title" msgid="7465009437851044444">"Dozvoliti aplikaciji <xliff:g id="APP_0">%1$s</xliff:g> prikazivanje isječaka aplikacije <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
     <string name="slice_permission_text_1" msgid="3514586565609596523">"- Može čitati informacije iz aplikacije <xliff:g id="APP">%1$s</xliff:g>"</string>
-    <string name="slice_permission_text_2" msgid="3146758297471143723">"- Može poduzeti radnje unutar aplikacije <xliff:g id="APP">%1$s</xliff:g>"</string>
+    <string name="slice_permission_text_2" msgid="3146758297471143723">"- Može poduzeti radnje u aplikaciji <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="slice_permission_checkbox" msgid="7986504458640562900">"Dozvoli aplikaciji <xliff:g id="APP">%1$s</xliff:g> prikazivanje isječaka iz svake aplikacije"</string>
     <string name="slice_permission_allow" msgid="2340244901366722709">"Dozvoli"</string>
     <string name="slice_permission_deny" msgid="7683681514008048807">"Odbij"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 920db25..23754ea 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -426,9 +426,11 @@
     <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_limit_reached_title" msgid="7374910700117359177">"S\'ha assolit el límit d\'usuaris"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="other">Pots afegir fins a <xliff:g id="COUNT">%d</xliff:g> usuaris.</item>
+      <item quantity="one">Només es pot crear un usuari.</item>
+    </plurals>
     <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>
@@ -732,8 +734,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"Mantén premut i arrossega per reorganitzar les funcions"</string>
     <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>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 4077908..e7583b5 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -434,9 +434,13 @@
     <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_limit_reached_title" msgid="7374910700117359177">"Bylo dosaženo limitu uživatelů"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="few">Lze přidat až <xliff:g id="COUNT">%d</xliff:g> uživatele.</item>
+      <item quantity="many">Lze přidat až <xliff:g id="COUNT">%d</xliff:g> uživatele.</item>
+      <item quantity="other">Lze přidat až <xliff:g id="COUNT">%d</xliff:g> uživatelů.</item>
+      <item quantity="one">Lze vytvořit jen jednoho uživatele.</item>
+    </plurals>
     <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>
@@ -744,8 +748,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"Dlaždice můžete uspořádat podržením a přetažením"</string>
     <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>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 2ebc0e8..31634a9 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -426,9 +426,11 @@
     <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_limit_reached_title" msgid="7374910700117359177">"Grænsen for antal brugere er nået"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="one">Du kan tilføje op til <xliff:g id="COUNT">%d</xliff:g> bruger.</item>
+      <item quantity="other">Du kan tilføje op til <xliff:g id="COUNT">%d</xliff:g> brugere.</item>
+    </plurals>
     <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>
@@ -732,8 +734,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"Omorganiser felter ved at holde dem nede og trække"</string>
     <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>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 6636c9d..aa6e449 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -430,9 +430,11 @@
     <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_limit_reached_title" msgid="7374910700117359177">"Nutzerlimit erreicht"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="other">Du kannst bis zu <xliff:g id="COUNT">%d</xliff:g> Nutzer hinzufügen.</item>
+      <item quantity="one">Es kann nur ein Nutzer erstellt werden.</item>
+    </plurals>
     <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>
@@ -736,8 +738,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"Halten und ziehen, um die Kacheln neu anzuordnen"</string>
     <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>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 60c412a..1a1c762 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -426,9 +426,11 @@
     <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_limit_reached_title" msgid="7374910700117359177">"Συμπληρώθηκε το όριο χρηστών"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="other">Μπορείτε να προσθέσετε έως <xliff:g id="COUNT">%d</xliff:g> χρήστες.</item>
+      <item quantity="one">Είναι δυνατή η δημιουργία μόνο ενός χρήστη.</item>
+    </plurals>
     <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>
@@ -732,8 +734,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"Κρατήστε και σύρετε για αναδιάταξη των πλακιδίων"</string>
     <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>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index f5587fe..31509dc 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -428,9 +428,11 @@
     <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_limit_reached_title" msgid="7374910700117359177">"Alcanzaste el límite de usuarios"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="other">Puedes agregar hasta <xliff:g id="COUNT">%d</xliff:g> usuarios.</item>
+      <item quantity="one">Solo se puede crear un usuario.</item>
+    </plurals>
     <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>
@@ -734,8 +736,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"Mantén presionado y arrastra para reorganizar los mosaicos"</string>
     <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>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index e78e130..2cc3abd 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -428,9 +428,11 @@
     <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_limit_reached_title" msgid="7374910700117359177">"Has alcanzado el límite de usuarios"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="other">Puedes añadir hasta <xliff:g id="COUNT">%d</xliff:g> usuarios.</item>
+      <item quantity="one">Solo se puede crear un usuario.</item>
+    </plurals>
     <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>
@@ -734,8 +736,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"Mantener pulsado y arrastrar para reorganizar los mosaicos"</string>
     <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>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index 68cb738..f22dc1a 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -428,9 +428,11 @@
     <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_limit_reached_title" msgid="7374910700117359177">"Kasutajate limiit on täis"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="other">Võite lisada kuni <xliff:g id="COUNT">%d</xliff:g> kasutajat.</item>
+      <item quantity="one">Luua saab ainult ühe kasutaja.</item>
+    </plurals>
     <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>
@@ -734,8 +736,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"Paanide ümberpaigutamiseks hoidke neid all ja lohistage"</string>
     <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>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index e203b76..87dba92 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -428,9 +428,11 @@
     <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_limit_reached_title" msgid="7374910700117359177">"Erabiltzaile-mugara iritsi zara"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="other">Gehienez, <xliff:g id="COUNT">%d</xliff:g> erabiltzaile gehi ditzakezu.</item>
+      <item quantity="one">Erabiltzaile bakarra sor daiteke.</item>
+    </plurals>
     <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>
@@ -734,8 +736,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"Eduki sakatuta eta arrastatu, lauzak berrantolatzeko"</string>
     <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>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 62bb59f..5411d3d 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -426,9 +426,11 @@
     <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_limit_reached_title" msgid="7374910700117359177">"به تعداد مجاز تعداد کاربر رسیده‌اید"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="one">می‌توانید حداکثر <xliff:g id="COUNT">%d</xliff:g> کاربر اضافه کنید.</item>
+      <item quantity="other">می‌توانید حداکثر <xliff:g id="COUNT">%d</xliff:g> کاربر اضافه کنید.</item>
+    </plurals>
     <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>
@@ -732,8 +734,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"برای تغییر دادن ترتیب کاشی‌ها، آن‌ها را نگه دارید و بکشید"</string>
     <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>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 330f7d6..83345b8 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -426,9 +426,11 @@
     <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_limit_reached_title" msgid="7374910700117359177">"Käyttäjäraja saavutettu"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="other">Voit lisätä korkeintaan <xliff:g id="COUNT">%d</xliff:g> käyttäjää.</item>
+      <item quantity="one">Käyttäjiä voi olla vain yksi.</item>
+    </plurals>
     <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>
@@ -732,8 +734,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"Järjestele ruutuja koskettamalla pitkään ja vetämällä"</string>
     <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>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 47430ba..c9c252f 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -428,9 +428,11 @@
     <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_limit_reached_title" msgid="7374910700117359177">"Limite d\'utilisateurs atteinte"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="one">Vous pouvez ajouter jusqu\'à <xliff:g id="COUNT">%d</xliff:g> utilisateur.</item>
+      <item quantity="other">Vous pouvez ajouter jusqu\'à <xliff:g id="COUNT">%d</xliff:g> utilisateurs.</item>
+    </plurals>
     <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>
@@ -734,8 +736,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"Maint. doigt sur l\'écran, puis glissez-le pour réorg. tuiles"</string>
     <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>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index c10c1d2..4559854 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -361,7 +361,7 @@
     <string name="recents_search_bar_label" msgid="8074997400187836677">"rechercher"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Impossible de lancer <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"L\'application <xliff:g id="APP">%s</xliff:g> est désactivée en mode sécurisé."</string>
-    <string name="recents_stack_action_button_label" msgid="6593727103310426253">"Tout effacer"</string>
+    <string name="recents_stack_action_button_label" msgid="6593727103310426253">"Tout fermer"</string>
     <string name="recents_drag_hint_message" msgid="2649739267073203985">"Faire glisser ici pour utiliser l\'écran partagé"</string>
     <string name="recents_swipe_up_onboarding" msgid="3824607135920170001">"Balayer l\'écran vers le haut pour changer d\'application"</string>
     <string name="recents_quick_scrub_onboarding" msgid="2778062804333285789">"Déplacer vers la droite pour changer rapidement d\'application"</string>
@@ -428,9 +428,11 @@
     <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_limit_reached_title" msgid="7374910700117359177">"Limite nombre utilisateurs atteinte"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="one">Vous pouvez ajouter <xliff:g id="COUNT">%d</xliff:g> profil utilisateur.</item>
+      <item quantity="other">Vous pouvez ajouter jusqu\'à <xliff:g id="COUNT">%d</xliff:g> profils utilisateur.</item>
+    </plurals>
     <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>
@@ -734,8 +736,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"Sélectionnez et faites glisser les tuiles pour réorganiser"</string>
     <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>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index 5c6737f..9cb251e 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -428,9 +428,11 @@
     <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_limit_reached_title" msgid="7374910700117359177">"Alcanzouse o límite de usuarios"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="other">Podes engadir ata <xliff:g id="COUNT">%d</xliff:g> usuarios.</item>
+      <item quantity="one">Só se pode crear un usuario.</item>
+    </plurals>
     <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>
@@ -734,8 +736,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"Para reorganizar os mosaicos, mantenos premidos e arrástraos"</string>
     <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>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index 76e00d4..df06cbe 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -426,9 +426,11 @@
     <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_limit_reached_title" msgid="7374910700117359177">"વપરાશકર્તા સંખ્યાની મર્યાદા"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="one">તમે <xliff:g id="COUNT">%d</xliff:g> વપરાશકર્તા સુધી ઉમેરી શકો છો.</item>
+      <item quantity="other">તમે <xliff:g id="COUNT">%d</xliff:g> વપરાશકર્તાઓ સુધી ઉમેરી શકો છો.</item>
+    </plurals>
     <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>
@@ -732,8 +734,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"ટાઇલને ફરીથી ગોઠવવા માટે આંગળી દબાવીને ખેંચો"</string>
     <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>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index ad8d505..46555a4 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -426,9 +426,11 @@
     <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_limit_reached_title" msgid="7374910700117359177">"अब और उपयोगकर्ता नहीं जोड़े जा सकते"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="one">आप ज़्यादा से ज़्यादा <xliff:g id="COUNT">%d</xliff:g> उपयोगकर्ता जोड़ सकते हैं.</item>
+      <item quantity="other">आप ज़्यादा से ज़्यादा <xliff:g id="COUNT">%d</xliff:g> उपयोगकर्ता जोड़ सकते हैं.</item>
+    </plurals>
     <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>
@@ -732,8 +734,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"टाइल का क्रम फिर से बदलने के लिए उन्हें दबाकर रखें और खींचें"</string>
     <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>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 435fc56..7ad2fe2 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -429,9 +429,12 @@
     <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_limit_reached_title" msgid="7374910700117359177">"Dosegnuto je ograničenje korisnika"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="one">Možete dodati najviše <xliff:g id="COUNT">%d</xliff:g> korisnika.</item>
+      <item quantity="few">Možete dodati najviše <xliff:g id="COUNT">%d</xliff:g> korisnika.</item>
+      <item quantity="other">Možete dodati najviše <xliff:g id="COUNT">%d</xliff:g> korisnika.</item>
+    </plurals>
     <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>
@@ -737,8 +740,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"Zadržite i povucite da biste preuredili pločice"</string>
     <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>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 6574c97..f5fad27 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -426,9 +426,11 @@
     <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_limit_reached_title" msgid="7374910700117359177">"Maximális felhasználószám elérve"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="other">Legfeljebb <xliff:g id="COUNT">%d</xliff:g> felhasználót adhat hozzá.</item>
+      <item quantity="one">Csak egy felhasználót lehet létrehozni.</item>
+    </plurals>
     <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>
@@ -732,8 +734,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"Tartsa lenyomva, és húzza a mozaikok átrendezéséhez"</string>
     <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>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 20209a2..5eeca4c 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -426,9 +426,11 @@
     <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_limit_reached_title" msgid="7374910700117359177">"Սահմանաչափը սպառված է"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="one">Հնարավոր է ավելացնել առավելագույնը <xliff:g id="COUNT">%d</xliff:g> օգտատեր։</item>
+      <item quantity="other">Հնարավոր է ավելացնել առավելագույնը <xliff:g id="COUNT">%d</xliff:g> օգտատեր։</item>
+    </plurals>
     <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>
@@ -732,8 +734,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"Պահեք և քաշեք՝ սալիկները վերադասավորելու համար"</string>
     <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>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 5111ed6..5a61a64 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -426,9 +426,11 @@
     <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_limit_reached_title" msgid="7374910700117359177">"Batas pengguna tercapai"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="other">Anda dapat menambahkan hingga <xliff:g id="COUNT">%d</xliff:g> pengguna.</item>
+      <item quantity="one">Hanya dapat membuat satu pengguna.</item>
+    </plurals>
     <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>
@@ -732,8 +734,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"Tahan dan tarik untuk mengatur ulang tile"</string>
     <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>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index 508b2bd..fb83ff07 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -426,9 +426,11 @@
     <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_limit_reached_title" msgid="7374910700117359177">"Notandahámarki náð"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="one">Þú getur bætt við allt að <xliff:g id="COUNT">%d</xliff:g> notanda.</item>
+      <item quantity="other">Þú getur bætt við allt að <xliff:g id="COUNT">%d</xliff:g> notendum.</item>
+    </plurals>
     <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>
@@ -732,8 +734,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"Haltu og dragðu til að endurraða flísum"</string>
     <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>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 467ca8d..c081eaa 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -428,9 +428,11 @@
     <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_limit_reached_title" msgid="7374910700117359177">"Limite di utenti raggiunto"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="other">Puoi aggiungere fino a <xliff:g id="COUNT">%d</xliff:g> utenti.</item>
+      <item quantity="one">È possibile creare un solo utente.</item>
+    </plurals>
     <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>
@@ -734,8 +736,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"Tieni premuto e trascina per riordinare i riquadri"</string>
     <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>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 46d930e..d3d18ae 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -432,9 +432,13 @@
     <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_limit_reached_title" msgid="7374910700117359177">"הגעת למגבלת המשתמשים שניתן להוסיף"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="two">ניתן להוסיף עד <xliff:g id="COUNT">%d</xliff:g> משתמשים.</item>
+      <item quantity="many">ניתן להוסיף עד <xliff:g id="COUNT">%d</xliff:g> משתמשים.</item>
+      <item quantity="other">ניתן להוסיף עד <xliff:g id="COUNT">%d</xliff:g> משתמשים.</item>
+      <item quantity="one">ניתן ליצור רק משתמש אחד.</item>
+    </plurals>
     <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>
@@ -742,8 +746,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"יש ללחוץ ולגרור כדי לסדר מחדש את האריחים"</string>
     <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>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index b34a5b4..8377f07 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -428,9 +428,11 @@
     <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_limit_reached_title" msgid="7374910700117359177">"ユーザー数が上限に達しました"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="other">最大 <xliff:g id="COUNT">%d</xliff:g> 人のユーザーを追加できます。</item>
+      <item quantity="one">作成できるユーザーは 1 人のみです。</item>
+    </plurals>
     <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,8 +736,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"タイルを並べ替えるには押し続けながらドラッグ"</string>
     <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>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index e490dac..fb880c7 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -426,9 +426,11 @@
     <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_limit_reached_title" msgid="7374910700117359177">"მიღწეულია მომხმარებელთა ლიმიტი"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="other">შესაძლებელია <xliff:g id="COUNT">%d</xliff:g>-მდე მომხმარებლის დამატება.</item>
+      <item quantity="one">შესაძლებელია მხოლოდ ერთი მომხმარებლის შექმნა.</item>
+    </plurals>
     <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>
@@ -732,8 +734,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"ფილების გადაწყობა შეგიძლიათ მათი ჩავლებით გადატანით"</string>
     <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>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index eb50c28..6e372d7 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -426,9 +426,11 @@
     <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_limit_reached_title" msgid="7374910700117359177">"Пайдаланушылар саны шегіне жетті"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> пайдаланушыға дейін енгізуге болады.</item>
+      <item quantity="one">Тек бір пайдаланушыны жасауға болады.</item>
+    </plurals>
     <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>
@@ -732,8 +734,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"Бөлшектердің ретін өзгерту үшін оны басып тұрып сүйреңіз"</string>
     <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>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index 4f1d71d..eb9ed61 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -426,9 +426,11 @@
     <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_limit_reached_title" msgid="7374910700117359177">"​បាន​ឈាន​ដល់ចំនួន​កំណត់អ្នកប្រើប្រាស់"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="other">អ្នកអាចបញ្ចូល​អ្នក​ប្រើប្រាស់បាន​រហូតដល់ <xliff:g id="COUNT">%d</xliff:g> នាក់។</item>
+      <item quantity="one">អាច​បង្កើត​អ្នក​ប្រើប្រាស់​បាន​​តែម្នាក់ប៉ុណ្ណោះ។</item>
+    </plurals>
     <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>
@@ -732,8 +734,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"ចុច​ឱ្យ​ជាប់ រួចអូស​ដើម្បី​រៀបចំ​ប្រអប់​ឡើងវិញ"</string>
     <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>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index 49a9419b..c63dbe9 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -426,9 +426,11 @@
     <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_limit_reached_title" msgid="7374910700117359177">"ಬಳಕೆದಾರರ ಮಿತಿ ತಲುಪಿದೆ"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="one">ನೀವು <xliff:g id="COUNT">%d</xliff:g> ಬಳಕೆದಾರರವರೆಗೆ ಸೇರಿಸಬಹುದು.</item>
+      <item quantity="other">ನೀವು <xliff:g id="COUNT">%d</xliff:g> ಬಳಕೆದಾರರವರೆಗೆ ಸೇರಿಸಬಹುದು.</item>
+    </plurals>
     <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>
@@ -732,8 +734,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"ಟೈಲ್‌ಗಳನ್ನು ಮರುಹೊಂದಿಸಲು ಹೋಲ್ಡ್‌ ಮಾಡಿ ಮತ್ತು ಡ್ರ್ಯಾಗ್‌ ಮಾಡಿ"</string>
     <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>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index ad98bce..77c983e 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -428,9 +428,11 @@
     <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_limit_reached_title" msgid="7374910700117359177">"사용자 제한 도달"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="other">사용자를 <xliff:g id="COUNT">%d</xliff:g>명까지 추가할 수 있습니다.</item>
+      <item quantity="one">사용자를 한 명만 만들 수 있습니다.</item>
+    </plurals>
     <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,8 +736,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"길게 터치하고 드래그하여 타일을 다시 정렬"</string>
     <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>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index 0bbdc91..e334da4 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -426,9 +426,11 @@
     <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_limit_reached_title" msgid="7374910700117359177">"Дагы колдонуучу кошууга болбойт"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> колдонуучуга чейин кошууга болот.</item>
+      <item quantity="one">Бир колдонуучуну гана кошууга болот.</item>
+    </plurals>
     <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>
@@ -732,8 +734,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"Мозаикаларды иреттөө үчүн кармап туруп, сүйрөңүз"</string>
     <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>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index 12c67db..56f9e1d 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -426,9 +426,11 @@
     <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_limit_reached_title" msgid="7374910700117359177">"ຮອດຂີດຈຳກັດຜູ້ໃຊ້ແລ້ວ"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="other">ທ່ານສາມາດເພີ່ມໄດ້ສູງສຸດ <xliff:g id="COUNT">%d</xliff:g> ຄົນ.</item>
+      <item quantity="one">ສາມາດສ້າງໄດ້ໜຶ່ງຜູ້ໃຊ້ເທົ່ານັ້ນ.</item>
+    </plurals>
     <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>
@@ -732,8 +734,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"ກົດຄ້າງໄວ້ແລ້ວລາກເພື່ອຈັດຮຽງໃໝ່"</string>
     <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>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index f59b1ad..b8ae38b 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -432,9 +432,13 @@
     <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_limit_reached_title" msgid="7374910700117359177">"Pasiekta naudotojų riba"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="one">Galite pridėti iki <xliff:g id="COUNT">%d</xliff:g> naudotojo.</item>
+      <item quantity="few">Galite pridėti iki <xliff:g id="COUNT">%d</xliff:g> naudotojų.</item>
+      <item quantity="many">Galite pridėti iki <xliff:g id="COUNT">%d</xliff:g> naudotojo.</item>
+      <item quantity="other">Galite pridėti iki <xliff:g id="COUNT">%d</xliff:g> naudotojų.</item>
+    </plurals>
     <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>
@@ -742,8 +746,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"Norėdami pertvarkyti išklot., laikykite nuspaudę ir vilkite"</string>
     <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>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 0075094..4a0ee10 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -429,9 +429,12 @@
     <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_limit_reached_title" msgid="7374910700117359177">"Sasniegts lietotāju ierobežojums"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="zero">Varat pievienot ne vairāk kā <xliff:g id="COUNT">%d</xliff:g> lietotājus.</item>
+      <item quantity="one">Varat pievienot ne vairāk kā <xliff:g id="COUNT">%d</xliff:g> lietotāju.</item>
+      <item quantity="other">Varat pievienot ne vairāk kā <xliff:g id="COUNT">%d</xliff:g> lietotājus.</item>
+    </plurals>
     <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>
@@ -737,8 +740,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"Lai pārkārtotu elementus, turiet un velciet tos"</string>
     <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>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index 68dc653..bf9cc35 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -426,9 +426,11 @@
     <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_limit_reached_title" msgid="7374910700117359177">"Достигнато ограничување на корисник"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="one">Може да додадете најмногу <xliff:g id="COUNT">%d</xliff:g> корисник.</item>
+      <item quantity="other">Може да додадете најмногу <xliff:g id="COUNT">%d</xliff:g> корисници.</item>
+    </plurals>
     <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>
@@ -732,8 +734,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"Задржете и влечете за да ги преуредите плочките"</string>
     <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>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index 507cbbf..fefd073 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -426,9 +426,11 @@
     <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_limit_reached_title" msgid="7374910700117359177">"ഉപയോക്തൃ പരിധി എത്തി"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="other">നിങ്ങൾക്ക് <xliff:g id="COUNT">%d</xliff:g> ഉപയോക്താക്കളെ വരെ ചേർക്കാനാവും.</item>
+      <item quantity="one">ഒരു ഉപയോക്താവിന് മാത്രമേ സൃഷ്‌ടിക്കാനാവൂ.</item>
+    </plurals>
     <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>
@@ -732,8 +734,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"ടൈലുകൾ പുനഃക്രമീകരിക്കാൻ അമർത്തിപ്പിടിച്ച് വലിച്ചിടുക"</string>
     <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>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index 8e27efe..e86dc64 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -424,9 +424,11 @@
     <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_limit_reached_title" msgid="7374910700117359177">"Хэрэглэгчийн хязгаарт хүрсэн"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="other">Та <xliff:g id="COUNT">%d</xliff:g> хүртэлх хэрэглэгч нэмэх боломжтой.</item>
+      <item quantity="one">Зөвхөн нэг хэрэглэгч үүсгэх боломжтой.</item>
+    </plurals>
     <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>
@@ -730,8 +732,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"Хавтангуудыг дахин засварлахын тулд дараад чирнэ үү"</string>
     <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>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index 1c16dc2..a9f9af4 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -426,9 +426,11 @@
     <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_limit_reached_title" msgid="7374910700117359177">"वापरकर्ता मर्यादा गाठली"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="one">तुम्ही <xliff:g id="COUNT">%d</xliff:g> वापरकर्त्यापर्यंत जोडू शकता.</item>
+      <item quantity="other">तुम्ही <xliff:g id="COUNT">%d</xliff:g> वापरकर्त्यांपर्यंत जोडू शकता.</item>
+    </plurals>
     <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>
@@ -732,8 +734,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"टाइलची पुनर्रचना करण्यासाठी धरून ठेवा आणि ड्रॅग करा"</string>
     <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>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 947c0ff..6ec7889 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -426,9 +426,11 @@
     <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_limit_reached_title" msgid="7374910700117359177">"Had pengguna dicapai"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="other">Anda boleh menambah sehingga <xliff:g id="COUNT">%d</xliff:g> pengguna.</item>
+      <item quantity="one">Hanya satu pengguna yang boleh dibuat.</item>
+    </plurals>
     <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>
@@ -732,8 +734,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"Tahan dan seret untuk mengatur semula jubin"</string>
     <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>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index 8264240..7afb3b9 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -426,9 +426,11 @@
     <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_limit_reached_title" msgid="7374910700117359177">"အသုံးပြုသူ အကန့်အသတ် ပြည့်သွားပါပြီ"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="other">အသုံးပြုသူ <xliff:g id="COUNT">%d</xliff:g> ဦးအထိ ထည့်နိုင်သည်။</item>
+      <item quantity="one">အသုံးပြုသူ တစ်ဦးသာ ထည့်နိုင်သည်။</item>
+    </plurals>
     <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>
@@ -732,8 +734,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"အကွက်ငယ်များ ပြန်စီစဉ်ရန် ဖိပြီးဆွဲပါ"</string>
     <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>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 8c8e905..b817877 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -426,9 +426,11 @@
     <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_limit_reached_title" msgid="7374910700117359177">"Grensen for antall brukere er nådd"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="other">Du kan legge til opptil <xliff:g id="COUNT">%d</xliff:g> brukere.</item>
+      <item quantity="one">Du kan bare opprette én bruker.</item>
+    </plurals>
     <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>
@@ -732,8 +734,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"Hold og dra for å endre rekkefølge for ruter"</string>
     <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>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index 1b8149e..6cc405f 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -426,9 +426,11 @@
     <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_limit_reached_title" msgid="7374910700117359177">"प्रयोगकर्ताको सीमा पुग्यो"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="other">तपाईं अधिकतम <xliff:g id="COUNT">%d</xliff:g> प्रयोगहरू मात्र थप्न सक्नुहुन्छ।</item>
+      <item quantity="one">एउटा प्रयोगकर्ता मात्र सिर्जना गर्न सकिन्छ।</item>
+    </plurals>
     <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>
@@ -732,8 +734,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"टाइलहरू पुनः क्रमबद्ध गर्न होल्ड गरी ड्र्याग गर्नुहोस्"</string>
     <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>
diff --git a/packages/SystemUI/res/values-night/colors.xml b/packages/SystemUI/res/values-night/colors.xml
index 45d2185..2c5120d 100644
--- a/packages/SystemUI/res/values-night/colors.xml
+++ b/packages/SystemUI/res/values-night/colors.xml
@@ -25,10 +25,10 @@
     <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>
+    <color name="notification_material_background_dimmed_color">#aa000000</color>
 
     <!-- The color of the dividing line between grouped notifications while . -->
-    <color name="notification_divider_color">#000</color>
+    <color name="notification_divider_color">#212121</color>
 
     <!-- The background color of the notification shade -->
     <color name="notification_shade_background_color">#181818</color>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 61dba4a..e8c6f8d 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -426,9 +426,11 @@
     <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_limit_reached_title" msgid="7374910700117359177">"Gebruikerslimiet bereikt"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="other">Je kunt maximaal <xliff:g id="COUNT">%d</xliff:g> gebruikers toevoegen.</item>
+      <item quantity="one">Er kan maar één gebruiker worden gemaakt.</item>
+    </plurals>
     <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>
@@ -732,8 +734,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"Houd vast en sleep om tegels opnieuw in te delen"</string>
     <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>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index 7f79090..277181f 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -426,9 +426,11 @@
     <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_limit_reached_title" msgid="7374910700117359177">"ଉପଯୋଗକର୍ତ୍ତା ସୀମାରେ ପହଞ୍ଚିଛି"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="other">କେବଳ <xliff:g id="COUNT">%d</xliff:g> ଉପଯୋଗକର୍ତ୍ତା ହିଁ ତିଆରି କରିହେବ।</item>
+      <item quantity="one">କେବଳ ଜଣେ ଉପଯୋଗକର୍ତ୍ତା ହିଁ ତିଆରି କରିହେବ।</item>
+    </plurals>
     <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>
@@ -732,8 +734,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"ଟାଇଲ୍‍ ପୁଣି ଆୟୋଜିତ କରିବାକୁ ଦାବିଧରି ଟାଣନ୍ତୁ"</string>
     <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>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index c6ec96e..6509871 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -426,9 +426,11 @@
     <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_limit_reached_title" msgid="7374910700117359177">"ਵਰਤੋਂਕਾਰ ਸ਼ਾਮਲ ਕਰਨ ਦੀ ਸੀਮਾ ਪੂਰੀ ਹੋਈ"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="one">ਤੁਸੀਂ <xliff:g id="COUNT">%d</xliff:g> ਤੱਕ ਵਰਤੋਂਕਾਰ ਸ਼ਾਮਲ ਕਰ ਸਕਦੇ ਹੋ।</item>
+      <item quantity="other">ਤੁਸੀਂ <xliff:g id="COUNT">%d</xliff:g> ਤੱਕ ਵਰਤੋਂਕਾਰਾਂ ਨੂੰ ਸ਼ਾਮਲ ਕਰ ਸਕਦੇ ਹੋ।</item>
+    </plurals>
     <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>
@@ -732,8 +734,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"ਟਾਇਲਾਂ ਨੂੰ ਮੁੜ-ਵਿਵਸਥਿਤ ਕਰਨ ਲਈ ਫੜ੍ਹ ਕੇ ਘਸੀਟੋ"</string>
     <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>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 33a8117..2959a8d 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -432,9 +432,13 @@
     <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_limit_reached_title" msgid="7374910700117359177">"Osiągnięto limit użytkowników"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="few">Możesz dodać maksymalnie <xliff:g id="COUNT">%d</xliff:g> użytkowników.</item>
+      <item quantity="many">Możesz dodać maksymalnie <xliff:g id="COUNT">%d</xliff:g> użytkowników.</item>
+      <item quantity="other">Możesz dodać maksymalnie <xliff:g id="COUNT">%d</xliff:g> użytkownika.</item>
+      <item quantity="one">Można utworzyć tylko jednego użytkownika.</item>
+    </plurals>
     <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>
@@ -742,8 +746,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"Przytrzymaj i przeciągnij, by przestawić kafelki"</string>
     <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>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 60825b7..ba50c13 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -160,7 +160,7 @@
     <string name="data_connection_roaming" msgid="6037232010953697354">"Roaming"</string>
     <string name="data_connection_edge" msgid="871835227939216682">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
-    <string name="accessibility_no_sim" msgid="8274017118472455155">"Sem SIM."</string>
+    <string name="accessibility_no_sim" msgid="8274017118472455155">"Sem chip."</string>
     <string name="accessibility_cell_data" msgid="5326139158682385073">"Dados móveis"</string>
     <string name="accessibility_cell_data_on" msgid="5927098403452994422">"Dados móveis ativados"</string>
     <string name="cell_data_off_content_description" msgid="4356113230238585072">"Dados móveis desativados"</string>
@@ -168,7 +168,7 @@
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Tethering Bluetooth."</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Modo avião."</string>
     <string name="accessibility_vpn_on" msgid="5993385083262856059">"VPN ativada."</string>
-    <string name="accessibility_no_sims" msgid="3957997018324995781">"Sem cartão SIM."</string>
+    <string name="accessibility_no_sims" msgid="3957997018324995781">"Sem chip."</string>
     <string name="carrier_network_change_mode" msgid="8149202439957837762">"Alteração de rede da operadora"</string>
     <string name="accessibility_battery_details" msgid="7645516654955025422">"Abrir detalhes da bateria"</string>
     <string name="accessibility_battery_level" msgid="7451474187113371965">"Bateria em <xliff:g id="NUMBER">%d</xliff:g> por cento."</string>
@@ -428,9 +428,11 @@
     <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_limit_reached_title" msgid="7374910700117359177">"Limite de usuários atingido"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="one">É possível adicionar até <xliff:g id="COUNT">%d</xliff:g> usuário.</item>
+      <item quantity="other">É possível adicionar até <xliff:g id="COUNT">%d</xliff:g> usuários.</item>
+    </plurals>
     <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>
@@ -734,8 +736,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"Mantenha pressionado e arraste para reorganizar os blocos"</string>
     <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>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 4be7281..a03dba2 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -426,9 +426,11 @@
     <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_limit_reached_title" msgid="7374910700117359177">"Limite de utilizadores alcançado"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="other">Pode adicionar até <xliff:g id="COUNT">%d</xliff:g> utilizadores.</item>
+      <item quantity="one">Apenas é possível criar um utilizador.</item>
+    </plurals>
     <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>
@@ -732,8 +734,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"Tocar sem soltar e arrastar para reorganizar os mosaicos"</string>
     <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>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 60825b7..ba50c13 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -160,7 +160,7 @@
     <string name="data_connection_roaming" msgid="6037232010953697354">"Roaming"</string>
     <string name="data_connection_edge" msgid="871835227939216682">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
-    <string name="accessibility_no_sim" msgid="8274017118472455155">"Sem SIM."</string>
+    <string name="accessibility_no_sim" msgid="8274017118472455155">"Sem chip."</string>
     <string name="accessibility_cell_data" msgid="5326139158682385073">"Dados móveis"</string>
     <string name="accessibility_cell_data_on" msgid="5927098403452994422">"Dados móveis ativados"</string>
     <string name="cell_data_off_content_description" msgid="4356113230238585072">"Dados móveis desativados"</string>
@@ -168,7 +168,7 @@
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Tethering Bluetooth."</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Modo avião."</string>
     <string name="accessibility_vpn_on" msgid="5993385083262856059">"VPN ativada."</string>
-    <string name="accessibility_no_sims" msgid="3957997018324995781">"Sem cartão SIM."</string>
+    <string name="accessibility_no_sims" msgid="3957997018324995781">"Sem chip."</string>
     <string name="carrier_network_change_mode" msgid="8149202439957837762">"Alteração de rede da operadora"</string>
     <string name="accessibility_battery_details" msgid="7645516654955025422">"Abrir detalhes da bateria"</string>
     <string name="accessibility_battery_level" msgid="7451474187113371965">"Bateria em <xliff:g id="NUMBER">%d</xliff:g> por cento."</string>
@@ -428,9 +428,11 @@
     <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_limit_reached_title" msgid="7374910700117359177">"Limite de usuários atingido"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="one">É possível adicionar até <xliff:g id="COUNT">%d</xliff:g> usuário.</item>
+      <item quantity="other">É possível adicionar até <xliff:g id="COUNT">%d</xliff:g> usuários.</item>
+    </plurals>
     <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>
@@ -734,8 +736,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"Mantenha pressionado e arraste para reorganizar os blocos"</string>
     <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>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 618c890..149803b 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -431,9 +431,12 @@
     <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_limit_reached_title" msgid="7374910700117359177">"Ați atins limita de utilizatori"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="few">Puteți adăuga maximum <xliff:g id="COUNT">%d</xliff:g> utilizatori.</item>
+      <item quantity="other">Puteți adăuga maximum <xliff:g id="COUNT">%d</xliff:g> de utilizatori.</item>
+      <item quantity="one">Poate fi creat doar un utilizator.</item>
+    </plurals>
     <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>
@@ -739,8 +742,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"Țineți apăsat și trageți pentru a rearanja piesele"</string>
     <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>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index c754c36..7a756cd 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -434,9 +434,13 @@
     <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_limit_reached_title" msgid="7374910700117359177">"Достигнут лимит"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="one">Можно добавить не более <xliff:g id="COUNT">%d</xliff:g> пользователя.</item>
+      <item quantity="few">Можно добавить не более <xliff:g id="COUNT">%d</xliff:g> пользователей.</item>
+      <item quantity="many">Можно добавить не более <xliff:g id="COUNT">%d</xliff:g> пользователей.</item>
+      <item quantity="other">Можно добавить не более <xliff:g id="COUNT">%d</xliff:g> пользователя.</item>
+    </plurals>
     <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>
@@ -744,8 +748,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"Чтобы изменить порядок элементов, перетащите их"</string>
     <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>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index 8ec763d..e29aeda 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -426,9 +426,11 @@
     <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_limit_reached_title" msgid="7374910700117359177">"පරිශීලක සීමාවට ළඟා විය"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="one">ඔබට පරිශීලකයින් <xliff:g id="COUNT">%d</xliff:g>ක් දක්වා එක් කළ හැකිය.</item>
+      <item quantity="other">ඔබට පරිශීලකයින් <xliff:g id="COUNT">%d</xliff:g>ක් දක්වා එක් කළ හැකිය.</item>
+    </plurals>
     <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>
@@ -732,8 +734,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"ටයිල් නැවත සකස් කිරීමට අල්ලාගෙන සිට අදින්න"</string>
     <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>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index de32ae5..8193e3f 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -434,9 +434,13 @@
     <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_limit_reached_title" msgid="7374910700117359177">"Dosiahnutý limit počtu používateľov"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="few">Môžete pridať maximálne <xliff:g id="COUNT">%d</xliff:g> používateľov.</item>
+      <item quantity="many">You can add up to <xliff:g id="COUNT">%d</xliff:g> users.</item>
+      <item quantity="other">Môžete pridať maximálne <xliff:g id="COUNT">%d</xliff:g> používateľov.</item>
+      <item quantity="one">Môžete vytvoriť iba jedného používateľa.</item>
+    </plurals>
     <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>
@@ -744,8 +748,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"Dlaždice môžete usporiadať pridržaním a presunutím"</string>
     <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>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 11de2d5..71694417 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -434,9 +434,13 @@
     <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_limit_reached_title" msgid="7374910700117359177">"Omejitev uporabnikov je dosežena"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="one">Dodate lahko do <xliff:g id="COUNT">%d</xliff:g> uporabnika.</item>
+      <item quantity="two">Dodate lahko do <xliff:g id="COUNT">%d</xliff:g> uporabnika.</item>
+      <item quantity="few">Dodate lahko do <xliff:g id="COUNT">%d</xliff:g> uporabnike.</item>
+      <item quantity="other">Dodate lahko do <xliff:g id="COUNT">%d</xliff:g> uporabnikov.</item>
+    </plurals>
     <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>
@@ -744,8 +748,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"Držite in povlecite, da prerazporedite ploščice"</string>
     <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>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index ab7076c..f2903ef 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -426,9 +426,11 @@
     <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_limit_reached_title" msgid="7374910700117359177">"U arrit kufiri i përdoruesve"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="other">Mund të shtosh deri në <xliff:g id="COUNT">%d</xliff:g> përdorues.</item>
+      <item quantity="one">Mund të krijohet vetëm një përdorues.</item>
+    </plurals>
     <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>
@@ -732,8 +734,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"Mbaje të shtypur dhe zvarrit për të risistemuar pllakëzat"</string>
     <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>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 2dbdc3d..e77b080 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -429,9 +429,12 @@
     <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_limit_reached_title" msgid="7374910700117359177">"Достигнут максимални број корисника"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="one">Можете да додате највише <xliff:g id="COUNT">%d</xliff:g> корисника.</item>
+      <item quantity="few">Можете да додате највише <xliff:g id="COUNT">%d</xliff:g> корисника.</item>
+      <item quantity="other">Можете да додате највише <xliff:g id="COUNT">%d</xliff:g> корисника.</item>
+    </plurals>
     <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>
@@ -737,8 +740,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"Задржите и превуците да бисте променили распоред плочица"</string>
     <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>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 4b05e27..ccc498e 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -426,9 +426,11 @@
     <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_limit_reached_title" msgid="7374910700117359177">"Användargränsen har nåtts"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="other">Det går att lägga till upp till <xliff:g id="COUNT">%d</xliff:g> användare.</item>
+      <item quantity="one">Det går bara att skapa en användare.</item>
+    </plurals>
     <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>
@@ -732,8 +734,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"Ordna om rutor genom att trycka och dra"</string>
     <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>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 7cb38b2..83e9997 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -426,9 +426,11 @@
     <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_limit_reached_title" msgid="7374910700117359177">"Umefikia kima cha juu cha watumiaji"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="other">Unaruhusiwa kuongeza hadi watumiaji <xliff:g id="COUNT">%d</xliff:g>.</item>
+      <item quantity="one">Unaruhusiwa kuongeza mtumiaji mmoja pekee.</item>
+    </plurals>
     <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>
@@ -732,8 +734,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"Shikilia na uburute ili upange vigae upya"</string>
     <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>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index 84041a9..6f06ab5 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -426,9 +426,11 @@
     <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_limit_reached_title" msgid="7374910700117359177">"பயனர் வரம்பை அடைந்துவிட்டீர்கள்"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> பயனர்கள் வரை சேர்க்க முடியும்.</item>
+      <item quantity="one">ஒரு பயனரை மட்டுமே சேர்க்க முடியும்.</item>
+    </plurals>
     <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>
@@ -732,8 +734,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"கட்டங்களை மறுவரிசைப்படுத்த அவற்றைப் பிடித்து இழுக்கவும்"</string>
     <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>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index fc48ac1..7c09699 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -426,9 +426,11 @@
     <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_limit_reached_title" msgid="7374910700117359177">"వినియోగదారు పరిమితిని చేరుకున్నారు"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="other">మీరు <xliff:g id="COUNT">%d</xliff:g> వినియోగదారుల వరకు జోడించవచ్చు.</item>
+      <item quantity="one">ఒక్క వినియోగదారుని మాత్రమే సృష్టించవచ్చు.</item>
+    </plurals>
     <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>
@@ -732,8 +734,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"టైల్‌ల క్రమం మార్చడానికి వాటిని పట్టుకుని, లాగండి"</string>
     <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>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index bf61986..1d59868 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -426,14 +426,16 @@
     <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_limit_reached_title" msgid="7374910700117359177">"ถึงขีดจำกัดผู้ใช้แล้ว"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="other">คุณเพิ่มผู้ใช้ได้สูงสุด <xliff:g id="COUNT">%d</xliff:g> คน</item>
+      <item quantity="one">สร้างผู้ใช้ได้เพียง 1 คนเท่านั้น</item>
+    </plurals>
     <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>
     <string name="battery_saver_notification_title" msgid="8614079794522291840">"เปิดโหมดประหยัดแบตเตอรี่อยู่"</string>
-    <string name="battery_saver_notification_text" msgid="820318788126672692">"ลดการใช้แบตเตอรี่และข้อมูลแบ็กกราวด์"</string>
+    <string name="battery_saver_notification_text" msgid="820318788126672692">"ลดการใช้แบตเตอรี่และอินเทอร์เน็ตที่ใช้งานอยู่เบื้องหลัง"</string>
     <string name="battery_saver_notification_action_text" msgid="132118784269455533">"ปิดโหมดประหยัดแบตเตอรี่"</string>
     <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> จะเริ่มจับภาพทุกอย่างที่แสดงบนหน้าจอ"</string>
     <string name="media_projection_remember_text" msgid="3103510882172746752">"ไม่ต้องแสดงข้อความนี้อีก"</string>
@@ -646,7 +648,7 @@
     <string name="battery_panel_title" msgid="7944156115535366613">"การใช้งานแบตเตอรี่"</string>
     <string name="battery_detail_charging_summary" msgid="1279095653533044008">"ไม่สามารถใช้โหมดประหยัดแบตเตอรี่ระหว่างการชาร์จ"</string>
     <string name="battery_detail_switch_title" msgid="6285872470260795421">"โหมดประหยัดแบตเตอรี่"</string>
-    <string name="battery_detail_switch_summary" msgid="9049111149407626804">"ลดประสิทธิภาพการทำงานและข้อมูลแบ็กกราวด์"</string>
+    <string name="battery_detail_switch_summary" msgid="9049111149407626804">"ลดประสิทธิภาพการทำงานและอินเทอร์เน็ตที่ใช้งานอยู่เบื้องหลัง"</string>
     <string name="keyboard_key_button_template" msgid="6230056639734377300">"ปุ่ม <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="keyboard_key_home" msgid="2243500072071305073">"Home"</string>
     <string name="keyboard_key_back" msgid="2337450286042721351">"กลับ"</string>
@@ -732,8 +734,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"กดชิ้นส่วนค้างไว้แล้วลากไปเพื่อจัดลำดับใหม่"</string>
     <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>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index fef7632..013acd4 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -426,9 +426,11 @@
     <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_limit_reached_title" msgid="7374910700117359177">"Naabot na ang limitasyon sa user"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="one">Maaari kang magdagdag ng hanggang <xliff:g id="COUNT">%d</xliff:g> user.</item>
+      <item quantity="other">Maaari kang magdagdag ng hanggang <xliff:g id="COUNT">%d</xliff:g> na user.</item>
+    </plurals>
     <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>
@@ -732,8 +734,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"Pindutin nang matagal at i-drag para ayusing muli ang tile"</string>
     <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>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index fd8ab73..9030113 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -426,9 +426,11 @@
     <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_limit_reached_title" msgid="7374910700117359177">"Kullanıcı sınırına ulaşıldı"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="other">En fazla <xliff:g id="COUNT">%d</xliff:g> kullanıcı ekleyebilirsiniz.</item>
+      <item quantity="one">Yalnızca bir kullanıcı oluşturulabilir.</item>
+    </plurals>
     <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>
@@ -732,8 +734,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"Blokları yeniden düzenlemek için basılı tutun ve sürükleyin"</string>
     <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>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 7d61d37..cf21c0f 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -434,9 +434,13 @@
     <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_limit_reached_title" msgid="7374910700117359177">"Ви досягли ліміту користувачів"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="one">Можна додати до <xliff:g id="COUNT">%d</xliff:g> користувача.</item>
+      <item quantity="few">Можна додати до <xliff:g id="COUNT">%d</xliff:g> користувачів.</item>
+      <item quantity="many">Можна додати до <xliff:g id="COUNT">%d</xliff:g> користувачів.</item>
+      <item quantity="other">Можна додати до <xliff:g id="COUNT">%d</xliff:g> користувача.</item>
+    </plurals>
     <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>
@@ -744,8 +748,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"Щоб упорядковувати компоненти, перетягуйте їх"</string>
     <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>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index dbdc034..d2ee8c7 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -426,9 +426,11 @@
     <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_limit_reached_title" msgid="7374910700117359177">"صارف کی حد مکمل ہو گئی"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="other">صرف <xliff:g id="COUNT">%d</xliff:g> صارفین بنائے جا سکتے ہیں۔</item>
+      <item quantity="one">صرف ایک صارف بنایا جا سکتا ہے۔</item>
+    </plurals>
     <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>
@@ -732,8 +734,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"ٹائلز کو دوبارہ ترتیب دینے کیلئے پکڑ کر گھسیٹیں"</string>
     <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>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index f4403e7..2c45ab8 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -428,9 +428,11 @@
     <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_limit_reached_title" msgid="7374910700117359177">"Limitga yetib keldi"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> tagacha foydalanuvchi qo‘shish mumkin.</item>
+      <item quantity="one">Faqat bitta foydalanuvchi yaratish mumkin.</item>
+    </plurals>
     <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>
@@ -734,8 +736,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"Qayta tartiblash uchun ushlab torting"</string>
     <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>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index d8fd0eb..8c5e10d 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -204,8 +204,8 @@
     <string name="accessibility_quick_settings_wifi_changed_on" msgid="6440117170789528622">"Đã bật Wifi."</string>
     <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Di động <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
     <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Pin <xliff:g id="STATE">%s</xliff:g>."</string>
-    <string name="accessibility_quick_settings_airplane_off" msgid="7786329360056634412">"Chế độ trên máy bay tắt."</string>
-    <string name="accessibility_quick_settings_airplane_on" msgid="6406141469157599296">"Chế độ trên máy bay bật."</string>
+    <string name="accessibility_quick_settings_airplane_off" msgid="7786329360056634412">"Chế độ trên máy bay đang tắt."</string>
+    <string name="accessibility_quick_settings_airplane_on" msgid="6406141469157599296">"Chế độ trên máy bay đang bật."</string>
     <string name="accessibility_quick_settings_airplane_changed_off" msgid="66846307818850664">"Đã tắt chế độ trên máy bay."</string>
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"Đã bật chế độ trên máy bay."</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="2960643943620637020">"hoàn toàn tắt tiếng"</string>
@@ -426,9 +426,11 @@
     <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_limit_reached_title" msgid="7374910700117359177">"Đã đạt đến giới hạn người dùng"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="other">Bạn có thể thêm tối đa <xliff:g id="COUNT">%d</xliff:g> người dùng.</item>
+      <item quantity="one">Chỉ có thể tạo một người dùng.</item>
+    </plurals>
     <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>
@@ -732,8 +734,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"Giữ và kéo để sắp xếp lại các ô"</string>
     <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>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index c7443fe..6259bfd 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -426,9 +426,11 @@
     <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_limit_reached_title" msgid="7374910700117359177">"已达到用户数上限"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="other">您最多可以添加 <xliff:g id="COUNT">%d</xliff:g> 位用户。</item>
+      <item quantity="one">您只能创建一位用户。</item>
+    </plurals>
     <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>
@@ -732,8 +734,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"按住并拖动即可重新排列图块"</string>
     <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>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index dace26a..aa19f4f 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -428,9 +428,11 @@
     <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_limit_reached_title" msgid="7374910700117359177">"已達到使用者上限"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="other">您可以加入多達 <xliff:g id="COUNT">%d</xliff:g> 個使用者。</item>
+      <item quantity="one">只可以建立一個使用者。</item>
+    </plurals>
     <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,8 +736,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"按住並拖曳即可重新排列圖塊"</string>
     <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>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index c1be1fb..363c610 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -426,9 +426,11 @@
     <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_limit_reached_title" msgid="7374910700117359177">"已達使用者數量上限"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="other">最多可新增 <xliff:g id="COUNT">%d</xliff:g> 位使用者。</item>
+      <item quantity="one">只能建立 1 位使用者。</item>
+    </plurals>
     <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>
@@ -732,8 +734,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"按住並拖曳即可重新排列圖塊"</string>
     <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>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 5be16e3..0e4729b 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -426,9 +426,11 @@
     <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_limit_reached_title" msgid="7374910700117359177">"Kufinyelelwe kumkhawulo womsebenzisi"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="one">Ungangeza kufikela kubasebenzisi abangu-<xliff:g id="COUNT">%d</xliff:g>.</item>
+      <item quantity="other">Ungangeza kufikela kubasebenzisi abangu-<xliff:g id="COUNT">%d</xliff:g>.</item>
+    </plurals>
     <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>
@@ -732,8 +734,7 @@
     <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_rearrange_tiles" msgid="4566074720193667473">"Bamba uphinde uhudule ukuze uphinde ulungise amathayela"</string>
     <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>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 19492a0..11bd392 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -79,13 +79,6 @@
     <!-- Show camera affordance on Keyguard -->
     <bool name="config_keyguardShowCameraAffordance">false</bool>
 
-    <!-- Whether we should use SRC drawing mode when drawing the scrim behind. If this flag is set,
-         we change the canvas opacity so libhwui doesn't call glClear on our surface, and then we
-         draw the scrim with SRC to overwrite the whole buffer, which saves us a layer of overdraw.
-         However, SRC performs poorly on some devices, where it is more efficient to
-         glClear + SRC_OVER, in which case this flag should be disabled. -->
-    <bool name="config_status_bar_scrim_behind_use_src">true</bool>
-
     <!-- The length of the vibration when the notification pops open. -->
     <integer name="one_finger_pop_duration_ms">10</integer>
 
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index d051f07..26eadb5 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -361,7 +361,7 @@
     <dimen name="qs_quick_layout_width">-1px</dimen>
     <dimen name="qs_quick_tile_padding">12dp</dimen>
     <dimen name="qs_header_gear_translation">16dp</dimen>
-    <dimen name="qs_header_tile_margin_horizontal">0dp</dimen>
+    <dimen name="qs_header_tile_margin_horizontal">4dp</dimen>
     <dimen name="qs_page_indicator_width">16dp</dimen>
     <dimen name="qs_page_indicator_height">8dp</dimen>
     <dimen name="qs_tile_icon_size">24dp</dimen>
diff --git a/packages/SystemUI/shared/Android.bp b/packages/SystemUI/shared/Android.bp
index eb71698..710b5f7 100644
--- a/packages/SystemUI/shared/Android.bp
+++ b/packages/SystemUI/shared/Android.bp
@@ -24,20 +24,3 @@
     // 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/src/com/android/systemui/shared/system/InputConsumerController.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/InputConsumerController.java
index 0d25c91..0cde9da 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/InputConsumerController.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/InputConsumerController.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.shared.system;
 
+import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.WindowManager.INPUT_CONSUMER_PIP;
 import static android.view.WindowManager.INPUT_CONSUMER_RECENTS_ANIMATION;
 
@@ -146,8 +147,9 @@
         if (mInputEventReceiver == null) {
             final InputChannel inputChannel = new InputChannel();
             try {
-                mWindowManager.destroyInputConsumer(mName);
-                mWindowManager.createInputConsumer(mToken, mName, inputChannel);
+                // TODO(b/113087003): Support Picture-in-picture in multi-display.
+                mWindowManager.destroyInputConsumer(mName, DEFAULT_DISPLAY);
+                mWindowManager.createInputConsumer(mToken, mName, DEFAULT_DISPLAY, inputChannel);
             } catch (RemoteException e) {
                 Log.e(TAG, "Failed to create input consumer", e);
             }
@@ -164,7 +166,8 @@
     public void unregisterInputConsumer() {
         if (mInputEventReceiver != null) {
             try {
-                mWindowManager.destroyInputConsumer(mName);
+                // TODO(b/113087003): Support Picture-in-picture in multi-display.
+                mWindowManager.destroyInputConsumer(mName, DEFAULT_DISPLAY);
             } catch (RemoteException e) {
                 Log.e(TAG, "Failed to destroy input consumer", e);
             }
diff --git a/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java b/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java
index 5605b7a..ac8f024 100644
--- a/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java
+++ b/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java
@@ -39,6 +39,7 @@
 import com.android.internal.telephony.IccCardConstants.State;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.internal.util.EmergencyAffordanceManager;
+import com.android.systemui.util.EmergencyDialerConstants;
 
 /**
  * This class implements a smart emergency button that updates itself based
@@ -48,11 +49,13 @@
  */
 public class EmergencyButton extends Button {
     private static final Intent INTENT_EMERGENCY_DIAL = new Intent()
-            .setAction("com.android.phone.EmergencyDialer.DIAL")
+            .setAction(EmergencyDialerConstants.ACTION_DIAL)
             .setPackage("com.android.phone")
             .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                     | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
-                    | Intent.FLAG_ACTIVITY_CLEAR_TOP);
+                    | Intent.FLAG_ACTIVITY_CLEAR_TOP)
+            .putExtra(EmergencyDialerConstants.EXTRA_ENTRY_TYPE,
+                    EmergencyDialerConstants.ENTRY_TYPE_LOCKSCREEN_BUTTON);
 
     private static final String LOG_TAG = "EmergencyButton";
     private final EmergencyAffordanceManager mEmergencyAffordanceManager;
diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
index acc7b49..77f4bf5 100644
--- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
@@ -35,6 +35,8 @@
 import android.view.SurfaceHolder;
 import android.view.WindowManager;
 
+import com.android.internal.annotations.VisibleForTesting;
+
 import java.io.FileDescriptor;
 import java.io.IOException;
 import java.io.PrintWriter;
@@ -77,6 +79,13 @@
             unloadWallpaper(false /* forgetSize */);
         };
 
+        // Surface is rejected if size below a threshold on some devices (ie. 8px on elfin)
+        // set min to 64 px (CTS covers this)
+        @VisibleForTesting
+        static final int MIN_BACKGROUND_WIDTH = 64;
+        @VisibleForTesting
+        static final int MIN_BACKGROUND_HEIGHT = 64;
+
         Bitmap mBackground;
         int mBackgroundWidth = -1, mBackgroundHeight = -1;
         int mLastSurfaceWidth = -1, mLastSurfaceHeight = -1;
@@ -156,9 +165,9 @@
                 hasWallpaper = false;
             }
 
-            // Force the wallpaper to cover the screen in both dimensions
-            int surfaceWidth = Math.max(displayInfo.logicalWidth, mBackgroundWidth);
-            int surfaceHeight = Math.max(displayInfo.logicalHeight, mBackgroundHeight);
+            // Set surface size equal to bitmap size, prevent memory waste
+            int surfaceWidth = Math.max(MIN_BACKGROUND_WIDTH, mBackgroundWidth);
+            int surfaceHeight = Math.max(MIN_BACKGROUND_HEIGHT, mBackgroundHeight);
 
             // Used a fixed size surface, because we are special.  We can do
             // this because we know the current design of window animations doesn't
@@ -257,7 +266,8 @@
             drawFrame();
         }
 
-        private DisplayInfo getDefaultDisplayInfo() {
+        @VisibleForTesting
+        DisplayInfo getDefaultDisplayInfo() {
             mDefaultDisplay.getDisplayInfo(mTmpDisplayInfo);
             return mTmpDisplayInfo;
         }
@@ -420,7 +430,8 @@
             }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
         }
 
-        private void updateBitmap(Bitmap bitmap) {
+        @VisibleForTesting
+        void updateBitmap(Bitmap bitmap) {
             mBackground = null;
             mBackgroundWidth = -1;
             mBackgroundHeight = -1;
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogImpl.java b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogImpl.java
index 6e62b0d..8fe577a 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogImpl.java
@@ -36,7 +36,7 @@
  * FingerprintDialogView).
  */
 public class BiometricDialogImpl extends SystemUI implements CommandQueue.Callbacks {
-    private static final String TAG = "FingerprintDialogImpl";
+    private static final String TAG = "BiometricDialogImpl";
     private static final boolean DEBUG = true;
 
     private static final int MSG_SHOW_DIALOG = 1;
@@ -120,8 +120,8 @@
     }
 
     @Override
-    public void showBiometricDialog(Bundle bundle, IBiometricPromptReceiver receiver) {
-        if (DEBUG) Log.d(TAG, "showBiometricDialog");
+    public void showBiometricDialog(Bundle bundle, IBiometricPromptReceiver receiver, int type) {
+        if (DEBUG) Log.d(TAG, "showBiometricDialog, type: " + type);
         // Remove these messages as they are part of the previous client
         mHandler.removeMessages(MSG_BIOMETRIC_ERROR);
         mHandler.removeMessages(MSG_BIOMETRIC_HELP);
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java b/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java
index 51cc4a1..e6026c1 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 = 7;
+    private static final int REASONS = 8;
 
     public static final int PULSE_REASON_NONE = -1;
     public static final int PULSE_REASON_INTENT = 0;
@@ -45,6 +45,7 @@
     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;
+    public static final int REASON_SENSOR_WAKE_UP = 7;
 
     private static boolean sRegisterKeyguardCallback = true;
 
@@ -74,7 +75,7 @@
     public static void tracePulseStart(int reason) {
         if (!ENABLED) return;
         sPulsing = true;
-        log("pulseStart reason=" + pulseReasonToString(reason));
+        log("pulseStart reason=" + reasonToString(reason));
     }
 
     public static void tracePulseFinish() {
@@ -102,8 +103,8 @@
                 sScreenOnPulsingStats = new SummaryStats();
                 sScreenOnNotPulsingStats = new SummaryStats();
                 sEmergencyCallStats = new SummaryStats();
-                sProxStats = new SummaryStats[PULSE_REASONS][2];
-                for (int i = 0; i < PULSE_REASONS; i++) {
+                sProxStats = new SummaryStats[REASONS][2];
+                for (int i = 0; i < REASONS; i++) {
                     sProxStats[i][0] = new SummaryStats();
                     sProxStats[i][1] = new SummaryStats();
                 }
@@ -157,6 +158,12 @@
         log("missedTick by=" + delay);
     }
 
+    public static void traceTimeTickScheduled(long when, long triggerAt) {
+        if (!ENABLED) return;
+        log("timeTickScheduled at=" + FORMAT.format(new Date(when)) + " triggerAt="
+                + FORMAT.format(new Date(triggerAt)));
+    }
+
     public static void traceKeyguard(boolean showing) {
         if (!ENABLED) return;
         log("keyguard " + showing);
@@ -176,15 +183,15 @@
     }
 
     public static void traceProximityResult(Context context, boolean near, long millis,
-            int pulseReason) {
+            int reason) {
         if (!ENABLED) return;
         init(context);
-        log("proximityResult reason=" + pulseReasonToString(pulseReason) + " near=" + near
+        log("proximityResult reason=" + reasonToString(reason) + " near=" + near
                 + " millis=" + millis);
-        sProxStats[pulseReason][near ? 0 : 1].append();
+        sProxStats[reason][near ? 0 : 1].append();
     }
 
-    public static String pulseReasonToString(int pulseReason) {
+    public static String reasonToString(int pulseReason) {
         switch (pulseReason) {
             case PULSE_REASON_INTENT: return "intent";
             case PULSE_REASON_NOTIFICATION: return "notification";
@@ -193,6 +200,7 @@
             case PULSE_REASON_SENSOR_DOUBLE_TAP: return "doubletap";
             case PULSE_REASON_SENSOR_LONG_PRESS: return "longpress";
             case PULSE_REASON_SENSOR_REACH: return "reach";
+            case REASON_SENSOR_WAKE_UP: return "wakeup";
             default: throw new IllegalArgumentException("bad reason: " + pulseReason);
         }
     }
@@ -218,8 +226,8 @@
             sScreenOnPulsingStats.dump(pw, "Screen on (pulsing)");
             sScreenOnNotPulsingStats.dump(pw, "Screen on (not pulsing)");
             sEmergencyCallStats.dump(pw, "Emergency call");
-            for (int i = 0; i < PULSE_REASONS; i++) {
-                final String reason = pulseReasonToString(i);
+            for (int i = 0; i < REASONS; i++) {
+                final String reason = reasonToString(i);
                 sProxStats[i][0].dump(pw, "Proximity near (" + reason + ")");
                 sProxStats[i][1].dump(pw, "Proximity far (" + reason + ")");
             }
@@ -262,10 +270,10 @@
         }
     }
 
-    public static void traceSensor(Context context, int pulseReason) {
+    public static void traceSensor(Context context, int reason) {
         if (!ENABLED) return;
         init(context);
-        log("sensor type=" + pulseReasonToString(pulseReason));
+        log("sensor type=" + reasonToString(reason));
     }
 
     private static class SummaryStats {
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
index 045a98c..f9dfb5d 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
@@ -63,6 +63,7 @@
     private final AmbientDisplayConfiguration mConfig;
     private final WakeLock mWakeLock;
     private final Consumer<Boolean> mProxCallback;
+    private final Consumer<Boolean> mWakeScreenCallback;
     private final Callback mCallback;
 
     private final Handler mHandler = new Handler();
@@ -70,9 +71,9 @@
 
 
     public DozeSensors(Context context, AlarmManager alarmManager, SensorManager sensorManager,
-            DozeParameters dozeParameters,
-            AmbientDisplayConfiguration config, WakeLock wakeLock, Callback callback,
-            Consumer<Boolean> proxCallback, AlwaysOnDisplayPolicy policy) {
+            DozeParameters dozeParameters, AmbientDisplayConfiguration config, WakeLock wakeLock,
+            Callback callback, Consumer<Boolean> proxCallback,
+            Consumer<Boolean> wakeScreenCallback, AlwaysOnDisplayPolicy policy) {
         mContext = context;
         mAlarmManager = alarmManager;
         mSensorManager = sensorManager;
@@ -80,6 +81,7 @@
         mConfig = config;
         mWakeLock = wakeLock;
         mProxCallback = proxCallback;
+        mWakeScreenCallback = wakeScreenCallback;
         mResolver = mContext.getContentResolver();
 
         mSensors = new TriggerSensor[] {
@@ -117,6 +119,7 @@
                         DozeLog.PULSE_REASON_SENSOR_REACH,
                         false /* reports touch coordinates */,
                         false /* touchscreen */),
+                new WakeScreenSensor(),
         };
 
         mProxSensor = new ProxSensor(policy);
@@ -302,9 +305,9 @@
         final boolean mSettingDefault;
         final boolean mRequiresTouchscreen;
 
-        private boolean mRequested;
-        private boolean mRegistered;
-        private boolean mDisabled;
+        protected boolean mRequested;
+        protected boolean mRegistered;
+        protected boolean mDisabled;
 
         public TriggerSensor(Sensor sensor, String setting, boolean configured, int pulseReason,
                 boolean reportsTouchCoordinates, boolean requiresTouchscreen) {
@@ -348,7 +351,7 @@
             }
         }
 
-        private boolean enabledBySetting() {
+        protected boolean enabledBySetting() {
             if (TextUtils.isEmpty(mSetting)) {
                 return true;
             }
@@ -401,7 +404,7 @@
             }
         }
 
-        private String triggerEventToString(TriggerEvent event) {
+        protected String triggerEventToString(TriggerEvent event) {
             if (event == null) return null;
             final StringBuilder sb = new StringBuilder("TriggerEvent[")
                     .append(event.timestamp).append(',')
@@ -415,6 +418,28 @@
         }
     }
 
+    private class WakeScreenSensor extends TriggerSensor {
+
+        WakeScreenSensor() {
+            super(findSensorWithType(mConfig.wakeScreenSensorType()),
+                    Settings.Secure.DOZE_WAKE_SCREEN_GESTURE, true /* configured */,
+                    DozeLog.REASON_SENSOR_WAKE_UP, false /* reportsTouchCoordinates */,
+                    false /* requiresTouchscreen */);
+        }
+
+        @Override
+        @AnyThread
+        public void onTrigger(TriggerEvent event) {
+            DozeLog.traceSensor(mContext, mPulseReason);
+            mHandler.post(mWakeLock.wrap(() -> {
+                if (DEBUG) Log.d(TAG, "onTrigger: " + triggerEventToString(event));
+                mRegistered = false;
+                mWakeScreenCallback.accept(event.values[0] > 0);
+                updateListener();  // reregister, this sensor only fires once
+            }));
+        }
+    }
+
     public interface Callback {
 
         /**
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
index 73cbd7d..1589969 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
@@ -84,7 +84,7 @@
         mWakeLock = wakeLock;
         mAllowPulseTriggers = allowPulseTriggers;
         mDozeSensors = new DozeSensors(context, alarmManager, mSensorManager, dozeParameters,
-                config, wakeLock, this::onSensor, this::onProximityFar,
+                config, wakeLock, this::onSensor, this::onProximityFar, this::onWakeScreen,
                 dozeParameters.getPolicy());
         mUiModeManager = mContext.getSystemService(UiModeManager.class);
     }
@@ -103,7 +103,7 @@
 
     private void proximityCheckThenCall(IntConsumer callback,
             boolean alreadyPerformedProxCheck,
-            int pulseReason) {
+            int reason) {
         Boolean cachedProxFar = mDozeSensors.isProximityCurrentlyFar();
         if (alreadyPerformedProxCheck) {
             callback.accept(ProximityCheck.RESULT_NOT_CHECKED);
@@ -116,7 +116,7 @@
                 public void onProximityResult(int result) {
                     final long end = SystemClock.uptimeMillis();
                     DozeLog.traceProximityResult(mContext, result == RESULT_NEAR,
-                            end - start, pulseReason);
+                            end - start, reason);
                     callback.accept(result);
                 }
             }.check();
@@ -182,6 +182,28 @@
         }
     }
 
+    private void onWakeScreen(boolean wake) {
+        DozeMachine.State state = mMachine.getState();
+        boolean paused = (state == DozeMachine.State.DOZE_AOD_PAUSED);
+        boolean pausing = (state == DozeMachine.State.DOZE_AOD_PAUSING);
+
+        if (wake) {
+            proximityCheckThenCall((result) -> {
+                if (result == ProximityCheck.RESULT_NEAR) {
+                    // In pocket, drop event.
+                    return;
+                }
+                if (pausing || paused) {
+                    mMachine.requestState(DozeMachine.State.DOZE_AOD);
+                }
+            }, false /* alreadyPerformedProxCheck */, DozeLog.REASON_SENSOR_WAKE_UP);
+        } else {
+            if (!pausing && !paused) {
+                mMachine.requestState(DozeMachine.State.DOZE_AOD_PAUSING);
+            }
+        }
+    }
+
     @Override
     public void transitionTo(DozeMachine.State oldState, DozeMachine.State newState) {
         switch (newState) {
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
index 7863245..67aa82d 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
@@ -158,8 +158,12 @@
             return;
         }
 
-        long delta = roundToNextMinute(System.currentTimeMillis()) - System.currentTimeMillis();
-        mTimeTicker.schedule(delta, AlarmTimeout.MODE_IGNORE_IF_SCHEDULED);
+        long time = System.currentTimeMillis();
+        long delta = roundToNextMinute(time) - System.currentTimeMillis();
+        boolean scheduled = mTimeTicker.schedule(delta, AlarmTimeout.MODE_IGNORE_IF_SCHEDULED);
+        if (scheduled) {
+            DozeLog.traceTimeTickScheduled(time, time + delta);
+        }
         mLastTimeTickElapsed = SystemClock.elapsedRealtime();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index 06d4434..cc1b9e8 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -89,6 +89,7 @@
 import com.android.systemui.colorextraction.SysuiColorExtractor;
 import com.android.systemui.plugins.GlobalActions.GlobalActionsManager;
 import com.android.systemui.statusbar.phone.ScrimController;
+import com.android.systemui.util.EmergencyDialerConstants;
 import com.android.systemui.volume.SystemUIInterpolators.LogAccelerateInterpolator;
 
 import java.util.ArrayList;
@@ -449,9 +450,6 @@
     }
 
     private class EmergencyDialerAction extends SinglePressAction {
-        private static final String ACTION_EMERGENCY_DIALER_DIAL =
-                "com.android.phone.EmergencyDialer.DIAL";
-
         private EmergencyDialerAction() {
             super(R.drawable.ic_faster_emergency,
                     R.string.global_action_emergency);
@@ -460,8 +458,10 @@
         @Override
         public void onPress() {
             MetricsLogger.action(mContext, MetricsEvent.ACTION_EMERGENCY_DIALER_FROM_POWER_MENU);
-            Intent intent = new Intent(ACTION_EMERGENCY_DIALER_DIAL);
+            Intent intent = new Intent(EmergencyDialerConstants.ACTION_DIAL);
             intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
+            intent.putExtra(EmergencyDialerConstants.EXTRA_ENTRY_TYPE,
+                    EmergencyDialerConstants.ENTRY_TYPE_POWER_MENU);
             mContext.startActivityAsUser(intent, UserHandle.CURRENT);
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 4977ff7..1655c01 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -503,9 +503,6 @@
                 case READY:
                     synchronized (KeyguardViewMediator.this) {
                         if (DEBUG_SIM_STATES) Log.d(TAG, "READY, reset state? " + mShowing);
-                        if (mShowing) {
-                            resetStateLocked();
-                        }
                         mLockWhenSimRemoved = true;
                     }
                     break;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/CellTileView.java b/packages/SystemUI/src/com/android/systemui/qs/CellTileView.java
index e7eefe8..376e6ae 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/CellTileView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/CellTileView.java
@@ -43,9 +43,9 @@
                 R.dimen.qs_tile_icon_size));
     }
 
-    protected void updateIcon(ImageView iv, State state) {
+    protected void updateIcon(ImageView iv, State state, boolean allowAnimations) {
         if (!(state.icon instanceof SignalIcon)) {
-            super.updateIcon(iv, state);
+            super.updateIcon(iv, state, allowAnimations);
             return;
         } else if (!Objects.equals(state.icon, iv.getTag(R.id.qs_icon_tag))) {
             mSignalDrawable.setLevel(((SignalIcon) state.icon).getState());
diff --git a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
index f1b7eec..ca1b489 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
@@ -261,6 +261,12 @@
         return mPages.get(0).mColumns;
     }
 
+    public int getNumVisibleTiles() {
+        if (mPages.size() == 0) return 0;
+        TilePage currentPage = mPages.get(getCurrentItem());
+        return currentPage.mRecords.size();
+    }
+
     public void startTileReveal(Set<String> tileSpecs, final Runnable postAnimation) {
         if (tileSpecs.isEmpty() || mPages.size() < 2 || getScrollX() != 0 || !beginFakeDrag()) {
             // Do not start the reveal animation unless there are tiles to animate, multiple
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
index 2a4bb60..f607367 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
@@ -169,6 +169,7 @@
         QSTileLayout tileLayout = mQsPanel.getTileLayout();
         mAllViews.add((View) tileLayout);
         int height = mQs.getView() != null ? mQs.getView().getMeasuredHeight() : 0;
+        int width = mQs.getView() != null ? mQs.getView().getMeasuredWidth() : 0;
         int heightDiff = height - mQs.getHeader().getBottom()
                 + mQs.getHeader().getPaddingBottom();
         firstPageBuilder.addFloat(tileLayout, "translationY", heightDiff, 0);
@@ -181,7 +182,9 @@
             }
             final View tileIcon = tileView.getIcon().getIconView();
             View view = mQs.getView();
-            if (count < mNumQuickTiles && mAllowFancy) {
+
+            // This case: less tiles to animate in small displays.
+            if (count < mQuickQsPanel.getTileLayout().getNumVisibleTiles() && mAllowFancy) {
                 // Quick tiles.
                 QSTileView quickTileView = mQuickQsPanel.getTileView(tile);
                 if (quickTileView == null) continue;
@@ -192,18 +195,26 @@
                 final int xDiff = loc2[0] - loc1[0];
                 final int yDiff = loc2[1] - loc1[1];
                 lastXDiff = loc1[0] - lastX;
-                // Move the quick tile right from its location to the new one.
-                translationXBuilder.addFloat(quickTileView, "translationX", 0, xDiff);
-                translationYBuilder.addFloat(quickTileView, "translationY", 0, yDiff);
 
-                // Counteract the parent translation on the tile. So we have a static base to
-                // animate the label position off from.
-                //firstPageBuilder.addFloat(tileView, "translationY", mQsPanel.getHeight(), 0);
+                if (count < tileLayout.getNumVisibleTiles()) {
+                    // Move the quick tile right from its location to the new one.
+                    translationXBuilder.addFloat(quickTileView, "translationX", 0, xDiff);
+                    translationYBuilder.addFloat(quickTileView, "translationY", 0, yDiff);
 
-                // Move the real tile from the quick tile position to its final
-                // location.
-                translationXBuilder.addFloat(tileView, "translationX", -xDiff, 0);
-                translationYBuilder.addFloat(tileView, "translationY", -yDiff, 0);
+                    // Counteract the parent translation on the tile. So we have a static base to
+                    // animate the label position off from.
+                    //firstPageBuilder.addFloat(tileView, "translationY", mQsPanel.getHeight(), 0);
+
+                    // Move the real tile from the quick tile position to its final
+                    // location.
+                    translationXBuilder.addFloat(tileView, "translationX", -xDiff, 0);
+                    translationYBuilder.addFloat(tileView, "translationY", -yDiff, 0);
+
+                } else { // These tiles disappear when expanding
+                    firstPageBuilder.addFloat(quickTileView, "alpha", 1, 0);
+                    translationYBuilder.addFloat(quickTileView, "translationY", 0, yDiff);
+                    translationXBuilder.addFloat(quickTileView, "translationX", 0, xDiff + width);
+                }
 
                 mQuickQsViews.add(tileView.getIconWithBackground());
                 mAllViews.add(tileView.getIcon());
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
index 7cb22a3..c36cdf6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
@@ -101,12 +101,7 @@
         if (savedInstanceState != null) {
             setExpanded(savedInstanceState.getBoolean(EXTRA_EXPANDED));
             setListening(savedInstanceState.getBoolean(EXTRA_LISTENING));
-            int[] loc = new int[2];
-            View edit = view.findViewById(android.R.id.edit);
-            edit.getLocationInWindow(loc);
-            int x = loc[0] + edit.getWidth() / 2;
-            int y = loc[1] + edit.getHeight() / 2;
-            mQSCustomizer.setEditLocation(x, y);
+            setEditLocation(view);
             mQSCustomizer.restoreInstanceState(savedInstanceState);
         }
         SysUiServiceProvider.getComponent(getContext(), CommandQueue.class).addCallbacks(this);
@@ -161,15 +156,24 @@
     @Override
     public void onConfigurationChanged(Configuration newConfig) {
         super.onConfigurationChanged(newConfig);
+        setEditLocation(getView());
         if (newConfig.getLayoutDirection() != mLayoutDirection) {
             mLayoutDirection = newConfig.getLayoutDirection();
-
             if (mQSAnimator != null) {
                 mQSAnimator.onRtlChanged();
             }
         }
     }
 
+    private void setEditLocation(View view) {
+        Log.w(TAG, "I'm changing the location of the button!!!");
+        View edit = view.findViewById(android.R.id.edit);
+        int[] loc = edit.getLocationOnScreen();
+        int x = loc[0] + edit.getWidth() / 2;
+        int y = loc[1] + edit.getHeight() / 2;
+        mQSCustomizer.setEditLocation(x, y);
+    }
+
     @Override
     public void setContainer(ViewGroup container) {
         if (container instanceof NotificationsQuickSettingsContainer) {
@@ -284,6 +288,7 @@
         mHeader.setListening(listening);
         mFooter.setListening(listening);
         mQSPanel.setListening(mListening && mQsExpanded);
+        mQSPanel.getFooter().setListening(listening);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index 3fc258b..7a57fdd 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -29,6 +29,7 @@
 import android.os.Message;
 import android.service.quicksettings.Tile;
 import android.util.AttributeSet;
+import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.widget.LinearLayout;
@@ -60,6 +61,8 @@
     public static final String QS_SHOW_BRIGHTNESS = "qs_show_brightness";
     public static final String QS_SHOW_HEADER = "qs_show_header";
 
+    private static final String TAG = "QSPanel";
+
     protected final Context mContext;
     protected final ArrayList<TileRecord> mRecords = new ArrayList<>();
     protected final View mBrightnessView;
@@ -313,7 +316,7 @@
 
     public void onCollapse() {
         if (mCustomizePanel != null && mCustomizePanel.isShown()) {
-            mCustomizePanel.hide(mCustomizePanel.getWidth() / 2, mCustomizePanel.getHeight() / 2);
+            mCustomizePanel.hide();
         }
     }
 
@@ -347,7 +350,6 @@
         if (mTileLayout != null) {
             mTileLayout.setListening(listening);
         }
-        mFooter.setListening(mListening);
         if (mListening) {
             refreshAllTiles();
         }
@@ -480,8 +482,7 @@
             public void run() {
                 if (mCustomizePanel != null) {
                     if (!mCustomizePanel.isCustomizing()) {
-                        int[] loc = new int[2];
-                        v.getLocationInWindow(loc);
+                        int[] loc = v.getLocationOnScreen();
                         int x = loc[0] + v.getWidth() / 2;
                         int y = loc[1] + v.getHeight() / 2;
                         mCustomizePanel.show(x, y);
@@ -495,7 +496,7 @@
     public void closeDetail() {
         if (mCustomizePanel != null && mCustomizePanel.isShown()) {
             // Treat this as a detail panel for now, to make things easy.
-            mCustomizePanel.hide(mCustomizePanel.getWidth() / 2, mCustomizePanel.getHeight() / 2);
+            mCustomizePanel.hide();
             return;
         }
         showDetail(false, mDetailRecord);
@@ -663,5 +664,7 @@
         void setListening(boolean listening);
 
         default void setExpansion(float expansion) {}
+
+        int getNumVisibleTiles();
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java
index 6418c80..8f3a7b3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java
@@ -96,6 +96,7 @@
     public void setListening(boolean listening) {
         if (listening) {
             mSecurityController.addCallback(mCallback);
+            refreshState();
         } else {
             mSecurityController.removeCallback(mCallback);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
index 1c50f79..556786a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
@@ -18,18 +18,17 @@
 
 import android.content.Context;
 import android.content.res.Configuration;
+import android.graphics.Rect;
 import android.util.AttributeSet;
 import android.view.Gravity;
 import android.view.View;
 import android.widget.LinearLayout;
-import android.widget.Space;
 
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.plugins.qs.QSTile;
 import com.android.systemui.plugins.qs.QSTile.SignalState;
 import com.android.systemui.plugins.qs.QSTile.State;
-import com.android.systemui.plugins.qs.QSTileView;
 import com.android.systemui.qs.customize.QSCustomizer;
 import com.android.systemui.tuner.TunerService;
 import com.android.systemui.tuner.TunerService.Tunable;
@@ -43,6 +42,7 @@
 public class QuickQSPanel extends QSPanel {
 
     public static final String NUM_QUICK_TILES = "sysui_qqs_count";
+    private static final String TAG = "QuickQSPanel";
 
     private boolean mDisabledByPolicy;
     private static int mDefaultMaxTiles;
@@ -178,121 +178,95 @@
         super.setVisibility(visibility);
     }
 
-    private static class HeaderTileLayout extends LinearLayout implements QSTileLayout {
+    private static class HeaderTileLayout extends TileLayout {
 
-        protected final ArrayList<TileRecord> mRecords = new ArrayList<>();
         private boolean mListening;
-        /** Size of the QS tile (width & height). */
-        private int mTileDimensionSize;
 
         public HeaderTileLayout(Context context) {
             super(context);
             setClipChildren(false);
             setClipToPadding(false);
-
-            mTileDimensionSize = mContext.getResources().getDimensionPixelSize(
-                    R.dimen.qs_quick_tile_size);
-            updateLayoutParams();
         }
 
         @Override
         protected void onConfigurationChanged(Configuration newConfig) {
             super.onConfigurationChanged(newConfig);
-            updateLayoutParams();
+            updateResources();
+        }
+
+        @Override
+        public void onFinishInflate(){
+            updateResources();
         }
 
         private void updateLayoutParams() {
-            setGravity(Gravity.CENTER);
             int width = getResources().getDimensionPixelSize(R.dimen.qs_quick_layout_width);
-            LayoutParams lp = new LayoutParams(width, LayoutParams.MATCH_PARENT);
+            LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(width, LayoutParams.MATCH_PARENT);
             lp.gravity = Gravity.CENTER_HORIZONTAL;
             setLayoutParams(lp);
         }
 
-        /**
-         * Returns {@link LayoutParams} based on the given {@code spaceWidth}. If the width is 0,
-         * then we're going to have the space expand to take up as much space as possible. If the
-         * width is non-zero, we want the inter-tile spacers to be fixed.
-         */
-        private LayoutParams generateSpaceLayoutParams() {
-            LayoutParams lp = new LayoutParams(0, mTileDimensionSize);
-            lp.weight = 1;
-            lp.gravity = Gravity.CENTER;
-            return lp;
-        }
-
-        @Override
-        public void setListening(boolean listening) {
-            if (mListening == listening) return;
-            mListening = listening;
-            for (TileRecord record : mRecords) {
-                record.tile.setListening(this, mListening);
-            }
-        }
-
-        @Override
-        public void addTile(TileRecord tile) {
-            if (getChildCount() != 0) {
-                addView(new Space(mContext), getChildCount(), generateSpaceLayoutParams());
-            }
-
-            addView(tile.tileView, getChildCount(), generateTileLayoutParams());
-            mRecords.add(tile);
-            tile.tile.setListening(this, mListening);
-        }
-
         private LayoutParams generateTileLayoutParams() {
-            LayoutParams lp = new LayoutParams(mTileDimensionSize, mTileDimensionSize);
-            lp.gravity = Gravity.CENTER;
+            LayoutParams lp = new LayoutParams(mCellWidth, mCellHeight);
             return lp;
         }
 
         @Override
-        public void removeTile(TileRecord tile) {
-            int childIndex = getChildIndex(tile.tileView);
-            // Remove the tile.
-            removeViewAt(childIndex);
-            if (getChildCount() != 0) {
-                // Remove its spacer as well.
-                removeViewAt(childIndex);
-            }
-            mRecords.remove(tile);
-            tile.tile.setListening(this, false);
-        }
-
-        private int getChildIndex(QSTileView tileView) {
-            final int childViewCount = getChildCount();
-            for (int i = 0; i < childViewCount; i++) {
-                if (getChildAt(i) == tileView) {
-                    return i;
-                }
-            }
-            return -1;
+        protected void addTileView(TileRecord tile) {
+            addView(tile.tileView, getChildCount(), generateTileLayoutParams());
         }
 
         @Override
-        public int getOffsetTop(TileRecord tile) {
-            return 0;
+        protected void onLayout(boolean changed, int l, int t, int r, int b) {
+            // We only care about clipping on the right side
+            Rect bounds = new Rect(0, 0, r - l, 10000);
+            setClipBounds(bounds);
+
+            calculateColumns();
+
+            for (int i = 0; i < mRecords.size(); i++) {
+                mRecords.get(i).tileView.setVisibility( i < mColumns ? View.VISIBLE : View.GONE);
+            }
+
+            setAccessibilityOrder();
+            layoutTileRecords(mColumns);
         }
 
         @Override
         public boolean updateResources() {
-            // No resources here.
+            mCellWidth = mContext.getResources().getDimensionPixelSize(R.dimen.qs_quick_tile_size);
+            mCellHeight = mCellWidth;
+
+            updateLayoutParams();
+
             return false;
         }
 
-        @Override
-        public boolean hasOverlappingRendering() {
-            return false;
-        }
+        private boolean calculateColumns() {
+            int prevNumColumns = mColumns;
+            int maxTiles = mRecords.size();
 
-        @Override
-        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
-            if (hideOverflowingChildren(widthMeasureSpec)) {
-                return; // Rely on visibility change to trigger remeasure.
+            if (maxTiles == 0){ // Early return during setup
+                mColumns = 0;
+                return true;
             }
 
+            final int availableWidth = getMeasuredWidth() - getPaddingStart() - getPaddingEnd();
+            final int leftoverWithespace = availableWidth - maxTiles * mCellWidth;
+            final int smallestHorizontalMarginNeeded = leftoverWithespace / (maxTiles - 1);
+
+            if (smallestHorizontalMarginNeeded > 0){
+                mCellMarginHorizontal = smallestHorizontalMarginNeeded;
+                mColumns = maxTiles;
+            } else{
+                mColumns = mCellWidth == 0 ? 1 :
+                        Math.min(maxTiles, availableWidth / mCellWidth );
+                mCellMarginHorizontal = (availableWidth - mColumns * mCellWidth) / (mColumns - 1);
+            }
+            return mColumns != prevNumColumns;
+        }
+
+        private void setAccessibilityOrder() {
             if (mRecords != null && mRecords.size() > 0) {
                 View previousView = this;
                 for (TileRecord record : mRecords) {
@@ -306,31 +280,28 @@
             }
         }
 
-        /**
-         * Hide child views that would otherwise be clipped.
-         * @return {@code true} if any child visibilities have changed.
-         */
-        private boolean hideOverflowingChildren(int widthMeasureSpec) {
-            if (getChildCount() == 0) {
-                return false;
+        @Override
+        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+            // Measure each QS tile.
+            for (TileRecord record : mRecords) {
+                if (record.tileView.getVisibility() == GONE) continue;
+                record.tileView.measure(exactly(mCellWidth), exactly(mCellHeight));
             }
-            boolean childVisibilityChanged = false;
-            int widthRemaining = MeasureSpec.getSize(widthMeasureSpec)
-                - getChildAt(0).getMeasuredWidth() - getPaddingStart() - getPaddingEnd();
-            for (int i = 2; i < getChildCount(); i += 2) {
-                View tileChild = getChildAt(i);
-                LayoutParams lp = (LayoutParams) tileChild.getLayoutParams();
-                // All Space views have 0 width; only tiles contribute to the total width.
-                widthRemaining = widthRemaining
-                    - tileChild.getMeasuredWidth() - lp.getMarginEnd() - lp.getMarginStart();
-                int newVisibility = widthRemaining < 0 ? View.GONE : View.VISIBLE;
-                if (tileChild.getVisibility() != newVisibility) {
-                    tileChild.setVisibility(newVisibility);
-                    getChildAt(i - 1).setVisibility(newVisibility); // Hide spacer as well.
-                    childVisibilityChanged = true;
-                }
-            }
-            return childVisibilityChanged;
+
+            int height = mCellHeight;
+            if (height < 0) height = 0;
+
+            setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), height);
+        }
+
+        @Override
+        public int getNumVisibleTiles() {
+            return mColumns;
+        }
+
+        @Override
+        protected int getColumnStart(int column) {
+            return getPaddingStart() + column *  (mCellWidth + mCellMarginHorizontal);
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index ff5ac76..b988c55 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -547,38 +547,23 @@
 
     /**
      * Fades in the updated status text. Note that if there's already a status showing, this will
-     * immediately hide it and fade in the updated status.
+     * immediately fade it out and fade in the updated status.
      */
     private void showStatus() {
         mStatusContainer.setAlpha(0f);
-        mStatusContainer.setVisibility(View.VISIBLE);
 
-        // Animate the alarm back in. Make sure to clear the animator listener for the animation!
         mStatusContainer.animate()
                 .alpha(1f)
                 .setDuration(FADE_ANIMATION_DURATION_MS)
-                .setListener(null)
                 .start();
     }
 
-    /** Fades out and hides the status text. */
+    /** Fades out the status text. */
     private void hideStatusText() {
-        if (mStatusContainer.getVisibility() == View.VISIBLE) {
-            mStatusContainer.animate()
-                    .alpha(0f)
-                    .setListener(new AnimatorListenerAdapter() {
-                        @Override
-                        public void onAnimationEnd(Animator animation) {
-                            if (DEBUG) Log.d(TAG, "hideAlarmText: Hid alarm text");
-
-                            // Reset the alpha regardless of how the animation ends for the next
-                            // time we show this view/want to animate it.
-                            mStatusContainer.setVisibility(View.INVISIBLE);
-                            mStatusContainer.setAlpha(1f);
-                        }
-                    })
-                    .start();
-        }
+        mStatusContainer.animate()
+                .alpha(0f)
+                .setDuration(FADE_ANIMATION_DURATION_MS)
+                .start();
     }
 
     public void updateEverything() {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/SignalTileView.java b/packages/SystemUI/src/com/android/systemui/qs/SignalTileView.java
index d9583af..ce90fc1 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/SignalTileView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/SignalTileView.java
@@ -18,14 +18,13 @@
 
 import android.animation.ValueAnimator;
 import android.content.Context;
-import android.graphics.drawable.Drawable;
 import android.view.View;
 import android.widget.FrameLayout;
 import android.widget.ImageView;
 
 import com.android.systemui.R;
-import com.android.systemui.plugins.qs.QSTile;
 import com.android.systemui.plugins.qs.QSTile.SignalState;
+import com.android.systemui.plugins.qs.QSTile.State;
 import com.android.systemui.qs.tileimpl.QSIconViewImpl;
 import com.android.systemui.qs.tileimpl.SlashImageView;
 
@@ -119,9 +118,9 @@
     }
 
     @Override
-    public void setIcon(QSTile.State state) {
+    public void setIcon(State state, boolean allowAnimations) {
         final SignalState s = (SignalState) state;
-        setIcon(mSignal, s);
+        setIcon(mSignal, s, allowAnimations);
 
         if (s.overlayIconId > 0) {
             mOverlay.setVisibility(VISIBLE);
@@ -134,9 +133,9 @@
         } else {
             mSignal.setPaddingRelative(0, 0, 0, 0);
         }
-        final boolean shown = isShown();
-        setVisibility(mIn, shown, s.activityIn);
-        setVisibility(mOut, shown, s.activityOut);
+        final boolean shouldAnimate = allowAnimations && isShown();
+        setVisibility(mIn, shouldAnimate, s.activityIn);
+        setVisibility(mOut, shouldAnimate, s.activityOut);
     }
 
     private void setVisibility(View view, boolean shown, boolean visible) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
index 45d63e0..c67165e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
@@ -56,6 +56,10 @@
     public void addTile(TileRecord tile) {
         mRecords.add(tile);
         tile.tile.setListening(this, mListening);
+        addTileView(tile);
+    }
+
+    protected void addTileView(TileRecord tile) {
         addView(tile.tileView);
     }
 
@@ -120,19 +124,18 @@
         return false;
     }
 
-    private static int exactly(int size) {
+    protected static int exactly(int size) {
         return MeasureSpec.makeMeasureSpec(size, MeasureSpec.EXACTLY);
     }
 
-    @Override
-    protected void onLayout(boolean changed, int l, int t, int r, int b) {
-        final int w = getWidth();
+
+    protected void layoutTileRecords(int numRecords) {
         final boolean isRtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL;
         int row = 0;
         int column = 0;
 
         // Layout each QS tile.
-        for (int i = 0; i < mRecords.size(); i++, column++) {
+        for (int i = 0; i < numRecords; i++, column++) {
             // If we reached the last column available to layout a tile, wrap back to the next row.
             if (column == mColumns) {
                 column = 0;
@@ -147,12 +150,22 @@
         }
     }
 
+    @Override
+    protected void onLayout(boolean changed, int l, int t, int r, int b) {
+        layoutTileRecords(mRecords.size());
+    }
+
     private int getRowTop(int row) {
         return row * (mCellHeight + mCellMarginVertical) + mCellMarginTop;
     }
 
-    private int getColumnStart(int column) {
+    protected int getColumnStart(int column) {
         return getPaddingStart() + mSidePadding + mCellMarginHorizontal / 2 +
                 column *  (mCellWidth + mCellMarginHorizontal);
     }
+
+    @Override
+    public int getNumVisibleTiles() {
+        return mRecords.size();
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
index 2ea15bd..3f7eeb8 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
@@ -26,6 +26,7 @@
 import androidx.recyclerview.widget.GridLayoutManager;
 import androidx.recyclerview.widget.RecyclerView;
 import android.util.AttributeSet;
+import android.util.Log;
 import android.util.TypedValue;
 import android.view.ContextThemeWrapper;
 import android.view.LayoutInflater;
@@ -63,6 +64,7 @@
 
     private static final int MENU_RESET = Menu.FIRST;
     private static final String EXTRA_QS_CUSTOMIZING = "qs_customizing";
+    private static final String TAG = "QSCustomizer";
 
     private final QSDetailClipper mClipper;
     private final LightBarController mLightBarController;
@@ -94,7 +96,7 @@
         mToolbar.setNavigationOnClickListener(new OnClickListener() {
             @Override
             public void onClick(View v) {
-                hide((int) v.getX() + v.getWidth() / 2, (int) v.getY() + v.getHeight() / 2);
+                hide();
             }
         });
         mToolbar.setOnMenuItemClickListener(this);
@@ -154,16 +156,20 @@
         mQs = qs;
     }
 
+    /** Animate and show QSCustomizer panel.
+     * @param x,y Location on screen of {@code edit} button to determine center of animation.
+     */
     public void show(int x, int y) {
         if (!isShown) {
-            mX = x;
-            mY = y;
+            int containerLocation[] = findViewById(R.id.customize_container).getLocationOnScreen();
+            mX = x - containerLocation[0];
+            mY = y - containerLocation[1];
             MetricsLogger.visible(getContext(), MetricsProto.MetricsEvent.QS_EDIT);
             isShown = true;
             mOpening = true;
             setTileSpecs();
             setVisibility(View.VISIBLE);
-            mClipper.animateCircularClip(x, y, true, mExpandAnimationListener);
+            mClipper.animateCircularClip(mX, mY, true, mExpandAnimationListener);
             queryTiles();
             mNotifQsContainer.setCustomizerAnimating(true);
             mNotifQsContainer.setCustomizerShowing(true);
@@ -192,7 +198,7 @@
         mTileQueryHelper.queryTiles(mHost);
     }
 
-    public void hide(int x, int y) {
+    public void hide() {
         if (isShown) {
             MetricsLogger.hidden(getContext(), MetricsProto.MetricsEvent.QS_EDIT);
             isShown = false;
@@ -278,16 +284,18 @@
             });
         }
     }
-
+    /** @param x,y Location on screen of animation center.
+     */
     public void setEditLocation(int x, int y) {
-        mX = x;
-        mY = y;
+        int containerLocation[] = findViewById(R.id.customize_container).getLocationOnScreen();
+        mX = x - containerLocation[0];
+        mY = y - containerLocation[1];
     }
 
     private final Callback mKeyguardCallback = () -> {
         if (!isAttachedToWindow()) return;
         if (Dependency.get(KeyguardMonitor.class).isShowing() && !mOpening) {
-            hide(0, 0);
+            hide();
         }
     };
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSIconViewImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSIconViewImpl.java
index e7e756f..9dd5d8f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSIconViewImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSIconViewImpl.java
@@ -84,16 +84,15 @@
         layout(mIcon, iconLeft, top);
     }
 
-    public void setIcon(QSTile.State state) {
-        setIcon((ImageView) mIcon, state);
+    public void setIcon(State state, boolean allowAnimations) {
+        setIcon((ImageView) mIcon, state, allowAnimations);
     }
 
-    protected void updateIcon(ImageView iv, State state) {
+    protected void updateIcon(ImageView iv, State state, boolean allowAnimations) {
         final QSTile.Icon icon = state.iconSupplier != null ? state.iconSupplier.get() : state.icon;
         if (!Objects.equals(icon, iv.getTag(R.id.qs_icon_tag))
                 || !Objects.equals(state.slash, iv.getTag(R.id.qs_slash_tag))) {
-            boolean shouldAnimate = iv.isShown() && mAnimationEnabled
-                    && iv.getDrawable() != null;
+            boolean shouldAnimate = allowAnimations && shouldAnimate(iv);
             Drawable d = icon != null
                     ? shouldAnimate ? icon.getDrawable(mContext)
                     : icon.getInvisibleDrawable(mContext) : null;
@@ -128,7 +127,11 @@
         }
     }
 
-    protected void setIcon(ImageView iv, QSTile.State state) {
+    private boolean shouldAnimate(ImageView iv) {
+        return mAnimationEnabled && iv.isShown() && iv.getDrawable() != null;
+    }
+
+    protected void setIcon(ImageView iv, QSTile.State state, boolean allowAnimations) {
         if (state.disabledByPolicy) {
             iv.setColorFilter(getContext().getColor(R.color.qs_tile_disabled_color));
         } else {
@@ -137,8 +140,8 @@
         if (state.state != mState) {
             int color = getColor(state.state);
             mState = state.state;
-            if (iv.isShown() && mTint != 0) {
-                animateGrayScale(mTint, color, iv, () -> updateIcon(iv, state));
+            if (mTint != 0 && allowAnimations && shouldAnimate(iv)) {
+                animateGrayScale(mTint, color, iv, () -> updateIcon(iv, state, allowAnimations));
                 mTint = color;
             } else {
                 if (iv instanceof AlphaControlledSlashImageView) {
@@ -148,10 +151,10 @@
                     setTint(iv, color);
                 }
                 mTint = color;
-                updateIcon(iv, state);
+                updateIcon(iv, state, allowAnimations);
             }
         } else {
-            updateIcon(iv, state);
+            updateIcon(iv, state, allowAnimations);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java
index 91afef02..d42127e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java
@@ -47,6 +47,7 @@
 
     private static final String TAG = "QSTileBaseView";
     private final H mHandler = new H();
+    private final int[] mLocInScreen = new int[2];
     private final FrameLayout mIconFrame;
     protected QSIconView mIcon;
     protected RippleDrawable mRipple;
@@ -178,8 +179,9 @@
 
     protected void handleStateChanged(QSTile.State state) {
         int circleColor = getCircleColor(state.state);
+        boolean allowAnimations = animationsEnabled();
         if (circleColor != mCircleColor) {
-            if (mBg.isShown() && animationsEnabled()) {
+            if (allowAnimations) {
                 ValueAnimator animator = ValueAnimator.ofArgb(mCircleColor, circleColor)
                         .setDuration(QS_ANIM_LENGTH);
                 animator.addUpdateListener(animation -> mBg.setImageTintList(ColorStateList.valueOf(
@@ -192,7 +194,7 @@
         }
 
         setClickable(state.state != Tile.STATE_UNAVAILABLE);
-        mIcon.setIcon(state);
+        mIcon.setIcon(state, allowAnimations);
         setContentDescription(state.contentDescription);
 
         mAccessibilityClass = state.expandedAccessibilityClassName;
@@ -205,8 +207,17 @@
         }
     }
 
+    /* The view should not be animated if it's not on screen and no part of it is visible.
+     */
     protected boolean animationsEnabled() {
-        return true;
+        if (!isShown()) {
+            return false;
+        }
+        if (getAlpha() != 1f) {
+            return false;
+        }
+        getLocationOnScreen(mLocInScreen);
+        return mLocInScreen[1] >= -getHeight();
     }
 
     private int getCircleColor(int state) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
index fb4fcd4..9e341e2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
@@ -168,12 +168,12 @@
         }
 
         final Resources r = mContext.getResources();
-        state.activityIn = cb.enabled && cb.activityIn;
-        state.activityOut = cb.enabled && cb.activityOut;
         state.label = r.getString(R.string.mobile_data);
         boolean mobileDataEnabled = mDataController.isMobileDataSupported()
                 && mDataController.isMobileDataEnabled();
         state.value = mobileDataEnabled;
+        state.activityIn = mobileDataEnabled && cb.activityIn;
+        state.activityOut = mobileDataEnabled && cb.activityOut;
         state.expandedAccessibilityClassName = Switch.class.getName();
         if (cb.noSim) {
             state.icon = ResourceIcon.get(R.drawable.ic_qs_no_sim);
@@ -231,7 +231,6 @@
     }
 
     private static final class CallbackInfo {
-        boolean enabled;
         boolean airplaneModeEnabled;
         String dataContentDescription;
         boolean activityIn;
@@ -251,7 +250,6 @@
                 // Not data sim, don't display.
                 return;
             }
-            mInfo.enabled = qsIcon.visible;
             mInfo.dataContentDescription = typeContentDescription;
             mInfo.activityIn = activityIn;
             mInfo.activityOut = activityOut;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java
index c017104..4516518 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java
@@ -36,10 +36,20 @@
  * 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 {
+public abstract class AlertingNotificationManager implements NotificationLifetimeExtender {
     private static final String TAG = "AlertNotifManager";
     protected final Clock mClock = new Clock();
     protected final ArrayMap<String, AlertEntry> mAlertEntries = new ArrayMap<>();
+
+    /**
+     * This is the list of entries that have already been removed from the
+     * NotificationManagerService side, but we keep it to prevent the UI from looking weird and
+     * will remove when possible. See {@link NotificationLifetimeExtender}
+     */
+    protected final ArraySet<NotificationData.Entry> mExtendedLifetimeAlertEntries =
+            new ArraySet<>();
+
+    protected NotificationSafeToRemoveCallback mNotificationLifetimeFinishedCallback;
     protected int mMinimumDisplayTime;
     protected int mAutoDismissNotificationDecay;
     @VisibleForTesting
@@ -74,7 +84,7 @@
         if (alertEntry == null) {
             return true;
         }
-        if (releaseImmediately || alertEntry.wasShownLongEnough()) {
+        if (releaseImmediately || canRemoveImmediately(key)) {
             removeAlertEntry(key);
         } else {
             alertEntry.removeAsSoonAsPossible();
@@ -191,6 +201,12 @@
         onAlertEntryRemoved(alertEntry);
         entry.row.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
         alertEntry.reset();
+        if (mExtendedLifetimeAlertEntries.contains(entry)) {
+            if (mNotificationLifetimeFinishedCallback != null) {
+                mNotificationLifetimeFinishedCallback.onSafeToRemove(key);
+            }
+            mExtendedLifetimeAlertEntries.remove(entry);
+        }
     }
 
     /**
@@ -207,6 +223,40 @@
         return new AlertEntry();
     }
 
+    /**
+     * Whether or not the alert can be removed currently.  If it hasn't been on screen long enough
+     * it should not be removed unless forced
+     * @param key the key to check if removable
+     * @return true if the alert entry can be removed
+     */
+    protected boolean canRemoveImmediately(String key) {
+        AlertEntry alertEntry = mAlertEntries.get(key);
+        return alertEntry == null || alertEntry.wasShownLongEnough();
+    }
+
+    ///////////////////////////////////////////////////////////////////////////////////////////////
+    // NotificationLifetimeExtender Methods
+
+    @Override
+    public void setCallback(NotificationSafeToRemoveCallback callback) {
+        mNotificationLifetimeFinishedCallback = callback;
+    }
+
+    @Override
+    public boolean shouldExtendLifetime(NotificationData.Entry entry) {
+        return !canRemoveImmediately(entry.key);
+    }
+
+    @Override
+    public void setShouldManageLifetime(NotificationData.Entry entry, boolean shouldExtend) {
+        if (shouldExtend) {
+            mExtendedLifetimeAlertEntries.add(entry);
+        } else {
+            mExtendedLifetimeAlertEntries.remove(entry);
+        }
+    }
+    ///////////////////////////////////////////////////////////////////////////////////////////////
+
     protected class AlertEntry implements Comparable<AlertEntry> {
         @Nullable public NotificationData.Entry mEntry;
         public long mPostTime;
@@ -214,11 +264,11 @@
 
         @Nullable protected Runnable mRemoveAlertRunnable;
 
-        public void setEntry(@Nullable final NotificationData.Entry entry) {
+        public void setEntry(@NonNull final NotificationData.Entry entry) {
             setEntry(entry, () -> removeAlertEntry(entry.key));
         }
 
-        public void setEntry(@Nullable final NotificationData.Entry entry,
+        public void setEntry(@NonNull final NotificationData.Entry entry,
                 @Nullable Runnable removeAlertRunnable) {
             mEntry = entry;
             mRemoveAlertRunnable = removeAlertRunnable;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index 909cd79..e19c844 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -160,7 +160,8 @@
 
         default void onRotationProposal(int rotation, boolean isValid) { }
 
-        default void showBiometricDialog(Bundle bundle, IBiometricPromptReceiver receiver) { }
+        default void showBiometricDialog(Bundle bundle, IBiometricPromptReceiver receiver,
+                int type) { }
         default void onBiometricAuthenticated() { }
         default void onBiometricHelp(String message) { }
         default void onBiometricError(String error) { }
@@ -513,11 +514,12 @@
     }
 
     @Override
-    public void showBiometricDialog(Bundle bundle, IBiometricPromptReceiver receiver) {
+    public void showBiometricDialog(Bundle bundle, IBiometricPromptReceiver receiver, int type) {
         synchronized (mLock) {
             SomeArgs args = SomeArgs.obtain();
             args.arg1 = bundle;
             args.arg2 = receiver;
+            args.argi1 = type;
             mHandler.obtainMessage(MSG_BIOMETRIC_SHOW, args)
                     .sendToTarget();
         }
@@ -756,11 +758,14 @@
                     mHandler.removeMessages(MSG_BIOMETRIC_ERROR);
                     mHandler.removeMessages(MSG_BIOMETRIC_HELP);
                     mHandler.removeMessages(MSG_BIOMETRIC_AUTHENTICATED);
+                    SomeArgs someArgs = (SomeArgs) msg.obj;
                     for (int i = 0; i < mCallbacks.size(); i++) {
                         mCallbacks.get(i).showBiometricDialog(
-                                (Bundle)((SomeArgs)msg.obj).arg1,
-                                (IBiometricPromptReceiver)((SomeArgs)msg.obj).arg2);
+                                (Bundle) someArgs.arg1,
+                                (IBiometricPromptReceiver) someArgs.arg2,
+                                someArgs.argi1);
                     }
+                    someArgs.recycle();
                     break;
                 case MSG_BIOMETRIC_AUTHENTICATED:
                     for (int i = 0; i < mCallbacks.size(); i++) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLifetimeExtender.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLifetimeExtender.java
new file mode 100644
index 0000000..62c21dc
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLifetimeExtender.java
@@ -0,0 +1,53 @@
+package com.android.systemui.statusbar;
+
+import com.android.systemui.statusbar.notification.NotificationData;
+
+import androidx.annotation.NonNull;
+
+/**
+ * Interface for anything that may need to keep notifications managed even after
+ * {@link NotificationListener} removes it.  The lifetime extender is in charge of performing the
+ * callback when the notification is then safe to remove.
+ */
+public interface NotificationLifetimeExtender {
+
+    /**
+     * Set the handler to callback to when the notification is safe to remove.
+     *
+     * @param callback the handler to callback
+     */
+    void setCallback(@NonNull NotificationSafeToRemoveCallback callback);
+
+    /**
+     * Determines whether or not the extender needs the notification kept after removal.
+     *
+     * @param entry the entry containing the notification to check
+     * @return true if the notification lifetime should be extended
+     */
+    boolean shouldExtendLifetime(@NonNull NotificationData.Entry entry);
+
+    /**
+     * Sets whether or not the lifetime should be managed by the extender.  In practice, if
+     * shouldManage is true, this is where the extender starts managing the entry internally and is
+     * now responsible for calling {@link NotificationSafeToRemoveCallback#onSafeToRemove(String)}
+     * when the entry is safe to remove.  If shouldManage is false, the extender no longer needs to
+     * worry about it (either because we will be removing it anyway or the entry is no longer
+     * removed due to an update).
+     *
+     * @param entry the entry that needs an extended lifetime
+     * @param shouldManage true if the extender should manage the entry now, false otherwise
+     */
+    void setShouldManageLifetime(@NonNull NotificationData.Entry entry, boolean shouldManage);
+
+    /**
+     * The callback for when the notification is now safe to remove (i.e. its lifetime has ended).
+     */
+    interface NotificationSafeToRemoveCallback {
+        /**
+         * Called when the lifetime extender determines it's safe to remove.
+         *
+         * @param key key of the entry that is now safe to remove
+         */
+        void onSafeToRemove(String key);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java
index 9b375df..cfa09bc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java
@@ -76,7 +76,6 @@
             mPresenter.getHandler().post(() -> {
                 processForRemoteInput(sbn.getNotification(), mContext);
                 String key = sbn.getKey();
-                mEntryManager.removeKeyKeptForRemoteInput(key);
                 boolean isUpdate =
                         mEntryManager.getNotificationData().get(key) != null;
                 // In case we don't allow child notifications, we ignore children of
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
index 929713c..ea7e03e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
@@ -17,8 +17,10 @@
 
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY;
 
+import android.annotation.NonNull;
 import android.app.ActivityManager;
 import android.app.ActivityOptions;
+import android.app.Notification;
 import android.app.PendingIntent;
 import android.app.RemoteInput;
 import android.content.Context;
@@ -29,6 +31,7 @@
 import android.os.SystemProperties;
 import android.os.UserManager;
 import android.service.notification.StatusBarNotification;
+import android.text.TextUtils;
 import android.util.ArraySet;
 import android.util.Log;
 import android.view.MotionEvent;
@@ -50,6 +53,7 @@
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
+import java.util.ArrayList;
 import java.util.Set;
 
 /**
@@ -61,10 +65,10 @@
 public class NotificationRemoteInputManager implements Dumpable {
     public static final boolean ENABLE_REMOTE_INPUT =
             SystemProperties.getBoolean("debug.enable_remote_input", true);
-    public static final boolean FORCE_REMOTE_INPUT_HISTORY =
+    public static boolean FORCE_REMOTE_INPUT_HISTORY =
             SystemProperties.getBoolean("debug.force_remoteinput_history", true);
     private static final boolean DEBUG = false;
-    private static final String TAG = "NotificationRemoteInputManager";
+    private static final String TAG = "NotifRemoteInputManager";
 
     /**
      * How long to wait before auto-dismissing a notification that was kept for remote input, and
@@ -74,12 +78,25 @@
      */
     private static final int REMOTE_INPUT_KEPT_ENTRY_AUTO_CANCEL_DELAY = 200;
 
-    protected final ArraySet<NotificationData.Entry> mRemoteInputEntriesToRemoveOnCollapse =
+    /**
+     * Notifications that are already removed but are kept around because we want to show the
+     * remote input history. See {@link RemoteInputHistoryExtender} and
+     * {@link SmartReplyHistoryExtender}.
+     */
+    protected final ArraySet<String> mKeysKeptForRemoteInputHistory = new ArraySet<>();
+
+    /**
+     * Notifications that are already removed but are kept around because the remote input is
+     * actively being used (i.e. user is typing in it).  See {@link RemoteInputActiveExtender}.
+     */
+    protected final ArraySet<NotificationData.Entry> mEntriesKeptForRemoteInputActive =
             new ArraySet<>();
 
     // Dependencies:
     protected final NotificationLockscreenUserManager mLockscreenUserManager =
             Dependency.get(NotificationLockscreenUserManager.class);
+    protected final SmartReplyController mSmartReplyController =
+            Dependency.get(SmartReplyController.class);
 
     protected final Context mContext;
     private final UserManager mUserManager;
@@ -87,8 +104,11 @@
     protected RemoteInputController mRemoteInputController;
     protected NotificationPresenter mPresenter;
     protected NotificationEntryManager mEntryManager;
+    protected NotificationLifetimeExtender.NotificationSafeToRemoveCallback
+            mNotificationLifetimeFinishedCallback;
     protected IStatusBarService mBarService;
     protected Callback mCallback;
+    protected final ArrayList<NotificationLifetimeExtender> mLifetimeExtenders = new ArrayList<>();
 
     private final RemoteViews.OnClickHandler mOnClickHandler = new RemoteViews.OnClickHandler() {
 
@@ -276,6 +296,7 @@
         mBarService = IStatusBarService.Stub.asInterface(
                 ServiceManager.getService(Context.STATUS_BAR_SERVICE));
         mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+        addLifetimeExtenders();
     }
 
     public void setUpWithPresenter(NotificationPresenter presenter,
@@ -290,16 +311,16 @@
             @Override
             public void onRemoteInputSent(NotificationData.Entry entry) {
                 if (FORCE_REMOTE_INPUT_HISTORY
-                        && mEntryManager.isNotificationKeptForRemoteInput(entry.key)) {
-                    mEntryManager.removeNotification(entry.key, null);
-                } else if (mRemoteInputEntriesToRemoveOnCollapse.contains(entry)) {
+                        && isNotificationKeptForRemoteInputHistory(entry.key)) {
+                    mNotificationLifetimeFinishedCallback.onSafeToRemove(entry.key);
+                } else if (mEntriesKeptForRemoteInputActive.contains(entry)) {
                     // We're currently holding onto this notification, but from the apps point of
                     // view it is already canceled, so we'll need to cancel it on the apps behalf
                     // after sending - unless the app posts an update in the mean time, so wait a
                     // bit.
                     mPresenter.getHandler().postDelayed(() -> {
-                        if (mRemoteInputEntriesToRemoveOnCollapse.remove(entry)) {
-                            mEntryManager.removeNotification(entry.key, null);
+                        if (mEntriesKeptForRemoteInputActive.remove(entry)) {
+                            mNotificationLifetimeFinishedCallback.onSafeToRemove(entry.key);
                         }
                     }, REMOTE_INPUT_KEPT_ENTRY_AUTO_CANCEL_DELAY);
                 }
@@ -310,45 +331,74 @@
                 }
             }
         });
+        mSmartReplyController.setCallback((entry, reply) -> {
+            StatusBarNotification newSbn =
+                    rebuildNotificationWithRemoteInput(entry, reply, true /* showSpinner */);
+            mEntryManager.updateNotification(newSbn, null /* ranking */);
+        });
+    }
 
+    /**
+     * Adds all the notification lifetime extenders. Each extender represents a reason for the
+     * NotificationRemoteInputManager to keep a notification lifetime extended.
+     */
+    protected void addLifetimeExtenders() {
+        mLifetimeExtenders.add(new RemoteInputHistoryExtender());
+        mLifetimeExtenders.add(new SmartReplyHistoryExtender());
+        mLifetimeExtenders.add(new RemoteInputActiveExtender());
+    }
+
+    public ArrayList<NotificationLifetimeExtender> getLifetimeExtenders() {
+        return mLifetimeExtenders;
     }
 
     public RemoteInputController getController() {
         return mRemoteInputController;
     }
 
-    public void onUpdateNotification(NotificationData.Entry entry) {
-        mRemoteInputEntriesToRemoveOnCollapse.remove(entry);
-    }
-
-    /**
-     * Returns true if NotificationRemoteInputManager wants to keep this notification around.
-     *
-     * @param entry notification being removed
-     */
-    public boolean onRemoveNotification(NotificationData.Entry entry) {
-        if (entry != null && mRemoteInputController.isRemoteInputActive(entry)
-                && (entry.row != null && !entry.row.isDismissed())) {
-            mRemoteInputEntriesToRemoveOnCollapse.add(entry);
-            return true;
-        }
-        return false;
-    }
-
     public void onPerformRemoveNotification(StatusBarNotification n,
             NotificationData.Entry entry) {
+        if (mKeysKeptForRemoteInputHistory.contains(n.getKey())) {
+            mKeysKeptForRemoteInputHistory.remove(n.getKey());
+        }
         if (mRemoteInputController.isRemoteInputActive(entry)) {
             mRemoteInputController.removeRemoteInput(entry, null);
         }
     }
 
-    public void removeRemoteInputEntriesKeptUntilCollapsed() {
-        for (int i = 0; i < mRemoteInputEntriesToRemoveOnCollapse.size(); i++) {
-            NotificationData.Entry entry = mRemoteInputEntriesToRemoveOnCollapse.valueAt(i);
+    public void onPanelCollapsed() {
+        for (int i = 0; i < mEntriesKeptForRemoteInputActive.size(); i++) {
+            NotificationData.Entry entry = mEntriesKeptForRemoteInputActive.valueAt(i);
             mRemoteInputController.removeRemoteInput(entry, null);
-            mEntryManager.removeNotification(entry.key, mEntryManager.getLatestRankingMap());
+            if (mNotificationLifetimeFinishedCallback != null) {
+                mNotificationLifetimeFinishedCallback.onSafeToRemove(entry.key);
+            }
         }
-        mRemoteInputEntriesToRemoveOnCollapse.clear();
+        mEntriesKeptForRemoteInputActive.clear();
+    }
+
+    public boolean isNotificationKeptForRemoteInputHistory(String key) {
+        return mKeysKeptForRemoteInputHistory.contains(key);
+    }
+
+    public boolean shouldKeepForRemoteInputHistory(NotificationData.Entry entry) {
+        if (entry.row == null || entry.row.isDismissed()) {
+            return false;
+        }
+        if (!FORCE_REMOTE_INPUT_HISTORY) {
+            return false;
+        }
+        return (mRemoteInputController.isSpinning(entry.key) || entry.hasJustSentRemoteInput());
+    }
+
+    public boolean shouldKeepForSmartReplyHistory(NotificationData.Entry entry) {
+        if (entry.row == null || entry.row.isDismissed()) {
+            return false;
+        }
+        if (!FORCE_REMOTE_INPUT_HISTORY) {
+            return false;
+        }
+        return mSmartReplyController.isSendingSmartReply(entry.key);
     }
 
     public void checkRemoteInputOutside(MotionEvent event) {
@@ -359,11 +409,63 @@
         }
     }
 
+    @VisibleForTesting
+    StatusBarNotification rebuildNotificationForCanceledSmartReplies(
+            NotificationData.Entry entry) {
+        return rebuildNotificationWithRemoteInput(entry, null /* remoteInputTest */,
+                false /* showSpinner */);
+    }
+
+    @VisibleForTesting
+    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;
+
+        return new StatusBarNotification(
+                sbn.getPackageName(),
+                sbn.getOpPkg(),
+                sbn.getId(),
+                sbn.getTag(),
+                sbn.getUid(),
+                sbn.getInitialPid(),
+                newNotification,
+                sbn.getUser(),
+                sbn.getOverrideGroupKey(),
+                sbn.getPostTime());
+    }
+
     @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         pw.println("NotificationRemoteInputManager state:");
-        pw.print("  mRemoteInputEntriesToRemoveOnCollapse: ");
-        pw.println(mRemoteInputEntriesToRemoveOnCollapse);
+        pw.print("  mKeysKeptForRemoteInputHistory: ");
+        pw.println(mKeysKeptForRemoteInputHistory);
+        pw.print("  mEntriesKeptForRemoteInputActive: ");
+        pw.println(mEntriesKeptForRemoteInputActive);
     }
 
     public void bindRow(ExpandableNotificationRow row) {
@@ -372,8 +474,133 @@
     }
 
     @VisibleForTesting
-    public Set<NotificationData.Entry> getRemoteInputEntriesToRemoveOnCollapse() {
-        return mRemoteInputEntriesToRemoveOnCollapse;
+    public Set<NotificationData.Entry> getEntriesKeptForRemoteInputActive() {
+        return mEntriesKeptForRemoteInputActive;
+    }
+
+    /**
+     * NotificationRemoteInputManager has multiple reasons to keep notification lifetime extended
+     * so we implement multiple NotificationLifetimeExtenders
+     */
+    protected abstract class RemoteInputExtender implements NotificationLifetimeExtender {
+        @Override
+        public void setCallback(NotificationSafeToRemoveCallback callback) {
+            if (mNotificationLifetimeFinishedCallback == null) {
+                mNotificationLifetimeFinishedCallback = callback;
+            }
+        }
+    }
+
+    /**
+     * Notification is kept alive as it was cancelled in response to a remote input interaction.
+     * This allows us to show what you replied and allows you to continue typing into it.
+     */
+    protected class RemoteInputHistoryExtender extends RemoteInputExtender {
+        @Override
+        public boolean shouldExtendLifetime(@NonNull NotificationData.Entry entry) {
+            return shouldKeepForRemoteInputHistory(entry);
+        }
+
+        @Override
+        public void setShouldManageLifetime(NotificationData.Entry entry,
+                boolean shouldExtend) {
+            if (shouldExtend) {
+                CharSequence remoteInputText = entry.remoteInputText;
+                if (TextUtils.isEmpty(remoteInputText)) {
+                    remoteInputText = entry.remoteInputTextWhenReset;
+                }
+                StatusBarNotification newSbn = rebuildNotificationWithRemoteInput(entry,
+                        remoteInputText, false /* showSpinner */);
+                entry.onRemoteInputInserted();
+
+                if (newSbn == null) {
+                    return;
+                }
+
+                mEntryManager.updateNotification(newSbn, null);
+
+                // Ensure the entry hasn't already been removed. This can happen if there is an
+                // inflation exception while updating the remote history
+                if (entry.row == null || entry.row.isRemoved()) {
+                    return;
+                }
+
+                if (Log.isLoggable(TAG, Log.DEBUG)) {
+                    Log.d(TAG, "Keeping notification around after sending remote input "
+                            + entry.key);
+                }
+
+                mKeysKeptForRemoteInputHistory.add(entry.key);
+            } else {
+                mKeysKeptForRemoteInputHistory.remove(entry.key);
+            }
+        }
+    }
+
+    /**
+     * Notification is kept alive for smart reply history.  Similar to REMOTE_INPUT_HISTORY but with
+     * {@link SmartReplyController} specific logic
+     */
+    protected class SmartReplyHistoryExtender extends RemoteInputExtender {
+        @Override
+        public boolean shouldExtendLifetime(@NonNull NotificationData.Entry entry) {
+            return shouldKeepForSmartReplyHistory(entry);
+        }
+
+        @Override
+        public void setShouldManageLifetime(NotificationData.Entry entry,
+                boolean shouldExtend) {
+            if (shouldExtend) {
+                StatusBarNotification newSbn = rebuildNotificationForCanceledSmartReplies(entry);
+
+                if (newSbn == null) {
+                    return;
+                }
+
+                mEntryManager.updateNotification(newSbn, null);
+
+                if (entry.row == null || entry.row.isRemoved()) {
+                    return;
+                }
+
+                if (Log.isLoggable(TAG, Log.DEBUG)) {
+                    Log.d(TAG, "Keeping notification around after sending smart reply "
+                            + entry.key);
+                }
+
+                mKeysKeptForRemoteInputHistory.add(entry.key);
+            } else {
+                mKeysKeptForRemoteInputHistory.remove(entry.key);
+                mSmartReplyController.stopSending(entry);
+            }
+        }
+    }
+
+    /**
+     * Notification is kept alive because the user is still using the remote input
+     */
+    protected class RemoteInputActiveExtender extends RemoteInputExtender {
+        @Override
+        public boolean shouldExtendLifetime(@NonNull NotificationData.Entry entry) {
+            if (entry.row == null || entry.row.isDismissed()) {
+                return false;
+            }
+            return mRemoteInputController.isRemoteInputActive(entry);
+        }
+
+        @Override
+        public void setShouldManageLifetime(NotificationData.Entry entry,
+                boolean shouldExtend) {
+            if (shouldExtend) {
+                if (Log.isLoggable(TAG, Log.DEBUG)) {
+                    Log.d(TAG, "Keeping notification around while remote input active "
+                            + entry.key);
+                }
+                mEntriesKeptForRemoteInputActive.add(entry);
+            } else {
+                mEntriesKeptForRemoteInputActive.remove(entry);
+            }
+        }
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ScrimView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ScrimView.java
index eaa4c6d..3bc4342 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ScrimView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ScrimView.java
@@ -53,11 +53,8 @@
     private static final String TAG = "ScrimView";
     private final ColorExtractor.GradientColors mColors;
     private int mDensity;
-    private boolean mDrawAsSrc;
     private float mViewAlpha = 1.0f;
     private ValueAnimator mAlphaAnimator;
-    private Rect mExcludedRect = new Rect();
-    private boolean mHasExcludedArea;
     private Drawable mDrawable;
     private PorterDuffColorFilter mColorFilter;
     private int mTintColor;
@@ -137,59 +134,8 @@
 
     @Override
     protected void onDraw(Canvas canvas) {
-        if (mDrawAsSrc || mDrawable.getAlpha() > 0) {
-            if (!mHasExcludedArea) {
-                mDrawable.draw(canvas);
-            } else {
-                if (mExcludedRect.top > 0) {
-                    canvas.save();
-                    canvas.clipRect(0, 0, getWidth(), mExcludedRect.top);
-                    mDrawable.draw(canvas);
-                    canvas.restore();
-                }
-                if (mExcludedRect.left > 0) {
-                    canvas.save();
-                    canvas.clipRect(0, mExcludedRect.top, mExcludedRect.left,
-                            mExcludedRect.bottom);
-                    mDrawable.draw(canvas);
-                    canvas.restore();
-                }
-                if (mExcludedRect.right < getWidth()) {
-                    canvas.save();
-                    canvas.clipRect(mExcludedRect.right, mExcludedRect.top, getWidth(),
-                            mExcludedRect.bottom);
-                    mDrawable.draw(canvas);
-                    canvas.restore();
-                }
-                if (mExcludedRect.bottom < getHeight()) {
-                    canvas.save();
-                    canvas.clipRect(0, mExcludedRect.bottom, getWidth(), getHeight());
-                    mDrawable.draw(canvas);
-                    canvas.restore();
-                }
-                // We also need to draw the rounded corners of the background
-                canvas.save();
-                canvas.clipRect(mExcludedRect.left, mExcludedRect.top,
-                        mExcludedRect.left + mCornerRadius, mExcludedRect.top + mCornerRadius);
-                mDrawable.draw(canvas);
-                canvas.restore();
-                canvas.save();
-                canvas.clipRect(mExcludedRect.right - mCornerRadius, mExcludedRect.top,
-                        mExcludedRect.right, mExcludedRect.top + mCornerRadius);
-                mDrawable.draw(canvas);
-                canvas.restore();
-                canvas.save();
-                canvas.clipRect(mExcludedRect.left, mExcludedRect.bottom - mCornerRadius,
-                        mExcludedRect.left + mCornerRadius, mExcludedRect.bottom);
-                mDrawable.draw(canvas);
-                canvas.restore();
-                canvas.save();
-                canvas.clipRect(mExcludedRect.right - mCornerRadius,
-                        mExcludedRect.bottom - mCornerRadius,
-                        mExcludedRect.right, mExcludedRect.bottom);
-                mDrawable.draw(canvas);
-                canvas.restore();
-            }
+        if (mDrawable.getAlpha() > 0) {
+            mDrawable.draw(canvas);
         }
     }
 
@@ -198,7 +144,6 @@
         mDrawable.setCallback(this);
         mDrawable.setBounds(getLeft(), getTop(), getRight(), getBottom());
         mDrawable.setAlpha((int) (255 * mViewAlpha));
-        setDrawAsSrc(mDrawAsSrc);
         updateScreenSize();
         invalidate();
     }
@@ -211,12 +156,6 @@
         }
     }
 
-    public void setDrawAsSrc(boolean asSrc) {
-        mDrawAsSrc = asSrc;
-        PorterDuff.Mode mode = asSrc ? PorterDuff.Mode.SRC : PorterDuff.Mode.SRC_OVER;
-        mDrawable.setXfermode(new PorterDuffXfermode(mode));
-    }
-
     @Override
     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
         super.onLayout(changed, left, top, right, bottom);
@@ -328,22 +267,6 @@
         return mViewAlpha;
     }
 
-    public void setExcludedArea(Rect area) {
-        if (area == null) {
-            mHasExcludedArea = false;
-            invalidate();
-            return;
-        }
-
-        int left = Math.max(area.left, 0);
-        int top = Math.max(area.top, 0);
-        int right = Math.min(area.right, getWidth());
-        int bottom = Math.min(area.bottom, getHeight());
-        mExcludedRect.set(left, top, right, bottom);
-        mHasExcludedArea = left < right && top < bottom;
-        invalidate();
-    }
-
     public void setChangeRunnable(Runnable changeRunnable) {
         mChangeRunnable = changeRunnable;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java b/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java
index e43c9e5..fb888dd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java
@@ -33,20 +33,19 @@
 public class SmartReplyController {
     private IStatusBarService mBarService;
     private Set<String> mSendingKeys = new ArraySet<>();
+    private Callback mCallback;
 
     public SmartReplyController() {
         mBarService = Dependency.get(IStatusBarService.class);
     }
 
-    public void smartReplySent(NotificationData.Entry entry, int replyIndex, CharSequence reply) {
-        NotificationEntryManager notificationEntryManager
-                = Dependency.get(NotificationEntryManager.class);
-        StatusBarNotification newSbn =
-                notificationEntryManager.rebuildNotificationWithRemoteInput(entry, reply,
-                        true /* showSpinner */);
-        notificationEntryManager.updateNotification(newSbn, null /* ranking */);
-        mSendingKeys.add(entry.key);
+    public void setCallback(Callback callback) {
+        mCallback = callback;
+    }
 
+    public void smartReplySent(NotificationData.Entry entry, int replyIndex, CharSequence reply) {
+        mCallback.onSmartReplySent(entry, reply);
+        mSendingKeys.add(entry.key);
         try {
             mBarService.onNotificationSmartReplySent(entry.notification.getKey(),
                     replyIndex);
@@ -77,4 +76,17 @@
             mSendingKeys.remove(entry.notification.getKey());
         }
     }
+
+    /**
+     * Callback for any class that needs to do something in response to a smart reply being sent.
+     */
+    public interface Callback {
+        /**
+         * A smart reply has just been sent for a notification
+         *
+         * @param entry the entry for the notification
+         * @param reply the reply that was sent
+         */
+        void onSmartReplySent(NotificationData.Entry entry, CharSequence reply);
+    }
 }
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 ed06752..304a00f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -495,32 +495,37 @@
     }
 
     @Override
-    public void onUserSwitched(int newUserId) {
-        super.onUserSwitched(newUserId);
-        if (mFullscreenUserSwitcher != null) {
-            mFullscreenUserSwitcher.onUserSwitched(newUserId);
-        }
-    }
-
-    @Override
     public void onStateChanged(int newState) {
         super.onStateChanged(newState);
-        CarUserManagerHelper helper = new CarUserManagerHelper(mContext);
-        if (!helper.isHeadlessSystemUser()) {
-            showUserSwitcher();
+        if (newState == StatusBarState.FULLSCREEN_USER_SWITCHER) {
+            if (!mFullscreenUserSwitcher.isVisible()) {
+                // Current execution path continues to set state after this, thus we deffer the
+                // dismissal to the next execution cycle.
+                postDismissKeyguard(); // Dismiss the keyguard if switcher is not visible.
+            }
+        } else {
+            mFullscreenUserSwitcher.hide();
         }
     }
 
     public void showUserSwitcher() {
-        if (mFullscreenUserSwitcher != null) {
-            if (mState == StatusBarState.FULLSCREEN_USER_SWITCHER) {
-                mFullscreenUserSwitcher.show();
-            } else {
-                mFullscreenUserSwitcher.hide();
-            }
+        if (mFullscreenUserSwitcher != null && mState == StatusBarState.FULLSCREEN_USER_SWITCHER) {
+            mFullscreenUserSwitcher.show(); // Makes the switcher visible.
         }
     }
 
+    public void postDismissKeyguard() {
+        mHandler.post(this::dismissKeyguard);
+    }
+
+    /**
+     * Dismisses the keyguard and shows bouncer if authentication is necessary.
+     */
+    public void dismissKeyguard() {
+        executeRunnableDismissingKeyguard(null/* runnable */, null /* cancelAction */,
+            true /* dismissShade */, true /* afterKeyguardGone */, true /* deferred */);
+    }
+
     @Override
     public void updateMediaMetaData(boolean metaDataChanged, boolean allowEnterAnimation) {
         // Do nothing, we don't want to display media art in the lock screen for a car.
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 67a76fd..2ebf5eb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
@@ -18,7 +18,6 @@
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
-import android.car.user.CarUserManagerHelper;
 import android.content.Context;
 import android.view.View;
 import android.view.ViewStub;
@@ -26,115 +25,87 @@
 import androidx.recyclerview.widget.GridLayoutManager;
 
 import com.android.systemui.R;
-import com.android.systemui.statusbar.phone.StatusBar;
 
 /**
  * Manages the fullscreen user switcher.
  */
 public class FullscreenUserSwitcher {
-    private final View mContainer;
-    private final View mParent;
     private final UserGridRecyclerView mUserGridView;
+    private final View mParent;
     private final int mShortAnimDuration;
-    private final StatusBar mStatusBar;
-    private final CarUserManagerHelper mCarUserManagerHelper;
-    private boolean mShowing;
+    private final CarStatusBar mStatusBar;
 
-    public FullscreenUserSwitcher(StatusBar statusBar, ViewStub containerStub, Context context) {
+    public FullscreenUserSwitcher(CarStatusBar statusBar, ViewStub containerStub, Context context) {
         mStatusBar = statusBar;
         mParent = containerStub.inflate();
-        mContainer = mParent.findViewById(R.id.container);
-        mUserGridView = mContainer.findViewById(R.id.user_grid);
+        mParent.setVisibility(View.VISIBLE);
+        View container = mParent.findViewById(R.id.container);
+
+        // Initialize user grid.
+        mUserGridView = container.findViewById(R.id.user_grid);
         GridLayoutManager layoutManager = new GridLayoutManager(context,
-                context.getResources().getInteger(R.integer.user_fullscreen_switcher_num_col));
+            context.getResources().getInteger(R.integer.user_fullscreen_switcher_num_col));
         mUserGridView.getRecyclerView().setLayoutManager(layoutManager);
         mUserGridView.buildAdapter();
         mUserGridView.setUserSelectionListener(this::onUserSelected);
 
-        mCarUserManagerHelper = new CarUserManagerHelper(context);
+        // Hide the user grid by default. It will only be made visible by clicking on a cancel
+        // button in a bouncer.
+        hide();
 
-        mShortAnimDuration = mContainer.getResources()
+        mShortAnimDuration = container.getResources()
             .getInteger(android.R.integer.config_shortAnimTime);
     }
 
+    /**
+     * Makes user grid visible.
+     */
     public void show() {
-        if (mCarUserManagerHelper.isHeadlessSystemUser()) {
-            showUserGrid();
-        }
-        if (mShowing) {
-            return;
-        }
-        mShowing = true;
-        mParent.setVisibility(View.VISIBLE);
-    }
-
-    public void hide() {
-        mShowing = false;
-        mParent.setVisibility(View.GONE);
-    }
-
-    public void onUserSwitched(int newUserId) {
-        toggleSwitchInProgress(false);
-        mParent.post(this::dismissKeyguard);
-    }
-
-    private void onUserSelected(UserGridRecyclerView.UserRecord record) {
-        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() {
+    /**
+     * Hides the user grid.
+     */
+    public void hide() {
         mUserGridView.setVisibility(View.INVISIBLE);
     }
 
-    // Dismisses the keyguard and shows bouncer if authentication is necessary.
-    private void dismissKeyguard() {
-        mStatusBar.executeRunnableDismissingKeyguard(null/* runnable */, null /* cancelAction */,
-                true /* dismissShade */, true /* afterKeyguardGone */, true /* deferred */);
+    /**
+     * @return {@code true} if user grid is visible, {@code false} otherwise.
+     */
+    public boolean isVisible() {
+        return mUserGridView.getVisibility() == View.VISIBLE;
     }
 
-    private void toggleSwitchInProgress(boolean inProgress) {
-        if (inProgress) {
-            fadeOut(mContainer);
-        } else {
-            fadeIn(mContainer);
+    /**
+     * Every time user clicks on an item in the switcher, we hide the switcher, either
+     * gradually or immediately.
+     *
+     * We dismiss the entire keyguard if user clicked on the foreground user (user we're already
+     * logged in as).
+     */
+    private void onUserSelected(UserGridRecyclerView.UserRecord record) {
+        if (record.mIsForeground) {
+            hide();
+            mStatusBar.dismissKeyguard();
+            return;
         }
+        // Switching is about to happen, since it takes time, fade out the switcher gradually.
+        fadeOut();
     }
 
-    private void fadeOut(View view) {
-        view.animate()
+    private void fadeOut() {
+        mUserGridView.animate()
                 .alpha(0.0f)
                 .setDuration(mShortAnimDuration)
                 .setListener(new AnimatorListenerAdapter() {
                     @Override
                     public void onAnimationEnd(Animator animation) {
-                        view.setVisibility(View.GONE);
+                        hide();
+                        mUserGridView.setAlpha(1.0f);
                     }
                 });
-    }
 
-    private void fadeIn(View view) {
-        view.animate()
-                .alpha(1.0f)
-                .setDuration(mShortAnimDuration)
-                .setListener(new AnimatorListenerAdapter() {
-                    @Override
-                    public void onAnimationStart(Animator animator) {
-                        view.setAlpha(0.0f);
-                        view.setVisibility(View.VISIBLE);
-                    }
-                });
     }
-}
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
index b655a6b..ac01fa3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
@@ -37,7 +37,6 @@
 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;
@@ -58,6 +57,7 @@
 import com.android.systemui.R;
 import com.android.systemui.UiOffloadThread;
 import com.android.systemui.recents.misc.SystemServicesProxy;
+import com.android.systemui.statusbar.NotificationLifetimeExtender;
 import com.android.systemui.statusbar.NotificationListener;
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
 import com.android.systemui.statusbar.NotificationMediaManager;
@@ -65,7 +65,6 @@
 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;
@@ -100,8 +99,6 @@
     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 =
@@ -124,8 +121,6 @@
             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;
@@ -139,13 +134,9 @@
     protected boolean mUseHeadsUp = false;
     protected boolean mDisableNotificationAlerts;
     protected NotificationListContainer mListContainer;
+    protected final ArrayList<NotificationLifetimeExtender> mNotificationLifetimeExtenders
+            = new ArrayList<>();
     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 {
@@ -198,14 +189,6 @@
                 }
             };
 
-    public NotificationListenerService.RankingMap getLatestRankingMap() {
-        return mLatestRankingMap;
-    }
-
-    public void setLatestRankingMap(NotificationListenerService.RankingMap latestRankingMap) {
-        mLatestRankingMap = latestRankingMap;
-    }
-
     public void setDisableNotificationAlerts(boolean disableNotificationAlerts) {
         mDisableNotificationAlerts = disableNotificationAlerts;
         mHeadsUpObserver.onChange(true);
@@ -215,18 +198,6 @@
         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:");
@@ -240,8 +211,6 @@
         }
         pw.print("  mUseHeadsUp=");
         pw.println(mUseHeadsUp);
-        pw.print("  mKeysKeptForRemoteInput: ");
-        pw.println(mKeysKeptForRemoteInput);
     }
 
     public NotificationEntryManager(Context context) {
@@ -294,6 +263,14 @@
                     mHeadsUpObserver);
         }
 
+        mNotificationLifetimeExtenders.add(mHeadsUpManager);
+        mNotificationLifetimeExtenders.add(mGutsManager);
+        mNotificationLifetimeExtenders.addAll(mRemoteInputManager.getLifetimeExtenders());
+
+        for (NotificationLifetimeExtender extender : mNotificationLifetimeExtenders) {
+            extender.setCallback(key -> removeNotification(key, mLatestRankingMap));
+        }
+
         mDeviceProvisionedController.addCallback(mDeviceProvisionedListener);
 
         mHeadsUpObserver.onChange(true); // set up
@@ -397,11 +374,6 @@
                 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();
@@ -433,7 +405,7 @@
      * WARNING: this will call back into us.  Don't hold any locks.
      */
     void handleNotificationError(StatusBarNotification n, String message) {
-        removeNotification(n.getKey(), null);
+        removeNotificationInternal(n.getKey(), null, true /* forceRemove */);
         try {
             mBarService.onNotificationError(n.getPackageName(), n.getTag(), n.getId(), n.getUid(),
                     n.getInitialPid(), message, n.getUserId());
@@ -487,7 +459,11 @@
 
     @Override
     public void removeNotification(String key, NotificationListenerService.RankingMap ranking) {
-        boolean deferRemoval = false;
+        removeNotificationInternal(key, ranking, false /* forceRemove */);
+    }
+
+    private void removeNotificationInternal(String key,
+            @Nullable NotificationListenerService.RankingMap ranking, boolean forceRemove) {
         abortExistingInflation(key);
         if (mHeadsUpManager.contains(key)) {
             // A cancel() in response to a remote input shouldn't be delayed, as it makes the
@@ -497,154 +473,53 @@
             boolean ignoreEarliestRemovalTime = mRemoteInputManager.getController().isSpinning(key)
                     && !FORCE_REMOTE_INPUT_HISTORY
                     || !mVisualStabilityManager.isReorderingAllowed();
-            deferRemoval = !mHeadsUpManager.removeNotification(key,  ignoreEarliestRemovalTime);
+
+            // Attempt to remove notification.
+            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));
+        if (entry == null) {
+            mCallback.onNotificationRemoved(key, null /* old */);
             return;
         }
 
-        if (mRemoteInputManager.onRemoveNotification(entry)) {
-            mLatestRankingMap = ranking;
-            return;
+        // If a manager needs to keep the notification around for whatever reason, we return early
+        // and keep the notification
+        if (!forceRemove) {
+            for (NotificationLifetimeExtender extender : mNotificationLifetimeExtenders) {
+                if (extender.shouldExtendLifetime(entry)) {
+                    mLatestRankingMap = ranking;
+                    extender.setShouldManageLifetime(entry, true /* shouldManage */);
+                    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;
+        // At this point, we are guaranteed the notification will be removed
+
+        // Ensure any managers keeping the lifetime extended stop managing the entry
+        for (NotificationLifetimeExtender extender: mNotificationLifetimeExtenders) {
+            extender.setShouldManageLifetime(entry, false /* shouldManage */);
         }
 
-        if (entry != null) {
-            mForegroundServiceController.removeNotification(entry.notification);
-        }
+        mMediaManager.onNotificationRemoved(key);
+        mForegroundServiceController.removeNotification(entry.notification);
 
-        if (entry != null && entry.row != null) {
+        if (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);
@@ -683,9 +558,9 @@
                 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));
+                boolean keepForReply =
+                        mRemoteInputManager.shouldKeepForRemoteInputHistory(childEntry)
+                        || mRemoteInputManager.shouldKeepForSmartReplyHistory(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!
@@ -868,13 +743,11 @@
         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 is updated so it is essentially re-added and thus alive again.  Don't need
+        // to keep its lifetime extended.
+        for (NotificationLifetimeExtender extender : mNotificationLifetimeExtenders) {
+            extender.setShouldManageLifetime(entry, false /* shouldManage */);
         }
 
         Notification n = notification.getNotification();
@@ -1080,20 +953,6 @@
         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.
      */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ShadeViewRefactor.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ShadeViewRefactor.java
new file mode 100644
index 0000000..f204c42
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ShadeViewRefactor.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 java.lang.annotation;
+
+@Retention(RetentionPolicy.SOURCE)
+public @interface ShadeViewRefactor {
+  /**
+   * Returns the refactor component.
+   * @return the refactor component.
+   */
+  RefactorComponent value();
+
+  public enum RefactorComponent {
+    ADAPTER,
+    LAYOUT_ALGORITHM,
+    STATE_RESOLVER,
+    DECORATOR,
+    INPUT,
+    COORDINATOR,
+    SHADE_VIEW
+  }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index 67db68d..216ed68 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -1141,9 +1141,13 @@
     }
 
     private void updateNotificationColor() {
+        Configuration currentConfig = getResources().getConfiguration();
+        boolean nightMode = (currentConfig.uiMode & Configuration.UI_MODE_NIGHT_MASK)
+                == Configuration.UI_MODE_NIGHT_YES;
+
         mNotificationColor = ContrastColorUtil.resolveContrastColor(mContext,
                 getStatusBarNotification().getNotification().color,
-                getBackgroundColorWithoutTint());
+                getBackgroundColorWithoutTint(), nightMode);
         mNotificationColorAmbient = ContrastColorUtil.resolveAmbientColor(mContext,
                 getStatusBarNotification().getNotification().color);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
index e635976..f4ef0f8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
@@ -38,27 +38,27 @@
 import android.view.View;
 import android.view.accessibility.AccessibilityManager;
 
+import com.android.internal.annotations.VisibleForTesting;
 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.NotificationLifetimeExtender;
+import com.android.systemui.statusbar.notification.NotificationData;
 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 {
+public class NotificationGutsManager implements Dumpable, NotificationLifetimeExtender {
     private static final String TAG = "NotificationGutsManager";
 
     // Must match constant in Settings. Used to highlight preferences when linking to Settings.
@@ -75,12 +75,13 @@
     // which notification is currently being longpress-examined by the user
     private NotificationGuts mNotificationGutsExposed;
     private NotificationMenuRowPlugin.MenuItem mGutsMenuItem;
-    protected NotificationPresenter mPresenter;
-    protected NotificationEntryManager mEntryManager;
+    private NotificationPresenter mPresenter;
+    private NotificationSafeToRemoveCallback mNotificationLifetimeFinishedCallback;
     private NotificationListContainer mListContainer;
     private NotificationInfo.CheckSaveListener mCheckSaveListener;
     private OnSettingsClickListener mOnSettingsClickListener;
-    private String mKeyToRemoveOnGutsClosed;
+    @VisibleForTesting
+    protected String mKeyToRemoveOnGutsClosed;
 
     public NotificationGutsManager(Context context) {
         mContext = context;
@@ -91,24 +92,15 @@
     }
 
     public void setUpWithPresenter(NotificationPresenter presenter,
-            NotificationEntryManager entryManager, NotificationListContainer listContainer,
+            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);
@@ -171,7 +163,9 @@
             String key = sbn.getKey();
             if (key.equals(mKeyToRemoveOnGutsClosed)) {
                 mKeyToRemoveOnGutsClosed = null;
-                mEntryManager.removeNotification(key, mEntryManager.getLatestRankingMap());
+                if (mNotificationLifetimeFinishedCallback != null) {
+                    mNotificationLifetimeFinishedCallback.onSafeToRemove(key);
+                }
             }
         });
 
@@ -410,6 +404,37 @@
     }
 
     @Override
+    public void setCallback(NotificationSafeToRemoveCallback callback) {
+        mNotificationLifetimeFinishedCallback = callback;
+    }
+
+    @Override
+    public boolean shouldExtendLifetime(NotificationData.Entry entry) {
+        return entry != null
+                &&(mNotificationGutsExposed != null
+                    && entry.row.getGuts() != null
+                    && mNotificationGutsExposed == entry.row.getGuts()
+                    && !mNotificationGutsExposed.isLeavebehind());
+    }
+
+    @Override
+    public void setShouldManageLifetime(NotificationData.Entry entry, boolean shouldExtend) {
+        if (shouldExtend) {
+            mKeyToRemoveOnGutsClosed = entry.key;
+            if (Log.isLoggable(TAG, Log.DEBUG)) {
+                Log.d(TAG, "Keeping notification because it's showing guts. " + entry.key);
+            }
+        } else {
+            if (mKeyToRemoveOnGutsClosed != null && mKeyToRemoveOnGutsClosed.equals(entry.key)) {
+                mKeyToRemoveOnGutsClosed = null;
+                if (Log.isLoggable(TAG, Log.DEBUG)) {
+                    Log.d(TAG, "Notification that was kept for guts was updated. " + entry.key);
+                }
+            }
+        }
+    }
+
+    @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         pw.println("NotificationGutsManager state:");
         pw.print("  mKeyToRemoveOnGutsClosed: ");
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index 4f554b6..52844fe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -134,6 +134,8 @@
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
+import java.lang.annotation.ShadeViewRefactor;
+import java.lang.annotation.ShadeViewRefactor.RefactorComponent;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
@@ -394,9 +396,6 @@
     };
     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;
@@ -468,18 +467,22 @@
     private Interpolator mDarkXInterpolator = Interpolators.FAST_OUT_SLOW_IN;
     private NotificationPanelView mNotificationPanel;
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public NotificationStackScrollLayout(Context context) {
         this(context, null);
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public NotificationStackScrollLayout(Context context, AttributeSet attrs) {
         this(context, attrs, 0);
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public NotificationStackScrollLayout(Context context, AttributeSet attrs, int defStyleAttr) {
         this(context, attrs, defStyleAttr, 0);
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public NotificationStackScrollLayout(Context context, AttributeSet attrs, int defStyleAttr,
             int defStyleRes) {
         super(context, attrs, defStyleAttr, defStyleRes);
@@ -527,6 +530,7 @@
     }
 
     @Override
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     protected void onFinishInflate() {
         super.onFinishInflate();
 
@@ -537,6 +541,7 @@
     }
 
     @Override
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void onDensityOrFontScaleChanged() {
         inflateFooterView();
         inflateEmptyShadeView();
@@ -544,6 +549,7 @@
     }
 
     @Override
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void onThemeChanged() {
         int which;
         if (mStatusBarState == StatusBarState.KEYGUARD
@@ -560,6 +566,7 @@
     }
 
     @VisibleForTesting
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void updateFooter() {
         boolean showDismissView = mClearAllEnabled && hasActiveClearableNotifications();
         boolean showFooterView = (showDismissView ||
@@ -573,6 +580,7 @@
     /**
      * Return whether there are any clearable notifications
      */
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public boolean hasActiveClearableNotifications() {
         int childCount = getChildCount();
         for (int i = 0; i < childCount; i++) {
@@ -587,7 +595,8 @@
         return false;
     }
 
-    public RemoteInputController.Delegate createDelegate() {
+  @ShadeViewRefactor(RefactorComponent.INPUT)
+  public RemoteInputController.Delegate createDelegate() {
         return new RemoteInputController.Delegate() {
             public void setRemoteInputActive(NotificationData.Entry entry,
                     boolean remoteInputActive) {
@@ -608,6 +617,7 @@
     }
 
     @Override
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
         Dependency.get(StatusBarStateController.class).addListener(mStateListener);
@@ -615,6 +625,7 @@
     }
 
     @Override
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     protected void onDetachedFromWindow() {
         super.onDetachedFromWindow();
         Dependency.get(StatusBarStateController.class).removeListener(mStateListener);
@@ -622,11 +633,13 @@
     }
 
     @Override
+    @ShadeViewRefactor(RefactorComponent.INPUT)
     public NotificationSwipeActionHelper getSwipeActionHelper() {
         return mSwipeHelper;
     }
 
     @Override
+    @ShadeViewRefactor(RefactorComponent.INPUT)
     public void onMenuClicked(View view, int x, int y, MenuItem item) {
         if (mLongPressListener == null) {
             return;
@@ -640,6 +653,7 @@
     }
 
     @Override
+    @ShadeViewRefactor(RefactorComponent.INPUT)
     public void onMenuReset(View row) {
         if (mTranslatingParentView != null && row == mTranslatingParentView) {
             mMenuExposedView = null;
@@ -648,6 +662,7 @@
     }
 
     @Override
+    @ShadeViewRefactor(RefactorComponent.INPUT)
     public void onMenuShown(View row) {
         mMenuExposedView = mTranslatingParentView;
         if (row instanceof ExpandableNotificationRow) {
@@ -659,6 +674,7 @@
     }
 
     @Override
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void onUiModeChanged() {
         mBgColor = mContext.getColor(R.color.notification_shade_background_color);
         updateBackgroundDimming();
@@ -673,6 +689,7 @@
         }
     }
 
+    @ShadeViewRefactor(RefactorComponent.DECORATOR)
     protected void onDraw(Canvas canvas) {
         if (mShouldDrawNotificationBackground
                 && (mCurrentBounds.top < mCurrentBounds.bottom || mAmbientState.isDark())) {
@@ -689,6 +706,7 @@
         }
     }
 
+    @ShadeViewRefactor(RefactorComponent.DECORATOR)
     private void drawBackground(Canvas canvas) {
         final int lockScreenLeft = mSidePaddings;
         final int lockScreenRight = getWidth() - mSidePaddings;
@@ -732,6 +750,7 @@
         updateClipping();
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     private void updateBackgroundDimming() {
         // No need to update the background color if it's not being drawn.
         if (!mShouldDrawNotificationBackground) {
@@ -758,6 +777,7 @@
         }
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     private void initView(Context context) {
         mScroller = new OverScroller(getContext());
         setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);
@@ -789,25 +809,12 @@
                 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();
-    }
-
+    @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     private void notifyHeightChangeListener(ExpandableView view) {
         notifyHeightChangeListener(view, false /* needsAnimation */);
     }
 
+    @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     private void notifyHeightChangeListener(ExpandableView view, boolean needsAnimation) {
         if (mOnHeightChangedListener != null) {
             mOnHeightChangedListener.onHeightChanged(view, needsAnimation);
@@ -815,6 +822,7 @@
     }
 
     @Override
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
 
@@ -834,6 +842,7 @@
     }
 
     @Override
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     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;
@@ -856,6 +865,7 @@
         updateAlgorithmLayoutMinHeight();
     }
 
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     private void requestAnimationOnViewResize(ExpandableNotificationRow row) {
         if (mAnimationsEnabled && (mIsExpanded || row != null && row.isPinned())) {
             mNeedViewResizeAnimation = true;
@@ -863,18 +873,21 @@
         }
     }
 
+    @ShadeViewRefactor(RefactorComponent.ADAPTER)
     public void updateSpeedBumpIndex(int newIndex, boolean noAmbient) {
         mAmbientState.setSpeedBumpIndex(newIndex);
         mNoAmbient = noAmbient;
     }
 
     @Override
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     public void setChildLocationsChangedListener(
             NotificationLogger.OnChildLocationsChangedListener listener) {
         mListener = listener;
     }
 
     @Override
+    @ShadeViewRefactor(RefactorComponent.LAYOUT_ALGORITHM)
     public boolean isInVisibleLocation(ExpandableNotificationRow row) {
         ExpandableViewState childViewState = mCurrentStackScrollState.getViewStateForView(row);
         if (childViewState == null) {
@@ -889,12 +902,14 @@
         return true;
     }
 
+    @ShadeViewRefactor(RefactorComponent.LAYOUT_ALGORITHM)
     private void setMaxLayoutHeight(int maxLayoutHeight) {
         mMaxLayoutHeight = maxLayoutHeight;
         mShelf.setMaxLayoutHeight(maxLayoutHeight);
         updateAlgorithmHeightAndPadding();
     }
 
+    @ShadeViewRefactor(RefactorComponent.LAYOUT_ALGORITHM)
     private void updateAlgorithmHeightAndPadding() {
         mTopPadding = (int) MathUtils.lerp(mRegularTopPadding, mDarkTopPadding,
                 mInterpolatedDarkAmount);
@@ -903,6 +918,7 @@
         mAmbientState.setTopPadding(mTopPadding);
     }
 
+    @ShadeViewRefactor(RefactorComponent.LAYOUT_ALGORITHM)
     private void updateAlgorithmLayoutMinHeight() {
         mAmbientState.setLayoutMinHeight(mQsExpanded || isHeadsUpTransition()
                 ? getLayoutMinHeight() : 0);
@@ -912,6 +928,7 @@
      * 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.
      */
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     private void updateChildren() {
         updateScrollStateForAddedChildren();
         mAmbientState.setCurrentScrollVelocity(mScroller.isFinished()
@@ -926,6 +943,7 @@
         }
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     private void onPreDrawDuringAnimation() {
         mShelf.updateAppearance();
         updateClippingToTopRoundedCorner();
@@ -934,6 +952,7 @@
         }
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     private void updateClippingToTopRoundedCorner() {
         Float clipStart = (float) mTopPadding
                 + mStackTranslation
@@ -956,6 +975,7 @@
         }
     }
 
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     private void updateScrollStateForAddedChildren() {
         if (mChildrenToAddAnimated.isEmpty()) {
             return;
@@ -979,6 +999,7 @@
         clampScrollPosition();
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     private void updateForcedScroll() {
         if (mForcedScroll != null && (!mForcedScroll.hasFocus()
                 || !mForcedScroll.isAttachedToWindow())) {
@@ -1000,6 +1021,7 @@
         }
     }
 
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     private void requestChildrenUpdate() {
         if (!mChildrenUpdateRequested) {
             getViewTreeObserver().addOnPreDrawListener(mChildrenUpdater);
@@ -1008,10 +1030,12 @@
         }
     }
 
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     private boolean isCurrentlyAnimating() {
         return mStateAnimator.isRunning();
     }
 
+    @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     private void clampScrollPosition() {
         int scrollRange = getScrollRange();
         if (scrollRange < mOwnScrollY) {
@@ -1019,10 +1043,12 @@
         }
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public int getTopPadding() {
         return mTopPadding;
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     private void setTopPadding(int topPadding, boolean animate) {
         if (mRegularTopPadding != topPadding) {
             mRegularTopPadding = topPadding;
@@ -1044,6 +1070,7 @@
      *
      * @param height the expanded height of the panel
      */
+    @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     public void setExpandedHeight(float height) {
         mExpandedHeight = height;
         setIsExpanded(height > 0);
@@ -1110,6 +1137,7 @@
         }
     }
 
+    @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     private void setRequestedClipBounds(Rect clipRect) {
         mRequestedClipBounds = clipRect;
         updateClipping();
@@ -1118,17 +1146,18 @@
     /**
      * Return the height of the content ignoring the footer.
      */
+    @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     public int getIntrinsicContentHeight() {
         return mIntrinsicContentHeight;
     }
 
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     public void updateClipping() {
         boolean animatingClipping = mInterpolatedDarkAmount > 0 && mInterpolatedDarkAmount < 1;
         boolean clipped = mRequestedClipBounds != null && !mInHeadsUpPinnedMode
                 && !mHeadsUpAnimatingAway;
         if (mIsClipped != clipped) {
             mIsClipped = clipped;
-            updateFadingState();
         }
 
         if (animatingClipping) {
@@ -1144,6 +1173,7 @@
      * @return The translation at the beginning when expanding.
      * Measured relative to the resting position.
      */
+    @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     private float getExpandTranslationStart() {
         return -mTopPadding + getMinExpansionHeight();
     }
@@ -1152,6 +1182,7 @@
      * @return the position from where the appear transition starts when expanding.
      * Measured in absolute height.
      */
+    @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     private float getAppearStartPosition() {
         if (isHeadsUpTransition()) {
             return mHeadsUpInset + mFirstVisibleBackgroundChild.getPinnedHeadsUpHeight();
@@ -1164,6 +1195,7 @@
      * intrinsic height, which also includes whether the notification is system expanded and
      * is mainly used when dragging down from a heads up notification.
      */
+    @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     private int getTopHeadsUpPinnedHeight() {
         NotificationData.Entry topEntry = mHeadsUpManager.getTopEntry();
         if (topEntry == null) {
@@ -1184,6 +1216,7 @@
      * @return the position from where the appear transition ends when expanding.
      * Measured in absolute height.
      */
+    @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     private float getAppearEndPosition() {
         int appearPosition;
         int notGoneChildCount = getNotGoneChildCount();
@@ -1203,6 +1236,7 @@
         return appearPosition + (onKeyguard() ? mTopPadding : mIntrinsicPadding);
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     private boolean isHeadsUpTransition() {
         return mTrackingHeadsUp && mFirstVisibleBackgroundChild != null
                 && mAmbientState.isAboveShelf(mFirstVisibleBackgroundChild);
@@ -1212,6 +1246,7 @@
      * @param height the height of the panel
      * @return the fraction of the appear animation that has been performed
      */
+    @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     public float getAppearFraction(float height) {
         float appearEndPosition = getAppearEndPosition();
         float appearStartPosition = getAppearStartPosition();
@@ -1219,10 +1254,12 @@
                 / (appearEndPosition - appearStartPosition);
     }
 
+    @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     public float getStackTranslation() {
         return mStackTranslation;
     }
 
+    @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     private void setStackTranslation(float stackTranslation) {
         if (stackTranslation != mStackTranslation) {
             mStackTranslation = stackTranslation;
@@ -1237,19 +1274,23 @@
      *
      * @return either the layout height or the externally defined height, whichever is smaller
      */
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     private int getLayoutHeight() {
         return Math.min(mMaxLayoutHeight, mCurrentStackHeight);
     }
 
+    @ShadeViewRefactor(RefactorComponent.ADAPTER)
     public int getFirstItemMinHeight() {
         final ExpandableView firstChild = getFirstChildNotGone();
         return firstChild != null ? firstChild.getMinHeight() : mCollapsedSize;
     }
 
+    @ShadeViewRefactor(RefactorComponent.INPUT)
     public void setLongPressListener(ExpandableNotificationRow.LongPressListener listener) {
         mLongPressListener = listener;
     }
 
+    @ShadeViewRefactor(RefactorComponent.ADAPTER)
     public void setQsContainer(ViewGroup qsContainer) {
         mQsContainer = qsContainer;
     }
@@ -1259,6 +1300,7 @@
      * re-invoking dismiss logic in case the notification has not made its way out yet).
      */
     @Override
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void onChildDismissed(View view) {
         ExpandableNotificationRow row = (ExpandableNotificationRow) view;
         if (!row.isDismissed()) {
@@ -1276,6 +1318,8 @@
      *
      * @param view view (e.g. notification) to dismiss from the layout
      */
+
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     private void handleChildViewDismissed(View view) {
         if (mDismissAllInProgress) {
             return;
@@ -1315,6 +1359,7 @@
     }
 
     @Override
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void onChildSnappedBack(View animView, float targetLeft) {
         mAmbientState.onDragFinished(animView);
         updateContinuousShadowDrawing();
@@ -1335,12 +1380,14 @@
     }
 
     @Override
+    @ShadeViewRefactor(RefactorComponent.INPUT)
     public boolean updateSwipeProgress(View animView, boolean dismissable, float swipeProgress) {
         // Returning true prevents alpha fading.
         return !mFadeNotificationsOnDismiss;
     }
 
     @Override
+    @ShadeViewRefactor(RefactorComponent.INPUT)
     public void onBeginDrag(View v) {
         mFalsingManager.onNotificatonStartDismissing();
         setSwipingInProgress(true);
@@ -1353,6 +1400,7 @@
         requestChildrenUpdate();
     }
 
+    @ShadeViewRefactor(RefactorComponent.ADAPTER)
     public static boolean isPinnedHeadsUp(View v) {
         if (v instanceof ExpandableNotificationRow) {
             ExpandableNotificationRow row = (ExpandableNotificationRow) v;
@@ -1361,6 +1409,7 @@
         return false;
     }
 
+    @ShadeViewRefactor(RefactorComponent.ADAPTER)
     private boolean isHeadsUp(View v) {
         if (v instanceof ExpandableNotificationRow) {
             ExpandableNotificationRow row = (ExpandableNotificationRow) v;
@@ -1370,17 +1419,20 @@
     }
 
     @Override
+    @ShadeViewRefactor(RefactorComponent.INPUT)
     public void onDragCancelled(View v) {
         mFalsingManager.onNotificatonStopDismissing();
         setSwipingInProgress(false);
     }
 
     @Override
+    @ShadeViewRefactor(RefactorComponent.INPUT)
     public float getFalsingThresholdFactor() {
         return mStatusBar.isWakeUpComingFromTouch() ? 1.5f : 1.0f;
     }
 
     @Override
+    @ShadeViewRefactor(RefactorComponent.INPUT)
     public View getChildAtPosition(MotionEvent ev) {
         View child = getChildAtPosition(ev.getX(), ev.getY());
         if (child instanceof ExpandableNotificationRow) {
@@ -1401,6 +1453,7 @@
         return child;
     }
 
+    @ShadeViewRefactor(RefactorComponent.INPUT)
     public ExpandableView getClosestChildAtRawPosition(float touchX, float touchY) {
         getLocationOnScreen(mTempInt2);
         float localTouchY = touchY - mTempInt2[1];
@@ -1431,12 +1484,14 @@
     }
 
     @Override
+    @ShadeViewRefactor(RefactorComponent.INPUT)
     public ExpandableView getChildAtRawPosition(float touchX, float touchY) {
         getLocationOnScreen(mTempInt2);
         return getChildAtPosition(touchX - mTempInt2[0], touchY - mTempInt2[1]);
     }
 
     @Override
+    @ShadeViewRefactor(RefactorComponent.INPUT)
     public ExpandableView getChildAtPosition(float touchX, float touchY) {
         return getChildAtPosition(touchX, touchY, true /* requireMinHeight */);
 
@@ -1450,6 +1505,7 @@
      * @param requireMinHeight Whether a minimum height is required for a child to be returned.
      * @return the child at the given location.
      */
+    @ShadeViewRefactor(RefactorComponent.INPUT)
     private ExpandableView getChildAtPosition(float touchX, float touchY,
             boolean requireMinHeight) {
         // find the view under the pointer, accounting for GONE views
@@ -1490,6 +1546,7 @@
     }
 
     @Override
+    @ShadeViewRefactor(RefactorComponent.ADAPTER)
     public boolean canChildBeExpanded(View v) {
         return v instanceof ExpandableNotificationRow
                 && ((ExpandableNotificationRow) v).isExpandable()
@@ -1499,6 +1556,7 @@
 
     /* Only ever called as a consequence of an expansion gesture in the shade. */
     @Override
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void setUserExpandedChild(View v, boolean userExpanded) {
         if (v instanceof ExpandableNotificationRow) {
             ExpandableNotificationRow row = (ExpandableNotificationRow) v;
@@ -1521,6 +1579,7 @@
     }
 
     @Override
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void setExpansionCancelled(View v) {
         if (v instanceof ExpandableNotificationRow) {
             ((ExpandableNotificationRow) v).setGroupExpansionChanging(false);
@@ -1528,6 +1587,7 @@
     }
 
     @Override
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void setUserLockedChild(View v, boolean userLocked) {
         if (v instanceof ExpandableNotificationRow) {
             ((ExpandableNotificationRow) v).setUserLocked(userLocked);
@@ -1537,6 +1597,7 @@
     }
 
     @Override
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     public void expansionStateChanged(boolean isExpanding) {
         mExpandingNotification = isExpanding;
         if (!mExpandedInThisMotion) {
@@ -1546,14 +1607,17 @@
     }
 
     @Override
+    @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     public int getMaxExpandHeight(ExpandableView view) {
         return view.getMaxContentHeight();
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void setScrollingEnabled(boolean enable) {
         mScrollingEnabled = enable;
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void lockScrollTo(View v) {
         if (mForcedScroll == v) {
             return;
@@ -1562,6 +1626,7 @@
         scrollTo(v);
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public boolean scrollTo(View v) {
         ExpandableView expandableView = (ExpandableView) v;
         int positionInLinearLayout = getPositionInLinearLayout(v);
@@ -1583,6 +1648,7 @@
      * @return the scroll necessary to make the bottom edge of {@param v} align with the top of
      * the IME.
      */
+    @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     private int targetScrollForView(ExpandableView v, int positionInLinearLayout) {
         return positionInLinearLayout + v.getIntrinsicHeight() +
                 getImeInset() - getHeight()
@@ -1590,6 +1656,7 @@
     }
 
     @Override
+    @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     public WindowInsets onApplyWindowInsets(WindowInsets insets) {
         mBottomInset = insets.getSystemWindowInsetBottom();
 
@@ -1607,6 +1674,7 @@
         return insets;
     }
 
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     private Runnable mReclamp = new Runnable() {
         @Override
         public void run() {
@@ -1618,28 +1686,34 @@
         }
     };
 
-    private void setExpandingEnabled(boolean enable) {
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
+    public void setExpandingEnabled(boolean enable) {
         mExpandHelper.setEnabled(enable);
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     private boolean isScrollingEnabled() {
         return mScrollingEnabled;
     }
 
     @Override
+    @ShadeViewRefactor(RefactorComponent.ADAPTER)
     public boolean canChildBeDismissed(View v) {
         return StackScrollAlgorithm.canChildBeDismissed(v);
     }
 
     @Override
+    @ShadeViewRefactor(RefactorComponent.INPUT)
     public boolean isAntiFalsingNeeded() {
         return onKeyguard();
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     private boolean onKeyguard() {
         return mStatusBarState == StatusBarState.KEYGUARD;
     }
 
+    @ShadeViewRefactor(RefactorComponent.INPUT)
     private void setSwipingInProgress(boolean isSwiped) {
         mSwipingInProgress = isSwiped;
         if (isSwiped) {
@@ -1648,6 +1722,7 @@
     }
 
     @Override
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     protected void onConfigurationChanged(Configuration newConfig) {
         super.onConfigurationChanged(newConfig);
         mStatusBarHeight = getResources().getDimensionPixelOffset(R.dimen.status_bar_height);
@@ -1658,12 +1733,14 @@
         initView(getContext());
     }
 
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     public void dismissViewAnimated(View child, Runnable endRunnable, int delay, long duration) {
         mSwipeHelper.dismissChild(child, 0, endRunnable, delay, true, duration,
                 true /* isDismissAll */);
     }
 
     @Override
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     public void snapViewIfNeeded(ExpandableNotificationRow child) {
         boolean animate = mIsExpanded || isPinnedHeadsUp(child);
         // If the child is showing the notification menu snap to that
@@ -1672,11 +1749,13 @@
     }
 
     @Override
+    @ShadeViewRefactor(RefactorComponent.ADAPTER)
     public ViewGroup getViewParentForNotification(NotificationData.Entry entry) {
         return this;
     }
 
     @Override
+    @ShadeViewRefactor(RefactorComponent.INPUT)
     public boolean onTouchEvent(MotionEvent ev) {
         boolean isCancelOrUp = ev.getActionMasked() == MotionEvent.ACTION_CANCEL
                 || ev.getActionMasked() == MotionEvent.ACTION_UP;
@@ -1725,6 +1804,7 @@
         return horizontalSwipeWantsIt || scrollerWantsIt || expandWantsIt || super.onTouchEvent(ev);
     }
 
+    @ShadeViewRefactor(RefactorComponent.INPUT)
     private void dispatchDownEventToScroller(MotionEvent ev) {
         MotionEvent downEvent = MotionEvent.obtain(ev);
         downEvent.setAction(MotionEvent.ACTION_DOWN);
@@ -1733,6 +1813,7 @@
     }
 
     @Override
+    @ShadeViewRefactor(RefactorComponent.INPUT)
     public boolean onGenericMotionEvent(MotionEvent event) {
         if (!isScrollingEnabled() || !mIsExpanded || mSwipingInProgress || mExpandingNotification
                 || mDisallowScrollingInThisMotion) {
@@ -1765,6 +1846,7 @@
         return super.onGenericMotionEvent(event);
     }
 
+    @ShadeViewRefactor(RefactorComponent.INPUT)
     private boolean onScrollTouch(MotionEvent ev) {
         if (!isScrollingEnabled()) {
             return false;
@@ -1901,10 +1983,12 @@
         return true;
     }
 
+    @ShadeViewRefactor(RefactorComponent.INPUT)
     protected boolean isInsideQsContainer(MotionEvent ev) {
         return ev.getY() < mQsContainer.getBottom();
     }
 
+    @ShadeViewRefactor(RefactorComponent.INPUT)
     private void onOverScrollFling(boolean open, int initialVelocity) {
         if (mOverscrollTopChangedListener != null) {
             mOverscrollTopChangedListener.flingTopOverscroll(initialVelocity, open);
@@ -1920,6 +2004,7 @@
      * @return The amount of scrolling to be performed by the scroller,
      * not handled by the overScroll amount.
      */
+    @ShadeViewRefactor(RefactorComponent.INPUT)
     private float overScrollUp(int deltaY, int range) {
         deltaY = Math.max(deltaY, 0);
         float currentTopAmount = getCurrentOverScrollAmount(true);
@@ -1953,6 +2038,7 @@
      * @return The amount of scrolling to be performed by the scroller,
      * not handled by the overScroll amount.
      */
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     private float overScrollDown(int deltaY) {
         deltaY = Math.min(deltaY, 0);
         float currentBottomAmount = getCurrentOverScrollAmount(false);
@@ -1977,6 +2063,7 @@
         return scrollAmount;
     }
 
+    @ShadeViewRefactor(RefactorComponent.INPUT)
     private void onSecondaryPointerUp(MotionEvent ev) {
         final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >>
                 MotionEvent.ACTION_POINTER_INDEX_SHIFT;
@@ -1994,12 +2081,14 @@
         }
     }
 
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     private void initVelocityTrackerIfNotExists() {
         if (mVelocityTracker == null) {
             mVelocityTracker = VelocityTracker.obtain();
         }
     }
 
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     private void recycleVelocityTracker() {
         if (mVelocityTracker != null) {
             mVelocityTracker.recycle();
@@ -2007,6 +2096,7 @@
         }
     }
 
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     private void initOrResetVelocityTracker() {
         if (mVelocityTracker == null) {
             mVelocityTracker = VelocityTracker.obtain();
@@ -2015,10 +2105,12 @@
         }
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void setFinishScrollingCallback(Runnable runnable) {
         mFinishScrollingCallback = runnable;
     }
 
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     private void animateScroll() {
         if (mScroller.computeScrollOffset()) {
             int oldY = mOwnScrollY;
@@ -2049,6 +2141,7 @@
         }
     }
 
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     private boolean customOverScrollBy(int deltaY, int scrollY, int scrollRangeY,
             int maxOverScrollY) {
 
@@ -2080,6 +2173,7 @@
      * @param onTop     Should the effect be applied on top of the scroller.
      * @param animate   Should an animation be performed.
      */
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     public void setOverScrolledPixels(float numPixels, boolean onTop, boolean animate) {
         setOverScrollAmount(numPixels * getRubberBandFactor(onTop), onTop, animate, true);
     }
@@ -2092,6 +2186,8 @@
      * @param onTop   Should the effect be applied on top of the scroller.
      * @param animate Should an animation be performed.
      */
+
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     public void setOverScrollAmount(float amount, boolean onTop, boolean animate) {
         setOverScrollAmount(amount, onTop, animate, true);
     }
@@ -2104,6 +2200,7 @@
      * @param animate         Should an animation be performed.
      * @param cancelAnimators Should running animations be cancelled.
      */
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     public void setOverScrollAmount(float amount, boolean onTop, boolean animate,
             boolean cancelAnimators) {
         setOverScrollAmount(amount, onTop, animate, cancelAnimators, isRubberbanded(onTop));
@@ -2119,6 +2216,7 @@
      * @param isRubberbanded  The value which will be passed to
      *                        {@link OnOverscrollTopChangedListener#onOverscrollTopChanged}
      */
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     public void setOverScrollAmount(float amount, boolean onTop, boolean animate,
             boolean cancelAnimators, boolean isRubberbanded) {
         if (cancelAnimators) {
@@ -2127,6 +2225,7 @@
         setOverScrollAmountInternal(amount, onTop, animate, isRubberbanded);
     }
 
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     private void setOverScrollAmountInternal(float amount, boolean onTop, boolean animate,
             boolean isRubberbanded) {
         amount = Math.max(0, amount);
@@ -2142,6 +2241,7 @@
         }
     }
 
+    @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     private void notifyOverscrollTopListener(float amount, boolean isRubberbanded) {
         mExpandHelper.onlyObserveMovements(amount > 1.0f);
         if (mDontReportNextOverScroll) {
@@ -2153,19 +2253,23 @@
         }
     }
 
+    @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     public void setOverscrollTopChangedListener(
             OnOverscrollTopChangedListener overscrollTopChangedListener) {
         mOverscrollTopChangedListener = overscrollTopChangedListener;
     }
 
+    @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     public float getCurrentOverScrollAmount(boolean top) {
         return mAmbientState.getOverScrollAmount(top);
     }
 
+    @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     public float getCurrentOverScrolledPixels(boolean top) {
         return top ? mOverScrolledTopPixels : mOverScrolledBottomPixels;
     }
 
+    @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     private void setOverScrolledPixels(float amount, boolean onTop) {
         if (onTop) {
             mOverScrolledTopPixels = amount;
@@ -2174,6 +2278,7 @@
         }
     }
 
+    @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     private void onCustomOverScrolled(int scrollY, boolean clampedY) {
         // Treat animating scrolls differently; see #computeScroll() for why.
         if (!mScroller.isFinished()) {
@@ -2193,6 +2298,7 @@
         }
     }
 
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     private void springBack() {
         int scrollRange = getScrollRange();
         boolean overScrolledTop = mOwnScrollY <= 0;
@@ -2216,6 +2322,7 @@
         }
     }
 
+    @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     private int getScrollRange() {
         // In current design, it only use the top HUN to treat all of HUNs
         // although there are more than one HUNs
@@ -2229,6 +2336,7 @@
         return scrollRange;
     }
 
+    @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     private int getImeInset() {
         return Math.max(0, mBottomInset - (getRootView().getHeight() - getHeight()));
     }
@@ -2236,6 +2344,7 @@
     /**
      * @return the first child which has visibility unequal to GONE
      */
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public ExpandableView getFirstChildNotGone() {
         int childCount = getChildCount();
         for (int i = 0; i < childCount; i++) {
@@ -2250,6 +2359,7 @@
     /**
      * @return the child before the given view which has visibility unequal to GONE
      */
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public ExpandableView getViewBeforeView(ExpandableView view) {
         ExpandableView previousView = null;
         int childCount = getChildCount();
@@ -2269,6 +2379,7 @@
      * @return The first child which has visibility unequal to GONE which is currently below the
      * given translationY or equal to it.
      */
+    @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     private View getFirstChildBelowTranlsationY(float translationY, boolean ignoreChildren) {
         int childCount = getChildCount();
         for (int i = 0; i < childCount; i++) {
@@ -2300,6 +2411,7 @@
     /**
      * @return the last child which has visibility unequal to GONE
      */
+    @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     public View getLastChildNotGone() {
         int childCount = getChildCount();
         for (int i = childCount - 1; i >= 0; i--) {
@@ -2314,6 +2426,7 @@
     /**
      * @return the number of children which have visibility unequal to GONE
      */
+    @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     public int getNotGoneChildCount() {
         int childCount = getChildCount();
         int count = 0;
@@ -2326,6 +2439,7 @@
         return count;
     }
 
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     private void updateContentHeight() {
         int height = 0;
         float previousPaddingRequest = mPaddingBetweenElements;
@@ -2399,15 +2513,18 @@
         mAmbientState.setLayoutMaxHeight(mContentHeight);
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     private boolean isPulsing(NotificationData.Entry entry) {
         return mAmbientState.isPulsing(entry);
     }
 
     @Override
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public boolean hasPulsingNotifications() {
         return mPulsing;
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     private void updateScrollability() {
         boolean scrollable = !mQsExpanded && getScrollRange() > 0;
         if (scrollable != mScrollable) {
@@ -2417,6 +2534,7 @@
         }
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     private void updateForwardAndBackwardScrollability() {
         boolean forwardScrollable = mScrollable && mOwnScrollY < getScrollRange();
         boolean backwardsScrollable = mScrollable && mOwnScrollY > 0;
@@ -2429,6 +2547,7 @@
         }
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     private void updateBackground() {
         // No need to update the background color if it's not being drawn.
         if (!mShouldDrawNotificationBackground || mAmbientState.isFullyDark()) {
@@ -2447,7 +2566,7 @@
                 startBackgroundAnimation();
             } else {
                 mCurrentBounds.set(mBackgroundBounds);
-                applyCurrentBackgroundBounds();
+                invalidate();
             }
         } else {
             abortBackgroundAnimators();
@@ -2456,6 +2575,7 @@
         mAnimateNextBackgroundTop = false;
     }
 
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     private void abortBackgroundAnimators() {
         if (mBottomAnimator != null) {
             mBottomAnimator.cancel();
@@ -2465,10 +2585,12 @@
         }
     }
 
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     private boolean areBoundsAnimating() {
         return mBottomAnimator != null || mTopAnimator != null;
     }
 
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     private void startBackgroundAnimation() {
         // left and right are always instantly applied
         mCurrentBounds.left = mBackgroundBounds.left;
@@ -2477,6 +2599,7 @@
         startTopAnimation();
     }
 
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     private void startTopAnimation() {
         int previousEndValue = mEndAnimationRect.top;
         int newEndValue = mBackgroundBounds.top;
@@ -2525,6 +2648,7 @@
         mTopAnimator = animator;
     }
 
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     private void startBottomAnimation() {
         int previousStartValue = mStartAnimationRect.bottom;
         int previousEndValue = mEndAnimationRect.bottom;
@@ -2573,33 +2697,22 @@
         mBottomAnimator = animator;
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     private void setBackgroundTop(int top) {
         mCurrentBounds.top = top;
-        applyCurrentBackgroundBounds();
+        invalidate();
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     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
      */
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     private void updateBackgroundBounds() {
         getLocationInWindow(mTempInt2);
         mBackgroundBounds.left = mTempInt2[0] + mSidePaddings;
@@ -2661,6 +2774,7 @@
         mBackgroundBounds.bottom = Math.max(bottom, top);
     }
 
+    @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     private ActivatableNotificationView getFirstPinnedHeadsUp() {
         int childCount = getChildCount();
         for (int i = 0; i < childCount; i++) {
@@ -2676,6 +2790,7 @@
         return null;
     }
 
+    @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     private ActivatableNotificationView getLastChildWithBackground() {
         int childCount = getChildCount();
         for (int i = childCount - 1; i >= 0; i--) {
@@ -2688,6 +2803,7 @@
         return null;
     }
 
+    @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     private ActivatableNotificationView getFirstChildWithBackground() {
         int childCount = getChildCount();
         for (int i = 0; i < childCount; i++) {
@@ -2707,6 +2823,7 @@
      *                  numbers mean that the finger/cursor is moving down the screen,
      *                  which means we want to scroll towards the top.
      */
+    @ShadeViewRefactor(RefactorComponent.INPUT)
     protected void fling(int velocityY) {
         if (getChildCount() > 0) {
             int scrollRange = getScrollRange();
@@ -2744,6 +2861,7 @@
      * @return Whether a fling performed on the top overscroll edge lead to the expanded
      * overScroll view (i.e QS).
      */
+    @ShadeViewRefactor(RefactorComponent.INPUT)
     private boolean shouldOverScrollFling(int initialVelocity) {
         float topOverScroll = getCurrentOverScrollAmount(true);
         return mScrolledToTopOnFirstDown
@@ -2761,6 +2879,7 @@
      * @param ignoreIntrinsicPadding if true, {@link #getIntrinsicPadding()} is ignored and
      *                               {@code qsHeight} is the final top padding
      */
+    @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     public void updateTopPadding(float qsHeight, boolean animate,
             boolean ignoreIntrinsicPadding) {
         int topPadding = (int) qsHeight;
@@ -2775,10 +2894,12 @@
         setExpandedHeight(mExpandedHeight);
     }
 
+    @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     public void setMaxTopPadding(int maxTopPadding) {
         mMaxTopPadding = maxTopPadding;
     }
 
+    @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     public int getLayoutMinHeight() {
         if (isHeadsUpTransition()) {
             return getTopHeadsUpPinnedHeight();
@@ -2786,6 +2907,7 @@
         return mShelf.getVisibility() == GONE ? 0 : mShelf.getIntrinsicHeight();
     }
 
+    @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     public int getFirstChildIntrinsicHeight() {
         final ExpandableView firstChild = getFirstChildNotGone();
         int firstChildMinHeight = firstChild != null
@@ -2799,10 +2921,13 @@
         return firstChildMinHeight;
     }
 
+    @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     public float getTopPaddingOverflow() {
         return mTopPaddingOverflow;
     }
 
+
+    @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     public int getPeekHeight() {
         final ExpandableView firstChild = getFirstChildNotGone();
         final int firstChildMinHeight = firstChild != null ? firstChild.getCollapsedHeight()
@@ -2814,10 +2939,12 @@
         return mIntrinsicPadding + firstChildMinHeight + shelfHeight;
     }
 
+    @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     private int clampPadding(int desiredPadding) {
         return Math.max(desiredPadding, mIntrinsicPadding);
     }
 
+    @ShadeViewRefactor(RefactorComponent.INPUT)
     private float getRubberBandFactor(boolean onTop) {
         if (!onTop) {
             return RUBBER_BAND_FACTOR_NORMAL;
@@ -2837,11 +2964,13 @@
      * rubberbanded, false if it is technically an overscroll but rather a motion to expand the
      * overscroll view (e.g. expand QS).
      */
+    @ShadeViewRefactor(RefactorComponent.INPUT)
     private boolean isRubberbanded(boolean onTop) {
         return !onTop || mExpandedInThisMotion || mIsExpansionChanging || mPanelTracking
                 || !mScrolledToTopOnFirstDown;
     }
 
+    @ShadeViewRefactor(RefactorComponent.INPUT)
     private void endDrag() {
         setIsBeingDragged(false);
 
@@ -2855,12 +2984,14 @@
         }
     }
 
+    @ShadeViewRefactor(RefactorComponent.INPUT)
     private void transformTouchEvent(MotionEvent ev, View sourceView, View targetView) {
         ev.offsetLocation(sourceView.getX(), sourceView.getY());
         ev.offsetLocation(-targetView.getX(), -targetView.getY());
     }
 
     @Override
+    @ShadeViewRefactor(RefactorComponent.INPUT)
     public boolean onInterceptTouchEvent(MotionEvent ev) {
         initDownStates(ev);
         handleEmptySpaceClick(ev);
@@ -2896,6 +3027,7 @@
         return swipeWantsIt || scrollWantsIt || expandWantsIt || super.onInterceptTouchEvent(ev);
     }
 
+    @ShadeViewRefactor(RefactorComponent.INPUT)
     private void handleEmptySpaceClick(MotionEvent ev) {
         switch (ev.getActionMasked()) {
             case MotionEvent.ACTION_MOVE:
@@ -2913,6 +3045,7 @@
         }
     }
 
+    @ShadeViewRefactor(RefactorComponent.INPUT)
     private void initDownStates(MotionEvent ev) {
         if (ev.getAction() == MotionEvent.ACTION_DOWN) {
             mExpandedInThisMotion = false;
@@ -2925,10 +3058,12 @@
         }
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void setChildTransferInProgress(boolean childTransferInProgress) {
         mChildTransferInProgress = childTransferInProgress;
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     @Override
     public void onViewRemoved(View child) {
         super.onViewRemoved(child);
@@ -2939,6 +3074,7 @@
         }
     }
 
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     @Override
     public void cleanUpViewState(View child) {
         if (child == mTranslatingParentView) {
@@ -2948,6 +3084,7 @@
     }
 
     @Override
+    @ShadeViewRefactor(RefactorComponent.INPUT)
     public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
         super.requestDisallowInterceptTouchEvent(disallowIntercept);
         if (disallowIntercept) {
@@ -2955,6 +3092,7 @@
         }
     }
 
+    @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     private void onViewRemovedInternal(View child, ViewGroup container) {
         if (mChangePositionInProgress) {
             // This is only a position change, don't do anything special
@@ -2979,6 +3117,7 @@
         focusNextViewIfFocused(child);
     }
 
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     private void focusNextViewIfFocused(View view) {
         if (view instanceof ExpandableNotificationRow) {
             ExpandableNotificationRow row = (ExpandableNotificationRow) view;
@@ -2998,6 +3137,7 @@
 
     }
 
+    @ShadeViewRefactor(RefactorComponent.ADAPTER)
     private boolean isChildInGroup(View child) {
         return child instanceof ExpandableNotificationRow
                 && mGroupManager.isChildInGroupWithSummary(
@@ -3010,6 +3150,7 @@
      * @param child The view to generate the remove animation for.
      * @return Whether an animation was generated.
      */
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     private boolean generateRemoveAnimation(View child) {
         if (removeRemovedChildFromHeadsUpChangeAnimations(child)) {
             mAddedHeadsUpChildren.remove(child);
@@ -3035,6 +3176,7 @@
         return false;
     }
 
+    @ShadeViewRefactor(RefactorComponent.ADAPTER)
     private boolean isClickedHeadsUp(View child) {
         return HeadsUpUtil.isClickedHeadsUpNotification(child);
     }
@@ -3044,6 +3186,7 @@
      *
      * @return whether any child was removed from the list to animate
      */
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     private boolean removeRemovedChildFromHeadsUpChangeAnimations(View child) {
         boolean hasAddEvent = false;
         for (Pair<ExpandableNotificationRow, Boolean> eventPair : mHeadsUpChangeAnimations) {
@@ -3068,6 +3211,7 @@
      * @return whether a view is not a top level child but a child notification and that group is
      * not expanded
      */
+    @ShadeViewRefactor(RefactorComponent.ADAPTER)
     private boolean isChildInInvisibleGroup(View child) {
         if (child instanceof ExpandableNotificationRow) {
             ExpandableNotificationRow row = (ExpandableNotificationRow) child;
@@ -3085,6 +3229,7 @@
      *
      * @param removedChild the removed child
      */
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     private void updateScrollStateForRemovedChild(ExpandableView removedChild) {
         int startingPosition = getPositionInLinearLayout(removedChild);
         float increasedPaddingAmount = removedChild.getIncreasedPaddingAmount();
@@ -3113,6 +3258,7 @@
         }
     }
 
+    @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     private int getIntrinsicHeight(View view) {
         if (view instanceof ExpandableView) {
             ExpandableView expandableView = (ExpandableView) view;
@@ -3121,6 +3267,7 @@
         return view.getHeight();
     }
 
+    @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     public int getPositionInLinearLayout(View requestedView) {
         ExpandableNotificationRow childInGroup = null;
         ExpandableNotificationRow requestedRow = null;
@@ -3182,11 +3329,13 @@
     }
 
     @Override
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void onViewAdded(View child) {
         super.onViewAdded(child);
         onViewAddedInternal(child);
     }
 
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     private void updateFirstAndLastBackgroundViews() {
         ActivatableNotificationView firstChild = getFirstChildWithBackground();
         ActivatableNotificationView lastChild = getLastChildWithBackground();
@@ -3205,6 +3354,7 @@
         invalidate();
     }
 
+    @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     private void onViewAddedInternal(View child) {
         updateHideSensitiveForChild(child);
         ((ExpandableView) child).setOnHeightChangedListener(this);
@@ -3213,6 +3363,7 @@
         updateChronometerForChild(child);
     }
 
+    @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     private void updateHideSensitiveForChild(View child) {
         if (child instanceof ExpandableView) {
             ExpandableView expandableView = (ExpandableView) child;
@@ -3221,15 +3372,18 @@
     }
 
     @Override
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void notifyGroupChildRemoved(View row, ViewGroup childrenContainer) {
         onViewRemovedInternal(row, childrenContainer);
     }
 
     @Override
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void notifyGroupChildAdded(View row) {
         onViewAddedInternal(row);
     }
 
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     public void setAnimationsEnabled(boolean animationsEnabled) {
         mAnimationsEnabled = animationsEnabled;
         updateNotificationAnimationStates();
@@ -3240,6 +3394,7 @@
         }
     }
 
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     private void updateNotificationAnimationStates() {
         boolean running = mAnimationsEnabled || hasPulsingNotifications();
         mShelf.setAnimationsEnabled(running);
@@ -3251,18 +3406,21 @@
         }
     }
 
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     private void updateAnimationState(View child) {
         updateAnimationState((mAnimationsEnabled || hasPulsingNotifications())
                 && (mIsExpanded || isPinnedHeadsUp(child)), child);
     }
 
     @Override
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void setExpandingNotification(ExpandableNotificationRow row) {
         mAmbientState.setExpandingNotification(row);
         requestChildrenUpdate();
     }
 
     @Override
+    @ShadeViewRefactor(RefactorComponent.ADAPTER)
     public void bindRow(ExpandableNotificationRow row) {
         row.setHeadsUpAnimatingAwayListener(animatingAway -> {
             mRoundnessManager.onHeadsupAnimatingAwayChanged(row, animatingAway);
@@ -3271,11 +3429,13 @@
     }
 
     @Override
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     public void applyExpandAnimationParams(ExpandAnimationParameters params) {
         mAmbientState.setExpandAnimationTopChange(params == null ? 0 : params.getTopChange());
         requestChildrenUpdate();
     }
 
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     private void updateAnimationState(boolean running, View child) {
         if (child instanceof ExpandableNotificationRow) {
             ExpandableNotificationRow row = (ExpandableNotificationRow) child;
@@ -3283,12 +3443,14 @@
         }
     }
 
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     public boolean isAddOrRemoveAnimationPending() {
         return mNeedsAnimation
                 && (!mChildrenToAddAnimated.isEmpty() || !mChildrenToRemoveAnimated.isEmpty());
     }
 
     @Override
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     public void generateAddAnimation(View child, boolean fromMoreCard) {
         if (mIsExpanded && mAnimationsEnabled && !mChangePositionInProgress) {
             // Generate Animations
@@ -3305,6 +3467,7 @@
     }
 
     @Override
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     public void changeViewPosition(View child, int newIndex) {
         int currentIndex = indexOfChild(child);
 
@@ -3336,6 +3499,7 @@
         }
     }
 
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     private void startAnimationToState() {
         if (mNeedsAnimation) {
             generateAllAnimationEvents();
@@ -3355,6 +3519,7 @@
         mGoToFullShadeDelay = 0;
     }
 
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     private void generateAllAnimationEvents() {
         generateHeadsUpAnimationEvents();
         generateChildRemovalEvents();
@@ -3374,6 +3539,7 @@
         generatePulsingAnimationEvent();
     }
 
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     private void generateHeadsUpAnimationEvents() {
         for (Pair<ExpandableNotificationRow, Boolean> eventPair : mHeadsUpChangeAnimations) {
             ExpandableNotificationRow row = eventPair.first;
@@ -3416,6 +3582,7 @@
         mAddedHeadsUpChildren.clear();
     }
 
+    @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     private boolean shouldHunAppearFromBottom(ExpandableViewState viewState) {
         if (viewState.yTranslation + viewState.height < mAmbientState.getMaxHeadsUpTranslation()) {
             return false;
@@ -3423,6 +3590,7 @@
         return true;
     }
 
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     private void generateGroupExpansionEvent() {
         // Generate a group expansion/collapsing event if there is such a group at all
         if (mExpandedGroupView != null) {
@@ -3432,6 +3600,7 @@
         }
     }
 
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     private void generateViewResizeEvent() {
         if (mNeedViewResizeAnimation) {
             boolean hasDisappearAnimation = false;
@@ -3452,6 +3621,7 @@
         mNeedViewResizeAnimation = false;
     }
 
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     private void generateSnapBackEvents() {
         for (View child : mSnappedBackChildren) {
             mAnimationEvents.add(new AnimationEvent(child,
@@ -3460,6 +3630,7 @@
         mSnappedBackChildren.clear();
     }
 
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     private void generateDragEvents() {
         for (View child : mDragAnimPendingChildren) {
             mAnimationEvents.add(new AnimationEvent(child,
@@ -3468,6 +3639,7 @@
         mDragAnimPendingChildren.clear();
     }
 
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     private void generateChildRemovalEvents() {
         for (View child : mChildrenToRemoveAnimated) {
             boolean childWasSwipedOut = mSwipedOutViews.contains(child);
@@ -3509,6 +3681,7 @@
         mChildrenToRemoveAnimated.clear();
     }
 
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     private void generatePositionChangeEvents() {
         for (View child : mChildrenChangingPositions) {
             mAnimationEvents.add(new AnimationEvent(child,
@@ -3522,6 +3695,7 @@
         }
     }
 
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     private void generateChildAdditionEvents() {
         for (View child : mChildrenToAddAnimated) {
             if (mFromMoreCardAdditions.contains(child)) {
@@ -3537,6 +3711,7 @@
         mFromMoreCardAdditions.clear();
     }
 
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     private void generateTopPaddingEvent() {
         if (mTopPaddingNeedsAnimation) {
             AnimationEvent event;
@@ -3553,6 +3728,7 @@
         mTopPaddingNeedsAnimation = false;
     }
 
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     private void generateActivateEvent() {
         if (mActivateNeedsAnimation) {
             mAnimationEvents.add(
@@ -3561,6 +3737,7 @@
         mActivateNeedsAnimation = false;
     }
 
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     private void generateAnimateEverythingEvent() {
         if (mEverythingNeedsAnimation) {
             mAnimationEvents.add(
@@ -3569,6 +3746,7 @@
         mEverythingNeedsAnimation = false;
     }
 
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     private void generateDimmedEvent() {
         if (mDimmedNeedsAnimation) {
             mAnimationEvents.add(
@@ -3577,6 +3755,7 @@
         mDimmedNeedsAnimation = false;
     }
 
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     private void generateHideSensitiveEvent() {
         if (mHideSensitiveNeedsAnimation) {
             mAnimationEvents.add(
@@ -3585,6 +3764,7 @@
         mHideSensitiveNeedsAnimation = false;
     }
 
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     private void generateDarkEvent() {
         if (mDarkNeedsAnimation) {
             AnimationEvent ev = new AnimationEvent(null,
@@ -3598,6 +3778,7 @@
         mDarkNeedsAnimation = false;
     }
 
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     private void generateGoToFullShadeEvent() {
         if (mGoToFullShadeNeedsAnimation) {
             mAnimationEvents.add(
@@ -3606,6 +3787,7 @@
         mGoToFullShadeNeedsAnimation = false;
     }
 
+    @ShadeViewRefactor(RefactorComponent.INPUT)
     private boolean onInterceptTouchEventScroll(MotionEvent ev) {
         if (!isScrollingEnabled()) {
             return false;
@@ -3715,6 +3897,7 @@
         return mIsBeingDragged;
     }
 
+    @ShadeViewRefactor(RefactorComponent.LAYOUT_ALGORITHM)
     protected StackScrollAlgorithm createStackScrollAlgorithm(Context context) {
         return new StackScrollAlgorithm(context);
     }
@@ -3722,6 +3905,7 @@
     /**
      * @return Whether the specified motion event is actually happening over the content.
      */
+    @ShadeViewRefactor(RefactorComponent.INPUT)
     private boolean isInContentBounds(MotionEvent event) {
         return isInContentBounds(event.getY());
     }
@@ -3729,10 +3913,12 @@
     /**
      * @return Whether a y coordinate is inside the content.
      */
+    @ShadeViewRefactor(RefactorComponent.INPUT)
     public boolean isInContentBounds(float y) {
         return y < getHeight() - getEmptyBottomMargin();
     }
 
+    @ShadeViewRefactor(RefactorComponent.INPUT)
     private void setIsBeingDragged(boolean isDragged) {
         mIsBeingDragged = isDragged;
         if (isDragged) {
@@ -3742,6 +3928,7 @@
     }
 
     @Override
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void onWindowFocusChanged(boolean hasWindowFocus) {
         super.onWindowFocusChanged(hasWindowFocus);
         if (!hasWindowFocus) {
@@ -3750,6 +3937,7 @@
     }
 
     @Override
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void clearChildFocus(View child) {
         super.clearChildFocus(child);
         if (mForcedScroll == child) {
@@ -3757,37 +3945,45 @@
         }
     }
 
+    @ShadeViewRefactor(RefactorComponent.INPUT)
     public void requestDisallowLongPress() {
         cancelLongPress();
     }
 
+    @ShadeViewRefactor(RefactorComponent.INPUT)
     public void requestDisallowDismiss() {
         mDisallowDismissInThisMotion = true;
     }
 
+    @ShadeViewRefactor(RefactorComponent.INPUT)
     public void cancelLongPress() {
         mSwipeHelper.cancelLongPress();
     }
 
     @Override
+    @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     public boolean isScrolledToTop() {
         return mOwnScrollY == 0;
     }
 
     @Override
+    @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     public boolean isScrolledToBottom() {
         return mOwnScrollY >= getScrollRange();
     }
 
     @Override
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public View getHostView() {
         return this;
     }
 
+    @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     public int getEmptyBottomMargin() {
         return Math.max(mMaxLayoutHeight - mContentHeight, 0);
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void checkSnoozeLeavebehind() {
         if (mCheckForLeavebehind) {
             mStatusBar.getGutsManager().closeAndSaveGuts(true /* removeLeavebehind */,
@@ -3797,16 +3993,19 @@
         }
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void resetCheckSnoozeLeavebehind() {
         mCheckForLeavebehind = true;
     }
 
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     public void onExpansionStarted() {
         mIsExpansionChanging = true;
         mAmbientState.setExpansionChanging(true);
         checkSnoozeLeavebehind();
     }
 
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     public void onExpansionStopped() {
         mIsExpansionChanging = false;
         resetCheckSnoozeLeavebehind();
@@ -3819,6 +4018,7 @@
         }
     }
 
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     private void clearUserLockedViews() {
         for (int i = 0; i < getChildCount(); i++) {
             ExpandableView child = (ExpandableView) getChildAt(i);
@@ -3829,6 +4029,7 @@
         }
     }
 
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     private void clearTemporaryViews() {
         // lets make sure nothing is transient anymore
         clearTemporaryViewsInGroup(this);
@@ -3841,27 +4042,32 @@
         }
     }
 
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     private void clearTemporaryViewsInGroup(ViewGroup viewGroup) {
         while (viewGroup != null && viewGroup.getTransientViewCount() != 0) {
             viewGroup.removeTransientView(viewGroup.getTransientView(0));
         }
     }
 
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     public void onPanelTrackingStarted() {
         mPanelTracking = true;
         mAmbientState.setPanelTracking(true);
     }
 
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     public void onPanelTrackingStopped() {
         mPanelTracking = false;
         mAmbientState.setPanelTracking(false);
     }
 
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     public void resetScrollPosition() {
         mScroller.abortAnimation();
         setOwnScrollY(0);
     }
 
+    @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     private void setIsExpanded(boolean isExpanded) {
         boolean changed = isExpanded != mIsExpanded;
         mIsExpanded = isExpanded;
@@ -3877,6 +4083,7 @@
         }
     }
 
+    @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     private void updateChronometers() {
         int childCount = getChildCount();
         for (int i = 0; i < childCount; i++) {
@@ -3884,6 +4091,7 @@
         }
     }
 
+    @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     private void updateChronometerForChild(View child) {
         if (child instanceof ExpandableNotificationRow) {
             ExpandableNotificationRow row = (ExpandableNotificationRow) child;
@@ -3892,6 +4100,7 @@
     }
 
     @Override
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     public void onHeightChanged(ExpandableView view, boolean needsAnimation) {
         updateContentHeight();
         updateScrollPositionOnExpandInBottom(view);
@@ -3911,11 +4120,13 @@
     }
 
     @Override
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void onReset(ExpandableView view) {
         updateAnimationState(view);
         updateChronometerForChild(view);
     }
 
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     private void updateScrollPositionOnExpandInBottom(ExpandableView view) {
         if (view instanceof ExpandableNotificationRow && !onKeyguard()) {
             ExpandableNotificationRow row = (ExpandableNotificationRow) view;
@@ -3940,15 +4151,18 @@
         }
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void setOnHeightChangedListener(
             ExpandableView.OnHeightChangedListener mOnHeightChangedListener) {
         this.mOnHeightChangedListener = mOnHeightChangedListener;
     }
 
+    @ShadeViewRefactor(RefactorComponent.INPUT)
     public void setOnEmptySpaceClickListener(OnEmptySpaceClickListener listener) {
         mOnEmptySpaceClickListener = listener;
     }
 
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     public void onChildAnimationFinished() {
         setAnimationRunning(false);
         requestChildrenUpdate();
@@ -3957,6 +4171,7 @@
         clearHeadsUpDisappearRunning();
     }
 
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     private void clearHeadsUpDisappearRunning() {
         for (int i = 0; i < getChildCount(); i++) {
             View view = getChildAt(i);
@@ -3972,6 +4187,7 @@
         }
     }
 
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     private void clearTransient() {
         for (ExpandableView view : mClearTransientViewsWhenFinished) {
             StackStateAnimator.removeTransientView(view);
@@ -3979,6 +4195,7 @@
         mClearTransientViewsWhenFinished.clear();
     }
 
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     private void runAnimationFinishedRunnables() {
         for (Runnable runnable : mAnimationFinishedRunnables) {
             runnable.run();
@@ -3989,6 +4206,7 @@
     /**
      * See {@link AmbientState#setDimmed}.
      */
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void setDimmed(boolean dimmed, boolean animate) {
         dimmed &= onKeyguard();
         mAmbientState.setDimmed(dimmed);
@@ -4003,15 +4221,18 @@
     }
 
     @VisibleForTesting
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     boolean isDimmed() {
         return mAmbientState.isDimmed();
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     private void setDimAmount(float dimAmount) {
         mDimAmount = dimAmount;
         updateBackgroundDimming();
     }
 
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     private void animateDimmed(boolean dimmed) {
         if (mDimAnimator != null) {
             mDimAnimator.cancel();
@@ -4027,8 +4248,8 @@
         mDimAnimator.addUpdateListener(mDimUpdateListener);
         mDimAnimator.start();
     }
-
-    private void setHideSensitive(boolean hideSensitive, boolean animate) {
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
+    public void setHideSensitive(boolean hideSensitive, boolean animate) {
         if (hideSensitive != mAmbientState.isHideSensitive()) {
             int childCount = getChildCount();
             for (int i = 0; i < childCount; i++) {
@@ -4048,6 +4269,7 @@
     /**
      * See {@link AmbientState#setActivatedChild}.
      */
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void setActivatedChild(ActivatableNotificationView activatedChild) {
         mAmbientState.setActivatedChild(activatedChild);
         if (mAnimationsEnabled) {
@@ -4057,10 +4279,12 @@
         requestChildrenUpdate();
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public ActivatableNotificationView getActivatedChild() {
         return mAmbientState.getActivatedChild();
     }
 
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     private void applyCurrentState() {
         mCurrentStackScrollState.apply();
         if (mListener != null) {
@@ -4073,6 +4297,7 @@
         updateClippingToTopRoundedCorner();
     }
 
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     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
@@ -4115,6 +4340,7 @@
      *
      * @param lightTheme True if light theme should be used.
      */
+    @ShadeViewRefactor(RefactorComponent.DECORATOR)
     public void updateDecorViews(boolean lightTheme) {
         if (lightTheme == mUsingLightTheme) {
             return;
@@ -4127,6 +4353,7 @@
         mEmptyShadeView.setTextColor(textColor);
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void goToFullShade(long delay) {
         mGoToFullShadeNeedsAnimation = true;
         mGoToFullShadeDelay = delay;
@@ -4134,15 +4361,18 @@
         requestChildrenUpdate();
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void cancelExpandHelper() {
         mExpandHelper.cancel();
     }
 
+    @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     public void setIntrinsicPadding(int intrinsicPadding) {
         mIntrinsicPadding = intrinsicPadding;
         mAmbientState.setIntrinsicPadding(intrinsicPadding);
     }
 
+    @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     public int getIntrinsicPadding() {
         return mIntrinsicPadding;
     }
@@ -4150,11 +4380,13 @@
     /**
      * @return the y position of the first notification
      */
+    @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     public float getNotificationsTopY() {
         return mTopPadding + getStackTranslation();
     }
 
     @Override
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public boolean shouldDelayChildPressedState() {
         return true;
     }
@@ -4162,6 +4394,7 @@
     /**
      * See {@link AmbientState#setDark}.
      */
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void setDark(boolean dark, boolean animate, @Nullable PointF touchWakeUpScreenLocation) {
         if (mAmbientState.isDark() == dark) {
             return;
@@ -4176,15 +4409,16 @@
             updateBackground();
         }
         requestChildrenUpdate();
-        applyCurrentBackgroundBounds();
         updateWillNotDraw();
         notifyHeightChangeListener(mShelf);
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     private void updatePanelTranslation() {
         setTranslationX(mVerticalPanelTranslation + mAntiBurnInOffsetX * mInterpolatedDarkAmount);
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void setVerticalPanelTranslation(float verticalPanelTranslation) {
         mVerticalPanelTranslation = verticalPanelTranslation;
         updatePanelTranslation();
@@ -4195,11 +4429,13 @@
      * not {@link #onDraw(Canvas)} is called). This method should be called whenever the
      * {@link #mAmbientState}'s dark mode is toggled.
      */
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     private void updateWillNotDraw() {
         boolean willDraw = mShouldDrawNotificationBackground || DEBUG;
         setWillNotDraw(!willDraw);
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     private void setDarkAmount(float darkAmount) {
         setDarkAmount(darkAmount, darkAmount);
     }
@@ -4213,6 +4449,7 @@
      * @param interpolatedDarkAmount The dark amount that follows the actual interpolation of the
      *                               animation curve.
      */
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void setDarkAmount(float linearDarkAmount, float interpolatedDarkAmount) {
         mLinearDarkAmount = linearDarkAmount;
         mInterpolatedDarkAmount = interpolatedDarkAmount;
@@ -4235,6 +4472,7 @@
         requestChildrenUpdate();
     }
 
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     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.
@@ -4246,6 +4484,7 @@
         }
     }
 
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     public long getDarkAnimationDuration(boolean dark) {
         long duration = StackStateAnimator.ANIMATION_DURATION_WAKEUP;
         // Longer animation when sleeping with more than 1 notification
@@ -4255,6 +4494,7 @@
         return duration;
     }
 
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     private int findDarkAnimationOriginIndex(@Nullable PointF screenLocation) {
         if (screenLocation == null || screenLocation.y < mTopPadding) {
             return AnimationEvent.DARK_ANIMATION_ORIGIN_INDEX_ABOVE;
@@ -4270,6 +4510,7 @@
         }
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     private int getNotGoneIndex(View child) {
         int count = getChildCount();
         int notGoneIndex = 0;
@@ -4285,6 +4526,7 @@
         return -1;
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void setFooterView(@NonNull FooterView footerView) {
         int index = -1;
         if (mFooterView != null) {
@@ -4295,6 +4537,7 @@
         addView(mFooterView, index);
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void setEmptyShadeView(EmptyShadeView emptyShadeView) {
         int index = -1;
         if (mEmptyShadeView != null) {
@@ -4305,6 +4548,7 @@
         addView(mEmptyShadeView, index);
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void updateEmptyShadeView(boolean visible) {
         mEmptyShadeView.setVisible(visible, mIsExpanded && mAnimationsEnabled);
 
@@ -4316,6 +4560,7 @@
         }
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void updateFooterView(boolean visible, boolean showDismissView) {
         if (mFooterView == null) {
             return;
@@ -4325,12 +4570,14 @@
         mFooterView.setSecondaryVisible(showDismissView, animate);
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void setDismissAllInProgress(boolean dismissAllInProgress) {
         mDismissAllInProgress = dismissAllInProgress;
         mAmbientState.setDismissAllInProgress(dismissAllInProgress);
         handleDismissAllClipping();
     }
 
+    @ShadeViewRefactor(RefactorComponent.ADAPTER)
     private void handleDismissAllClipping() {
         final int count = getChildCount();
         boolean previousChildWillBeDismissed = false;
@@ -4348,24 +4595,29 @@
         }
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public boolean isFooterViewNotGone() {
         return mFooterView != null
                 && mFooterView.getVisibility() != View.GONE
                 && !mFooterView.willBeGone();
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public boolean isFooterViewContentVisible() {
         return mFooterView != null && mFooterView.isContentVisible();
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public int getFooterViewHeight() {
         return mFooterView == null ? 0 : mFooterView.getHeight() + mPaddingBetweenElements;
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public int getEmptyShadeViewHeight() {
         return mEmptyShadeView.getHeight();
     }
 
+    @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     public float getBottomMostNotificationBottom() {
         final int count = getChildCount();
         float max = 0;
@@ -4383,15 +4635,18 @@
         return max + getStackTranslation();
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void setStatusBar(StatusBar statusBar) {
         this.mStatusBar = statusBar;
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void setGroupManager(NotificationGroupManager groupManager) {
         this.mGroupManager = groupManager;
         mGroupManager.setOnGroupChangeListener(this);
     }
 
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     private void requestAnimateEverything() {
         if (mIsExpanded && mAnimationsEnabled) {
             mEverythingNeedsAnimation = true;
@@ -4400,6 +4655,7 @@
         }
     }
 
+    @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     public boolean isBelowLastNotification(float touchX, float touchY) {
         int childCount = getChildCount();
         for (int i = childCount - 1; i >= 0; i--) {
@@ -4431,6 +4687,7 @@
     }
 
     @Override
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void onGroupExpansionChanged(ExpandableNotificationRow changedRow, boolean expanded) {
         boolean animated = !mGroupExpandedForMeasure && mAnimationsEnabled
                 && (mIsExpanded || changedRow.isPinned());
@@ -4451,12 +4708,14 @@
     }
 
     @Override
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void onGroupCreatedFromChildren(NotificationGroupManager.NotificationGroup group) {
         mStatusBar.requestNotificationUpdate();
     }
 
     /** @hide */
     @Override
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
         super.onInitializeAccessibilityEventInternal(event);
         event.setScrollable(mScrollable);
@@ -4467,6 +4726,7 @@
     }
 
     @Override
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
         super.onInitializeAccessibilityNodeInfoInternal(info);
         if (mScrollable) {
@@ -4487,6 +4747,7 @@
 
     /** @hide */
     @Override
+    @ShadeViewRefactor(RefactorComponent.INPUT)
     public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
         if (super.performAccessibilityActionInternal(action, arguments)) {
             return true;
@@ -4519,10 +4780,12 @@
     }
 
     @Override
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void onGroupsChanged() {
         mStatusBar.requestNotificationUpdate();
     }
 
+    @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     public void generateChildOrderChangedEvent() {
         if (mIsExpanded && mAnimationsEnabled) {
             mGenerateChildOrderChangedEvent = true;
@@ -4532,29 +4795,35 @@
     }
 
     @Override
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public int getContainerChildCount() {
         return getChildCount();
     }
 
     @Override
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public View getContainerChildAt(int i) {
         return getChildAt(i);
     }
 
     @Override
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void removeContainerView(View v) {
         removeView(v);
     }
 
     @Override
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void addContainerView(View v) {
         addView(v);
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void runAfterAnimationFinished(Runnable runnable) {
         mAnimationFinishedRunnables.add(runnable);
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void setHeadsUpManager(HeadsUpManagerPhone headsUpManager) {
         mHeadsUpManager = headsUpManager;
         mAmbientState.setHeadsUpManager(headsUpManager);
@@ -4562,6 +4831,7 @@
         mHeadsUpManager.setAnimationStateHandler(this);
     }
 
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     public void generateHeadsUpAnimation(ExpandableNotificationRow row, boolean isHeadsUp) {
         if (mAnimationsEnabled && (isHeadsUp || mHeadsUpGoingAwayAnimationsAllowed)) {
             mHeadsUpChangeAnimations.add(new Pair<>(row, isHeadsUp));
@@ -4573,6 +4843,7 @@
         }
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void setShadeExpanded(boolean shadeExpanded) {
         mAmbientState.setShadeExpanded(shadeExpanded);
         mStateAnimator.setShadeExpanded(shadeExpanded);
@@ -4585,31 +4856,37 @@
      * @param height          the height of the screen
      * @param bottomBarHeight the height of the bar on the bottom
      */
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void setHeadsUpBoundaries(int height, int bottomBarHeight) {
         mAmbientState.setMaxHeadsUpTranslation(height - bottomBarHeight);
         mStateAnimator.setHeadsUpAppearHeightBottom(height);
         requestChildrenUpdate();
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void setTrackingHeadsUp(ExpandableNotificationRow row) {
         mTrackingHeadsUp = row != null;
         mRoundnessManager.setTrackingHeadsUp(row);
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void setScrimController(ScrimController scrimController) {
         mScrimController = scrimController;
         mScrimController.setScrimBehindChangeRunnable(this::updateBackgroundDimming);
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void forceNoOverlappingRendering(boolean force) {
         mForceNoOverlappingRendering = force;
     }
 
     @Override
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public boolean hasOverlappingRendering() {
         return !mForceNoOverlappingRendering && super.hasOverlappingRendering();
     }
 
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     public void setAnimationRunning(boolean animationRunning) {
         if (animationRunning != mAnimationRunning) {
             if (animationRunning) {
@@ -4622,10 +4899,12 @@
         }
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public boolean isExpanded() {
         return mIsExpanded;
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void setPulsing(boolean pulsing, boolean animated) {
         if (!mPulsing && !pulsing) {
             return;
@@ -4641,6 +4920,7 @@
         mNeedsAnimation |= animated;
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     private void generatePulsingAnimationEvent() {
         if (mNeedingPulseAnimation != null) {
             int type = mPulsing ? AnimationEvent.ANIMATION_TYPE_PULSE_APPEAR
@@ -4650,45 +4930,19 @@
         }
     }
 
-    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);
-    }
-
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void setQsExpanded(boolean qsExpanded) {
         mQsExpanded = qsExpanded;
         updateAlgorithmLayoutMinHeight();
         updateScrollability();
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void setQsExpansionFraction(float qsExpansionFraction) {
         mQsExpansionFraction = qsExpansionFraction;
     }
 
+    @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     public void setOwnScrollY(int ownScrollY) {
         if (ownScrollY != mOwnScrollY) {
             // We still want to call the normal scrolled changed for accessibility reasons
@@ -4699,6 +4953,7 @@
         }
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void setShelf(NotificationShelf shelf) {
         int index = -1;
         if (mShelf != null) {
@@ -4712,10 +4967,12 @@
         shelf.bind(mAmbientState, this);
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public NotificationShelf getNotificationShelf() {
         return mShelf;
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void setMaxDisplayedNotifications(int maxDisplayedNotifications) {
         if (mMaxDisplayedNotifications != maxDisplayedNotifications) {
             mMaxDisplayedNotifications = maxDisplayedNotifications;
@@ -4724,25 +4981,30 @@
         }
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void setShouldShowShelfOnly(boolean shouldShowShelfOnly) {
         mShouldShowShelfOnly = shouldShowShelfOnly;
         updateAlgorithmLayoutMinHeight();
     }
 
+    @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     public int getMinExpansionHeight() {
         return mShelf.getIntrinsicHeight() - (mShelf.getIntrinsicHeight() - mStatusBarHeight) / 2;
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void setInHeadsUpPinnedMode(boolean inHeadsUpPinnedMode) {
         mInHeadsUpPinnedMode = inHeadsUpPinnedMode;
         updateClipping();
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void setHeadsUpAnimatingAway(boolean headsUpAnimatingAway) {
         mHeadsUpAnimatingAway = headsUpAnimatingAway;
         updateClipping();
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     private void setStatusBarState(int statusBarState) {
         mStatusBarState = statusBarState;
         mAmbientState.setStatusBarState(statusBarState);
@@ -4766,10 +5028,12 @@
         onUpdateRowStates();
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void setExpandingVelocity(float expandingVelocity) {
         mAmbientState.setExpandingVelocity(expandingVelocity);
     }
 
+    @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     public float getOpeningHeight() {
         if (mEmptyShadeView.getVisibility() == GONE) {
             return getMinExpansionHeight();
@@ -4778,29 +5042,34 @@
         }
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void setIsFullWidth(boolean isFullWidth) {
         mAmbientState.setPanelFullWidth(isFullWidth);
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void setUnlockHintRunning(boolean running) {
         mAmbientState.setUnlockHintRunning(running);
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void setQsCustomizerShowing(boolean isShowing) {
         mAmbientState.setQsCustomizerShowing(isShowing);
         requestChildrenUpdate();
     }
 
-    @Override
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void setHeadsUpGoingAwayAnimationsAllowed(boolean headsUpGoingAwayAnimationsAllowed) {
         mHeadsUpGoingAwayAnimationsAllowed = headsUpGoingAwayAnimationsAllowed;
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void setAntiBurnInOffsetX(int antiBurnInOffsetX) {
         mAntiBurnInOffsetX = antiBurnInOffsetX;
         updatePanelTranslation();
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     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"
@@ -4818,6 +5087,7 @@
                 mQsExpansionFraction));
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public boolean isFullyDark() {
         return mAmbientState.isFullyDark();
     }
@@ -4828,6 +5098,7 @@
      *
      * @param listener the listener to notify.
      */
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void addOnExpandedHeightListener(BiConsumer<Float, Float> listener) {
         mExpandedHeightListeners.add(listener);
     }
@@ -4835,24 +5106,29 @@
     /**
      * Stop a listener from listening to the expandedHeight.
      */
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void removeOnExpandedHeightListener(BiConsumer<Float, Float> listener) {
         mExpandedHeightListeners.remove(listener);
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void setHeadsUpAppearanceController(
             HeadsUpAppearanceController headsUpAppearanceController) {
         mHeadsUpAppearanceController = headsUpAppearanceController;
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void setIconAreaController(NotificationIconAreaController controller) {
         mIconAreaController = controller;
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     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);
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void clearAllNotifications() {
         // animate-swipe all dismissable notifications, then animate the shade closed
         int numChildren = getChildCount();
@@ -4915,6 +5191,7 @@
         performDismissAllAnimations(viewsToHide);
     }
 
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void performDismissAllAnimations(ArrayList<View> hideAnimatedList) {
         Runnable animationFinishAction = () -> {
             mStatusBar.animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE);
@@ -4947,6 +5224,7 @@
     }
 
     @VisibleForTesting
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     protected void inflateFooterView() {
         FooterView footerView = (FooterView) LayoutInflater.from(mContext).inflate(
                 R.layout.status_bar_notification_footer, this, false);
@@ -4958,7 +5236,8 @@
         setFooterView(footerView);
     }
 
-    private void inflateEmptyShadeView() {
+  @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
+  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);
@@ -4968,6 +5247,7 @@
     /**
      * Updates expanded, dimmed and locked states of notification rows.
      */
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     public void onUpdateRowStates() {
         changeViewPosition(mFooterView, -1);
 
@@ -4988,13 +5268,15 @@
         mScrimController.setNotificationCount(getNotGoneChildCount());
     }
 
-    public void setNotificationPanel(NotificationPanelView notificationPanelView) {
+  @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
+  public void setNotificationPanel(NotificationPanelView notificationPanelView) {
         mNotificationPanel = notificationPanelView;
     }
 
     /**
      * A listener that is notified when the empty space below the notifications is clicked on
      */
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public interface OnEmptySpaceClickListener {
         void onEmptySpaceClicked(float x, float y);
     }
@@ -5002,6 +5284,7 @@
     /**
      * A listener that gets notified when the overscroll at the top has changed.
      */
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public interface OnOverscrollTopChangedListener {
 
         /**
@@ -5025,7 +5308,8 @@
         void flingTopOverscroll(float velocity, boolean open);
     }
 
-    private class NotificationSwipeHelper extends SwipeHelper
+  @ShadeViewRefactor(RefactorComponent.INPUT)
+  private class NotificationSwipeHelper extends SwipeHelper
             implements NotificationSwipeActionHelper {
         private static final long COVER_MENU_DELAY = 4000;
         private Runnable mFalsingCheck;
@@ -5221,7 +5505,8 @@
         }
     }
 
-    public boolean hasActiveNotifications() {
+  @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
+  public boolean hasActiveNotifications() {
         return !mEntryManager.getNotificationData().getActiveNotifications().isEmpty();
     }
 
@@ -5230,6 +5515,7 @@
 
     /* Only ever called as a consequence of a lockscreen expansion gesture. */
     @Override
+    @ShadeViewRefactor(RefactorComponent.INPUT)
     public boolean onDraggedDown(View startingChild, int dragLengthY) {
         if (mStatusBarState == StatusBarState.KEYGUARD
                 && hasActiveNotifications() && (!mStatusBar.isDozing() || mStatusBar.isPulsing())) {
@@ -5252,6 +5538,7 @@
     }
 
     @Override
+    @ShadeViewRefactor(RefactorComponent.INPUT)
     public void onDragDownReset() {
         setDimmed(true /* dimmed */, true /* animated */);
         resetScrollPosition();
@@ -5259,27 +5546,32 @@
     }
 
     @Override
+    @ShadeViewRefactor(RefactorComponent.INPUT)
     public void onCrossedThreshold(boolean above) {
         setDimmed(!above /* dimmed */, true /* animate */);
     }
 
     @Override
+    @ShadeViewRefactor(RefactorComponent.INPUT)
     public void onTouchSlopExceeded() {
         cancelLongPress();
         checkSnoozeLeavebehind();
     }
 
     @Override
+    @ShadeViewRefactor(RefactorComponent.INPUT)
     public void setEmptyDragAmount(float amount) {
         mNotificationPanel.setEmptyDragAmount(amount);
     }
 
     @Override
+    @ShadeViewRefactor(RefactorComponent.INPUT)
     public boolean isFalsingCheckNeeded() {
         return mStatusBarState == StatusBarState.KEYGUARD;
     }
 
-    public void updateSpeedBumpIndex() {
+  @ShadeViewRefactor(RefactorComponent.INPUT)
+  public void updateSpeedBumpIndex() {
         int speedBumpIndex = 0;
         int currentIndex = 0;
         final int N = getChildCount();
@@ -5299,6 +5591,7 @@
         updateSpeedBumpIndex(speedBumpIndex, noAmbient);
     }
 
+    @ShadeViewRefactor(RefactorComponent.INPUT)
     private boolean isTouchInView(MotionEvent ev, View view) {
         if (view == null) {
             return false;
@@ -5316,6 +5609,7 @@
         return ret;
     }
 
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     private void updateContinuousShadowDrawing() {
         boolean continuousShadowUpdate = mAnimationRunning
                 || !mAmbientState.getDraggedViews().isEmpty();
@@ -5330,15 +5624,19 @@
     }
 
     @Override
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void resetExposedMenuView(boolean animate, boolean force) {
         mSwipeHelper.resetExposedMenuView(animate, force);
     }
 
+
+    @ShadeViewRefactor(RefactorComponent.INPUT)
     public void closeControlsIfOutsideTouch(MotionEvent ev) {
         mSwipeHelper.closeControlsIfOutsideTouch(ev);
     }
 
-    static class AnimationEvent {
+  @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
+  static class AnimationEvent {
 
         static AnimationFilter[] FILTERS = new AnimationFilter[]{
 
@@ -5638,7 +5936,8 @@
         }
     }
 
-    private final StateListener mStateListener = new StateListener() {
+  @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
+  private final StateListener mStateListener = new StateListener() {
         @Override
         public void onStatePreChange(int oldState, int newState) {
             if (oldState == StatusBarState.SHADE_LOCKED && newState == StatusBarState.KEYGUARD) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
index afd64f3..0d3ba77 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
@@ -45,7 +45,7 @@
         public void onDisplayBlanked() {
             if (DEBUG) {
                 Log.d(TAG, "Pulse in, mDozing=" + mDozing + " mPulseReason="
-                        + DozeLog.pulseReasonToString(mPulseReason));
+                        + DozeLog.reasonToString(mPulseReason));
             }
             if (!mDozing) {
                 return;
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 6150c2f..4a05989 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
@@ -258,18 +258,6 @@
         return mTrackingHeadsUp;
     }
 
-    /**
-     * 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
-     */
-    @Override
-    public boolean removeNotification(@NonNull String key, boolean releaseImmediately) {
-        return super.removeNotification(key, canRemoveImmediately(key)
-                || releaseImmediately);
-    }
-
     @Override
     public void snooze() {
         super.snooze();
@@ -405,7 +393,8 @@
         return (HeadsUpEntryPhone) getTopHeadsUpEntry();
     }
 
-    private boolean canRemoveImmediately(@NonNull String key) {
+    @Override
+    protected boolean canRemoveImmediately(@NonNull String key) {
         if (mSwipedOutKeys.contains(key)) {
             // We always instantly dismiss views being manually swiped out.
             mSwipedOutKeys.remove(key);
@@ -414,7 +403,8 @@
 
         HeadsUpEntryPhone headsUpEntry = getHeadsUpEntryPhone(key);
         HeadsUpEntryPhone topEntry = getTopHeadsUpEntryPhone();
-        return headsUpEntry != topEntry || headsUpEntry.wasShownLongEnough();
+
+        return headsUpEntry == null || headsUpEntry != topEntry || super.canRemoveImmediately(key);
     }
 
     /**
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 5fe362f..6b6566c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
@@ -415,10 +415,10 @@
             return false;
         }
         NotificationGroup group = mGroupMap.get(getGroupKey(sbn));
-        if (group == null) {
+        if (group == null || group.summary == null) {
             return false;
         }
-        return !group.children.isEmpty();
+        return !group.children.isEmpty() && Objects.equals(group.summary.notification, sbn);
     }
 
     /**
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 33ddfde..e5e5d40 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -2668,32 +2668,6 @@
         setLaunchingAffordance(false);
     }
 
-    @Override
-    public void setAlpha(float alpha) {
-        super.setAlpha(alpha);
-        updateFullyVisibleState(false /* forceNotFullyVisible */);
-    }
-
-    /**
-     * Must be called before starting a ViewPropertyAnimator alpha animation because those
-     * do NOT call setAlpha and therefore don't properly update the fullyVisibleState.
-     */
-    public void notifyStartFading() {
-        updateFullyVisibleState(true /* forceNotFullyVisible */);
-    }
-
-    @Override
-    public void setVisibility(int visibility) {
-        super.setVisibility(visibility);
-        updateFullyVisibleState(false /* forceNotFullyVisible */);
-    }
-
-    private void updateFullyVisibleState(boolean forceNotFullyVisible) {
-        mNotificationStackScroller.setParentNotFullyVisible(forceNotFullyVisible
-                || getAlpha() != 1.0f
-                || getVisibility() != VISIBLE);
-    }
-
     /**
      * Set whether we are currently launching an affordance. This is currently only set when
      * launched via a camera gesture.
@@ -2992,10 +2966,6 @@
         mNotificationStackScroller.setActivatedChild(o);
     }
 
-    public void setParentNotFullyVisible(boolean parent) {
-        mNotificationStackScroller.setParentNotFullyVisible(parent);
-    }
-
     public void runAfterAnimationFinished(Runnable r) {
         mNotificationStackScroller.runAfterAnimationFinished(r);
     }
@@ -3020,8 +2990,4 @@
         mNotificationStackScroller.setScrimController(scrimController);
         updateShowEmptyShadeView();
     }
-
-    public void setDrawBackgroundAsSrc(boolean asSrc) {
-        mNotificationStackScroller.setDrawBackgroundAsSrc(asSrc);
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index 57e01e7..a900c14 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -596,9 +596,10 @@
                 mContext.getString(R.string.instant_apps));
         mCurrentNotifs.add(new Pair<>(pkg, userId));
         String message = mContext.getString(R.string.instant_apps_message);
-        PendingIntent appInfoAction = PendingIntent.getActivity(mContext, 0,
+        UserHandle user = UserHandle.of(userId);
+        PendingIntent appInfoAction = PendingIntent.getActivityAsUser(mContext, 0,
                 new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
-                        .setData(Uri.fromParts("package", pkg, null)), 0);
+                        .setData(Uri.fromParts("package", pkg, null)), 0, null, user);
         Action action = new Notification.Action.Builder(null, mContext.getString(R.string.app_info),
                 appInfoAction).build();
 
@@ -611,8 +612,8 @@
                     .addFlags(Intent.FLAG_IGNORE_EPHEMERAL)
                     .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
 
-            PendingIntent pendingIntent = PendingIntent.getActivity(mContext,
-                    0 /* requestCode */, browserIntent, 0 /* flags */);
+            PendingIntent pendingIntent = PendingIntent.getActivityAsUser(mContext,
+                    0 /* requestCode */, browserIntent, 0 /* flags */, null, user);
             ComponentName aiaComponent = null;
             try {
                 aiaComponent = AppGlobals.getPackageManager().getInstantAppInstallerComponent();
@@ -629,7 +630,8 @@
                     .putExtra(Intent.EXTRA_LONG_VERSION_CODE, appInfo.versionCode)
                     .putExtra(Intent.EXTRA_INSTANT_APP_FAILURE, pendingIntent);
 
-            PendingIntent webPendingIntent = PendingIntent.getActivity(mContext, 0, goToWebIntent, 0);
+            PendingIntent webPendingIntent = PendingIntent.getActivityAsUser(mContext, 0,
+                    goToWebIntent, 0, null, user);
             Action webAction = new Notification.Action.Builder(null, mContext.getString(R.string.go_to_web),
                     webPendingIntent).build();
             builder.addAction(webAction);
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 0c361ce..e3a7b75 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -685,10 +685,6 @@
         return scrim.getTag(TAG_KEY_ANIM) != null;
     }
 
-    public void setDrawBehindAsSrc(boolean asSrc) {
-        mScrimBehind.setDrawAsSrc(asSrc);
-    }
-
     @VisibleForTesting
     void setOnAnimationFinished(Runnable onAnimationFinished) {
         mOnAnimationFinished = onAnimationFinished;
@@ -800,10 +796,6 @@
         return Handler.getMain();
     }
 
-    public void setExcludedBackgroundArea(Rect area) {
-        mScrimBehind.setExcludedArea(area);
-    }
-
     public int getBackgroundColor() {
         int color = mLockColors.getMainColor();
         return Color.argb((int) (mScrimBehind.getViewAlpha() * Color.alpha(color)),
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 6d742cd..7316c02dd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -328,14 +328,6 @@
     /** If true, the lockscreen will show a distinct wallpaper */
     private static final boolean ENABLE_LOCKSCREEN_WALLPAPER = 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
-     * if mScrimSrcModeEnabled. Note that 0.001 is rounded down to 0 in
-     * libhwui.
-     */
-    private static final float SRC_MIN_ALPHA = 0.002f;
-
     static {
         boolean onlyCoreApps;
         try {
@@ -485,7 +477,6 @@
 
     protected boolean mDozing;
     private boolean mDozingRequested;
-    protected boolean mScrimSrcModeEnabled;
 
     protected BackDropView mBackdrop;
     protected ImageView mBackdropFront, mBackdropBack;
@@ -652,7 +643,6 @@
         mVibrateOnOpening = mContext.getResources().getBoolean(
                 R.bool.config_vibrateOnIconAnimation);
         mVibratorHelper = Dependency.get(VibratorHelper.class);
-        mScrimSrcModeEnabled = res.getBoolean(R.bool.config_status_bar_scrim_behind_use_src);
 
         DateTimeView.setReceiverHandler(Dependency.get(Dependency.TIME_TICK_HANDLER));
         putComponent(StatusBar.class, this);
@@ -742,10 +732,12 @@
 
         IVrManager vrManager = IVrManager.Stub.asInterface(ServiceManager.getService(
                 Context.VR_SERVICE));
-        try {
-            vrManager.registerListener(mVrStateCallbacks);
-        } catch (RemoteException e) {
-            Slog.e(TAG, "Failed to register VR mode state listener: " + e);
+        if (vrManager != null) {
+            try {
+                vrManager.registerListener(mVrStateCallbacks);
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Failed to register VR mode state listener: " + e);
+            }
         }
 
         IWallpaperManager wallpaperManager = IWallpaperManager.Stub.asInterface(
@@ -800,7 +792,7 @@
                 this,
                 mNotificationPanel,
                 notifListContainer);
-        mGutsManager.setUpWithPresenter(this, mEntryManager, notifListContainer, mCheckSaveListener,
+        mGutsManager.setUpWithPresenter(this, notifListContainer, mCheckSaveListener,
                 key -> {
                     try {
                         mBarService.onNotificationSettingsViewed(key);
@@ -948,15 +940,6 @@
                     }
                 }, DozeParameters.getInstance(mContext),
                 mContext.getSystemService(AlarmManager.class));
-        if (mScrimSrcModeEnabled) {
-            Runnable runnable = () -> {
-                boolean asSrc = mBackdrop.getVisibility() != View.VISIBLE;
-                mScrimController.setDrawBehindAsSrc(asSrc);
-                mNotificationPanel.setDrawBackgroundAsSrc(asSrc);
-            };
-            mBackdrop.setOnVisibilityChangedRunnable(runnable);
-            runnable.run();
-        }
         mNotificationPanel.initDependencies(this, mGroupManager, mNotificationShelf,
                 mHeadsUpManager, mNotificationIconAreaController, mScrimController);
         mDozeScrimController = new DozeScrimController(mScrimController, context,
@@ -1483,7 +1466,7 @@
             if (mBackdrop.getVisibility() != View.VISIBLE) {
                 mBackdrop.setVisibility(View.VISIBLE);
                 if (allowEnterAnimation) {
-                    mBackdrop.setAlpha(SRC_MIN_ALPHA);
+                    mBackdrop.setAlpha(0);
                     mBackdrop.animate().alpha(1f);
                 } else {
                     mBackdrop.animate().cancel();
@@ -1501,9 +1484,6 @@
                             mBackdropBack.getDrawable().getConstantState()
                                     .newDrawable(mBackdropFront.getResources()).mutate();
                     mBackdropFront.setImageDrawable(drawable);
-                    if (mScrimSrcModeEnabled) {
-                        mBackdropFront.getDrawable().mutate().setXfermode(mSrcOverXferMode);
-                    }
                     mBackdropFront.setAlpha(1f);
                     mBackdropFront.setVisibility(View.VISIBLE);
                 } else {
@@ -1518,9 +1498,6 @@
                 } else {
                     mBackdropBack.setImageDrawable(artworkDrawable);
                 }
-                if (mScrimSrcModeEnabled) {
-                    mBackdropBack.getDrawable().mutate().setXfermode(mSrcXferMode);
-                }
 
                 if (mBackdropFront.getVisibility() == View.VISIBLE) {
                     if (DEBUG_MEDIA) {
@@ -1553,7 +1530,7 @@
                 } else {
                     mStatusBarWindowController.setBackdropShowing(false);
                     mBackdrop.animate()
-                            .alpha(SRC_MIN_ALPHA)
+                            .alpha(0)
                             .setInterpolator(Interpolators.ACCELERATE_DECELERATE)
                             .setDuration(300)
                             .setStartDelay(0)
@@ -1765,10 +1742,6 @@
         return mMediaManager.getMediaNotificationKey();
     }
 
-    public boolean isScrimSrcModeEnabled() {
-        return mScrimSrcModeEnabled;
-    }
-
     /**
      * To be called when there's a state change in StatusBarKeyguardViewManager.
      */
@@ -1811,7 +1784,7 @@
                         mStatusBarWindowController.setHeadsUpShowing(false);
                         mHeadsUpManager.setHeadsUpGoingAway(false);
                     }
-                    mRemoteInputManager.removeRemoteInputEntriesKeptUntilCollapsed();
+                    mRemoteInputManager.onPanelCollapsed();
                 });
             }
         }
@@ -1828,7 +1801,7 @@
 
     @Override
     public void onHeadsUpStateChanged(Entry entry, boolean isHeadsUp) {
-        mEntryManager.onHeadsUpStateChanged(entry, isHeadsUp);
+        mEntryManager.updateNotificationRanking(null /* rankingMap */);
 
         if (isHeadsUp) {
             mDozeServiceHost.fireNotificationHeadsUp();
@@ -1858,7 +1831,7 @@
         }
 
         if (!isExpanded) {
-            mRemoteInputManager.removeRemoteInputEntriesKeptUntilCollapsed();
+            mRemoteInputManager.onPanelCollapsed();
         }
     }
 
@@ -3410,7 +3383,6 @@
             updateScrimController();
             updateMediaMetaData(false, true);
             mNotificationPanel.setAlpha(1);
-            mNotificationPanel.setParentNotFullyVisible(true);
             mNotificationPanel.animate()
                     .alpha(0)
                     .setStartDelay(FADE_KEYGUARD_START_DELAY)
@@ -3432,7 +3404,6 @@
      * fading.
      */
     public void fadeKeyguardWhilePulsing() {
-        mNotificationPanel.notifyStartFading();
         mNotificationPanel.animate()
                 .alpha(0f)
                 .setStartDelay(0)
@@ -3751,7 +3722,7 @@
             clearNotificationEffects();
         }
         if (newState == StatusBarState.KEYGUARD) {
-            mRemoteInputManager.removeRemoteInputEntriesKeptUntilCollapsed();
+            mRemoteInputManager.onPanelCollapsed();
             maybeEscalateHeadsUp();
         }
     }
@@ -4380,6 +4351,7 @@
             }
             mEntryManager.updateNotifications();
             updateDozingState();
+            updateScrimController();
             updateReportRejectedTouchVisibility();
         }
         Trace.endSection();
@@ -4515,8 +4487,8 @@
             if (mDozingRequested) {
                 mDozingRequested = false;
                 DozeLog.traceDozing(mContext, mDozing);
-                mWakefulnessLifecycle.dispatchStartedWakingUp();
                 updateDozing();
+                mWakefulnessLifecycle.dispatchStartedWakingUp();
             }
         }
 
@@ -4861,7 +4833,8 @@
                     removeNotification(parentToCancelFinal);
                 }
                 if (shouldAutoCancel(sbn)
-                        || mEntryManager.isNotificationKeptForRemoteInput(notificationKey)) {
+                        || mRemoteInputManager.isNotificationKeptForRemoteInputHistory(
+                                notificationKey)) {
                     // Automatically remove all notifications that we may have kept around longer
                     removeNotification(sbn);
                 }
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 98f1a36..45b32c7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -227,20 +227,7 @@
     @Override
     protected void onAttachedToWindow () {
         super.onAttachedToWindow();
-
-        // We need to ensure that our window doesn't suffer from overdraw which would normally
-        // occur if our window is translucent. Since we are drawing the whole window anyway with
-        // the scrim, we don't need the window to be cleared in the beginning.
-        if (mService.isScrimSrcModeEnabled()) {
-            IBinder windowToken = getWindowToken();
-            WindowManager.LayoutParams lp = (WindowManager.LayoutParams) getLayoutParams();
-            lp.token = windowToken;
-            setLayoutParams(lp);
-            WindowManagerGlobal.getInstance().changeCanvasOpacity(windowToken, true);
-            setWillNotDraw(false);
-        } else {
-            setWillNotDraw(!DEBUG);
-        }
+        setWillNotDraw(!DEBUG);
     }
 
     @Override
@@ -394,26 +381,6 @@
     @Override
     public void onDraw(Canvas canvas) {
         super.onDraw(canvas);
-        if (mService.isScrimSrcModeEnabled()) {
-            // We need to ensure that our window is always drawn fully even when we have paddings,
-            // since we simulate it to be opaque.
-            int paddedBottom = getHeight() - getPaddingBottom();
-            int paddedRight = getWidth() - getPaddingRight();
-            if (getPaddingTop() != 0) {
-                canvas.drawRect(0, 0, getWidth(), getPaddingTop(), mTransparentSrcPaint);
-            }
-            if (getPaddingBottom() != 0) {
-                canvas.drawRect(0, paddedBottom, getWidth(), getHeight(), mTransparentSrcPaint);
-            }
-            if (getPaddingLeft() != 0) {
-                canvas.drawRect(0, getPaddingTop(), getPaddingLeft(), paddedBottom,
-                        mTransparentSrcPaint);
-            }
-            if (getPaddingRight() != 0) {
-                canvas.drawRect(paddedRight, getPaddingTop(), getWidth(), paddedBottom,
-                        mTransparentSrcPaint);
-            }
-        }
         if (DEBUG) {
             Paint pt = new Paint();
             pt.setColor(0x80FFFF00);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
index 3c16329..e9efaa1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
@@ -205,6 +205,8 @@
         public void onTetheringFailed() {
             if (DEBUG) Log.d(TAG, "onTetheringFailed");
             mWaitingForCallback = false;
+            // TODO(b/110697252): stopTethering must be called to reset soft ap state after failure
+            mConnectivityManager.stopTethering(ConnectivityManager.TETHERING_WIFI);
             fireHotspotChangedCallback(isHotspotEnabled());
           // TODO: Show error.
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index dbfbdd7..15b2f2b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -51,6 +51,7 @@
 import com.android.settingslib.RestrictedLockUtilsInternal;
 import com.android.settingslib.Utils;
 import com.android.systemui.Dependency;
+import com.android.systemui.Dumpable;
 import com.android.systemui.GuestResumeSessionReceiver;
 import com.android.systemui.Prefs;
 import com.android.systemui.Prefs.Key;
@@ -70,7 +71,7 @@
 /**
  * Keeps a list of all users on the device for user switching.
  */
-public class UserSwitcherController {
+public class UserSwitcherController implements Dumpable {
 
     private static final String TAG = "UserSwitcherController";
     private static final boolean DEBUG = false;
@@ -549,6 +550,7 @@
         };
     };
 
+    @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         pw.println("UserSwitcherController state:");
         pw.println("  mLastNonGuestUser=" + mLastNonGuestUser);
diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java
index 238407a..a46f018 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java
@@ -16,17 +16,13 @@
 
 package com.android.systemui.usb;
 
-import android.annotation.NonNull;
 import android.app.AlertDialog;
 import android.app.PendingIntent;
 import android.content.Context;
 import android.content.DialogInterface;
 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.res.XmlResourceParser;
 import android.hardware.usb.IUsbManager;
 import android.hardware.usb.UsbAccessory;
 import android.hardware.usb.UsbDevice;
@@ -45,13 +41,8 @@
 
 import com.android.internal.app.AlertActivity;
 import com.android.internal.app.AlertController;
-import com.android.internal.util.XmlUtils;
-import android.hardware.usb.AccessoryFilter;
-import android.hardware.usb.DeviceFilter;
 import com.android.systemui.R;
 
-import org.xmlpull.v1.XmlPullParser;
-
 public class UsbPermissionActivity extends AlertActivity
         implements DialogInterface.OnClickListener, CheckBox.OnCheckedChangeListener {
 
@@ -71,12 +62,13 @@
     public void onCreate(Bundle icicle) {
         super.onCreate(icicle);
 
-       Intent intent = getIntent();
+        Intent intent = getIntent();
         mDevice = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
         mAccessory = (UsbAccessory)intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
         mPendingIntent = (PendingIntent)intent.getParcelableExtra(Intent.EXTRA_INTENT);
         mUid = intent.getIntExtra(Intent.EXTRA_UID, -1);
-        mPackageName = intent.getStringExtra("package");
+        mPackageName = intent.getStringExtra(UsbManager.EXTRA_PACKAGE);
+        boolean canBeDefault = intent.getBooleanExtra(UsbManager.EXTRA_CAN_BE_DEFAULT, false);
 
         PackageManager packageManager = getPackageManager();
         ApplicationInfo aInfo;
@@ -105,121 +97,27 @@
         ap.mPositiveButtonListener = this;
         ap.mNegativeButtonListener = this;
 
-        try {
-            PackageInfo packageInfo = packageManager.getPackageInfo(mPackageName,
-                    PackageManager.GET_ACTIVITIES | PackageManager.GET_META_DATA);
-
-            if ((mDevice != null && canBeDefault(mDevice, packageInfo))
-                    || (mAccessory != null && canBeDefault(mAccessory, packageInfo))) {
-                // add "open when" checkbox
-                LayoutInflater inflater = (LayoutInflater) getSystemService(
-                        Context.LAYOUT_INFLATER_SERVICE);
-                ap.mView = inflater.inflate(com.android.internal.R.layout.always_use_checkbox, null);
-                mAlwaysUse = (CheckBox) ap.mView.findViewById(com.android.internal.R.id.alwaysUse);
-                if (mDevice == null) {
-                    mAlwaysUse.setText(getString(R.string.always_use_accessory, appName,
-                            mAccessory.getDescription()));
-                } else {
-                    mAlwaysUse.setText(getString(R.string.always_use_device, appName,
-                            mDevice.getProductName()));
-                }
-                mAlwaysUse.setOnCheckedChangeListener(this);
-
-                mClearDefaultHint = (TextView)ap.mView.findViewById(
-                        com.android.internal.R.id.clearDefaultHint);
-                mClearDefaultHint.setVisibility(View.GONE);
+        if (canBeDefault && (mDevice != null || mAccessory != null)) {
+            // add "open when" checkbox
+            LayoutInflater inflater = (LayoutInflater) getSystemService(
+                    Context.LAYOUT_INFLATER_SERVICE);
+            ap.mView = inflater.inflate(com.android.internal.R.layout.always_use_checkbox, null);
+            mAlwaysUse = (CheckBox) ap.mView.findViewById(com.android.internal.R.id.alwaysUse);
+            if (mDevice == null) {
+                mAlwaysUse.setText(getString(R.string.always_use_accessory, appName,
+                        mAccessory.getDescription()));
+            } else {
+                mAlwaysUse.setText(getString(R.string.always_use_device, appName,
+                        mDevice.getProductName()));
             }
-        } catch (PackageManager.NameNotFoundException e) {
-            // ignore
+            mAlwaysUse.setOnCheckedChangeListener(this);
+
+            mClearDefaultHint = (TextView)ap.mView.findViewById(
+                    com.android.internal.R.id.clearDefaultHint);
+            mClearDefaultHint.setVisibility(View.GONE);
         }
 
         setupAlert();
-
-    }
-
-    /**
-     * Can the app be the default for the USB device. I.e. can the app be launched by default if
-     * the device is plugged in.
-     *
-     * @param device The device the app would be default for
-     * @param packageInfo The package info of the app
-     *
-     * @return {@code true} iff the app can be default
-     */
-    private boolean canBeDefault(@NonNull UsbDevice device, @NonNull PackageInfo packageInfo) {
-        ActivityInfo[] activities = packageInfo.activities;
-        if (activities != null) {
-            int numActivities = activities.length;
-            for (int i = 0; i < numActivities; i++) {
-                ActivityInfo activityInfo = activities[i];
-
-                try (XmlResourceParser parser = activityInfo.loadXmlMetaData(getPackageManager(),
-                        UsbManager.ACTION_USB_DEVICE_ATTACHED)) {
-                    if (parser == null) {
-                        continue;
-                    }
-
-                    XmlUtils.nextElement(parser);
-                    while (parser.getEventType() != XmlPullParser.END_DOCUMENT) {
-                        if ("usb-device".equals(parser.getName())) {
-                            DeviceFilter filter = DeviceFilter.read(parser);
-                            if (filter.matches(device)) {
-                                return true;
-                            }
-                        }
-
-                        XmlUtils.nextElement(parser);
-                    }
-                } catch (Exception e) {
-                    Log.w(TAG, "Unable to load component info " + activityInfo.toString(), e);
-                }
-            }
-        }
-
-        return false;
-    }
-
-    /**
-     * Can the app be the default for the USB accessory. I.e. can the app be launched by default if
-     * the accessory is plugged in.
-     *
-     * @param accessory The accessory the app would be default for
-     * @param packageInfo The package info of the app
-     *
-     * @return {@code true} iff the app can be default
-     */
-    private boolean canBeDefault(@NonNull UsbAccessory accessory,
-            @NonNull PackageInfo packageInfo) {
-        ActivityInfo[] activities = packageInfo.activities;
-        if (activities != null) {
-            int numActivities = activities.length;
-            for (int i = 0; i < numActivities; i++) {
-                ActivityInfo activityInfo = activities[i];
-
-                try (XmlResourceParser parser = activityInfo.loadXmlMetaData(getPackageManager(),
-                        UsbManager.ACTION_USB_ACCESSORY_ATTACHED)) {
-                    if (parser == null) {
-                        continue;
-                    }
-
-                    XmlUtils.nextElement(parser);
-                    while (parser.getEventType() != XmlPullParser.END_DOCUMENT) {
-                        if ("usb-accessory".equals(parser.getName())) {
-                            AccessoryFilter filter = AccessoryFilter.read(parser);
-                            if (filter.matches(accessory)) {
-                                return true;
-                            }
-                        }
-
-                        XmlUtils.nextElement(parser);
-                    }
-                } catch (Exception e) {
-                    Log.w(TAG, "Unable to load component info " + activityInfo.toString(), e);
-                }
-            }
-        }
-
-        return false;
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/util/AlarmTimeout.java b/packages/SystemUI/src/com/android/systemui/util/AlarmTimeout.java
index f7f61af..a791376 100644
--- a/packages/SystemUI/src/com/android/systemui/util/AlarmTimeout.java
+++ b/packages/SystemUI/src/com/android/systemui/util/AlarmTimeout.java
@@ -44,7 +44,15 @@
         mHandler = handler;
     }
 
-    public void schedule(long timeout, int mode) {
+    /**
+     * Schedules an alarm in {@code timeout} milliseconds in the future.
+     *
+     * @param timeout How long to wait from now.
+     * @param mode {@link #MODE_CRASH_IF_SCHEDULED}, {@link #MODE_IGNORE_IF_SCHEDULED} or
+     *             {@link #MODE_RESCHEDULE_IF_SCHEDULED}.
+     * @return {@code true} when scheduled successfully, {@code false} otherwise.
+     */
+    public boolean schedule(long timeout, int mode) {
         switch (mode) {
             case MODE_CRASH_IF_SCHEDULED:
                 if (mScheduled) {
@@ -53,7 +61,7 @@
                 break;
             case MODE_IGNORE_IF_SCHEDULED:
                 if (mScheduled) {
-                    return;
+                    return false;
                 }
                 break;
             case MODE_RESCHEDULE_IF_SCHEDULED:
@@ -68,6 +76,7 @@
         mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP,
                 SystemClock.elapsedRealtime() + timeout, mTag, this, mHandler);
         mScheduled = true;
+        return true;
     }
 
     public boolean isScheduled() {
diff --git a/packages/SystemUI/src/com/android/systemui/util/EmergencyDialerConstants.java b/packages/SystemUI/src/com/android/systemui/util/EmergencyDialerConstants.java
new file mode 100644
index 0000000..d101ccb
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/util/EmergencyDialerConstants.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.util;
+
+/**
+ * Constants defined and used in emergency dialer.
+ * Please keep these constants being consistent with those in com.android.phone.EmergencyDialer.
+ */
+public class EmergencyDialerConstants {
+    // Intent action for emergency dialer activity.
+    public static final String ACTION_DIAL = "com.android.phone.EmergencyDialer.DIAL";
+
+    /**
+     * Extra included in {@link #ACTION_DIAL} to indicate the entry type that user starts
+     * the emergency dialer.
+     */
+    public static final String EXTRA_ENTRY_TYPE =
+            "com.android.phone.EmergencyDialer.extra.ENTRY_TYPE";
+
+    // Indicating the entrance to emergency dialer
+    public static final int ENTRY_TYPE_UNKNOWN = 0;
+    public static final int ENTRY_TYPE_LOCKSCREEN_BUTTON = 1;
+    public static final int ENTRY_TYPE_POWER_MENU = 2;
+}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java
index 2cbb78a..3744105 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java
@@ -356,10 +356,11 @@
     if (supplementalIconId != 0) {
       Drawable supplementalIcon = mContext.getResources().getDrawable(supplementalIconId);
       supplementalIcon.mutate().setTint(color);
-      listItem.setSupplementalIcon(supplementalIcon, true,
-          supplementalIconOnClickListener);
+      listItem.setSupplementalIcon(supplementalIcon, true);
+      listItem.setSupplementalIconListener(supplementalIconOnClickListener);
     } else {
       listItem.setSupplementalEmptyIcon(true);
+      listItem.setSupplementalIconListener(null);
     }
 
     mVolumeLineItems.add(listItem);
diff --git a/packages/SystemUI/tests/Android.mk b/packages/SystemUI/tests/Android.mk
index 6057614..aac37a2 100644
--- a/packages/SystemUI/tests/Android.mk
+++ b/packages/SystemUI/tests/Android.mk
@@ -38,7 +38,8 @@
     android.test.runner \
     telephony-common \
     android.test.base \
-    android.car
+    android.car \
+    android.car.user
 
 LOCAL_AAPT_FLAGS := --extra-packages com.android.systemui:com.android.keyguard
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ImageWallpaperTest.java b/packages/SystemUI/tests/src/com/android/systemui/ImageWallpaperTest.java
new file mode 100644
index 0000000..521d5d1
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/ImageWallpaperTest.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF 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 static org.junit.Assert.assertNotNull;
+import static org.mockito.Mockito.any;
+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.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.when;
+
+import android.graphics.Bitmap;
+import android.support.test.runner.AndroidJUnit4;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.view.DisplayInfo;
+import android.view.SurfaceHolder;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.concurrent.CountDownLatch;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class ImageWallpaperTest extends SysuiTestCase {
+
+    private static final int BMP_WIDTH = 128;
+    private static final int BMP_HEIGHT = 128;
+
+    private static final int INVALID_BMP_WIDTH = 1;
+    private static final int INVALID_BMP_HEIGHT = 1;
+
+    private ImageWallpaper mImageWallpaper;
+
+    @Mock private SurfaceHolder mSurfaceHolder;
+    @Mock private DisplayInfo mDisplayInfo;
+
+    CountDownLatch mEventCountdown;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+
+        mEventCountdown = new CountDownLatch(1);
+
+        mImageWallpaper = new ImageWallpaper() {
+            @Override
+            public Engine onCreateEngine() {
+                return new DrawableEngine() {
+                    @Override
+                    DisplayInfo getDefaultDisplayInfo() {
+                        return mDisplayInfo;
+                    }
+
+                    @Override
+                    public SurfaceHolder getSurfaceHolder() {
+                        return mSurfaceHolder;
+                    }
+
+                    @Override
+                    public void setFixedSizeAllowed(boolean allowed) {
+                        super.setFixedSizeAllowed(allowed);
+                        assertTrue("mFixedSizeAllowed should be true", allowed);
+                        mEventCountdown.countDown();
+                    }
+                };
+            }
+        };
+    }
+
+    @Test
+    public void testSetValidBitmapWallpaper() {
+        ImageWallpaper.DrawableEngine wallpaperEngine =
+                (ImageWallpaper.DrawableEngine) mImageWallpaper.onCreateEngine();
+
+        assertEquals("setFixedSizeAllowed should have been called.",
+                0, mEventCountdown.getCount());
+
+        Bitmap mockedBitmap = mock(Bitmap.class);
+        when(mockedBitmap.getWidth()).thenReturn(BMP_WIDTH);
+        when(mockedBitmap.getHeight()).thenReturn(BMP_HEIGHT);
+
+        wallpaperEngine.updateBitmap(mockedBitmap);
+
+        assertEquals(BMP_WIDTH, wallpaperEngine.mBackgroundWidth);
+        assertEquals(BMP_HEIGHT, wallpaperEngine.mBackgroundHeight);
+
+        verify(mSurfaceHolder, times(1)).setFixedSize(BMP_WIDTH, BMP_HEIGHT);
+
+    }
+
+    @Test
+    public void testSetTooSmallBitmapWallpaper() {
+        ImageWallpaper.DrawableEngine wallpaperEngine =
+                (ImageWallpaper.DrawableEngine) mImageWallpaper.onCreateEngine();
+
+        assertEquals("setFixedSizeAllowed should have been called.",
+                0, mEventCountdown.getCount());
+
+        Bitmap mockedBitmap = mock(Bitmap.class);
+        when(mockedBitmap.getWidth()).thenReturn(INVALID_BMP_WIDTH);
+        when(mockedBitmap.getHeight()).thenReturn(INVALID_BMP_HEIGHT);
+
+        wallpaperEngine.updateBitmap(mockedBitmap);
+
+        assertEquals(INVALID_BMP_WIDTH, wallpaperEngine.mBackgroundWidth);
+        assertEquals(INVALID_BMP_HEIGHT, wallpaperEngine.mBackgroundHeight);
+
+        verify(mSurfaceHolder, times(1)).setFixedSize(ImageWallpaper.DrawableEngine.MIN_BACKGROUND_WIDTH, ImageWallpaper.DrawableEngine.MIN_BACKGROUND_HEIGHT);
+    }
+
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSIconViewImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSIconViewImplTest.java
index f9f4f497..c5e4043 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSIconViewImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSIconViewImplTest.java
@@ -59,14 +59,14 @@
         // No current icon, only the static drawable should be used.
         s.icon = mock(Icon.class);
         when(iv.getDrawable()).thenReturn(null);
-        mIconView.updateIcon(iv, s);
+        mIconView.updateIcon(iv, s, true);
         verify(s.icon, never()).getDrawable(any());
         verify(s.icon).getInvisibleDrawable(any());
 
         // Has icon, should use the standard (animated) form.
         s.icon = mock(Icon.class);
         when(iv.getDrawable()).thenReturn(mock(Drawable.class));
-        mIconView.updateIcon(iv, s);
+        mIconView.updateIcon(iv, s, true);
         verify(s.icon).getDrawable(any());
         verify(s.icon, never()).getInvisibleDrawable(any());
     }
@@ -79,7 +79,7 @@
         int desiredColor = mIconView.getColor(s.state);
         when(iv.isShown()).thenReturn(true);
 
-        mIconView.setIcon(iv, s);
+        mIconView.setIcon(iv, s, true);
         verify(iv).setImageTintList(argThat(stateList -> stateList.getColors()[0] == desiredColor));
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/AlertingNotificationManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/AlertingNotificationManagerTest.java
index f04a115..f21ce27 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/AlertingNotificationManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/AlertingNotificationManagerTest.java
@@ -34,7 +34,6 @@
 
 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;
 
@@ -91,7 +90,7 @@
         return new TestableAlertingNotificationManager();
     }
 
-    private StatusBarNotification createNewNotification(int id) {
+    protected StatusBarNotification createNewNotification(int id) {
         Notification.Builder n = new Notification.Builder(mContext, "")
                 .setSmallIcon(R.drawable.ic_person)
                 .setContentTitle("Title")
@@ -154,7 +153,7 @@
     public void testRemoveNotification_forceRemove() {
         mAlertingNotificationManager.showNotification(mEntry);
 
-        //Remove forcibly with releaseImmediately = true.
+        // Remove forcibly with releaseImmediately = true.
         mAlertingNotificationManager.removeNotification(mEntry.key, true /* releaseImmediately */);
 
         assertFalse(mAlertingNotificationManager.contains(mEntry.key));
@@ -173,4 +172,30 @@
 
         assertEquals(0, mAlertingNotificationManager.getAllEntries().count());
     }
+
+    @Test
+    public void testShouldExtendLifetime_notShownLongEnough() {
+        mAlertingNotificationManager.showNotification(mEntry);
+
+        // The entry has just been added so the lifetime should be extended
+        assertTrue(mAlertingNotificationManager.shouldExtendLifetime(mEntry));
+    }
+
+    @Test
+    public void testSetShouldManageLifetime_setShouldManage() {
+        mAlertingNotificationManager.showNotification(mEntry);
+
+        mAlertingNotificationManager.setShouldManageLifetime(mEntry, true /* shouldManage */);
+
+        assertTrue(mAlertingNotificationManager.mExtendedLifetimeAlertEntries.contains(mEntry));
+    }
+
+    @Test
+    public void testSetShouldManageLifetime_setShouldNotManage() {
+        mAlertingNotificationManager.mExtendedLifetimeAlertEntries.add(mEntry);
+
+        mAlertingNotificationManager.setShouldManageLifetime(mEntry, false /* shouldManage */);
+
+        assertFalse(mAlertingNotificationManager.mExtendedLifetimeAlertEntries.contains(mEntry));
+    }
 }
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 8129b01..09c1931 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NonPhoneDependencyTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NonPhoneDependencyTest.java
@@ -86,8 +86,8 @@
 
         entryManager.setUpWithPresenter(mPresenter, mListContainer, mEntryManagerCallback,
                 mHeadsUpManager);
-        gutsManager.setUpWithPresenter(mPresenter, entryManager, mListContainer,
-                mCheckSaveListener, mOnClickListener);
+        gutsManager.setUpWithPresenter(mPresenter, mListContainer, mCheckSaveListener,
+                mOnClickListener);
         notificationLogger.setUpWithEntryManager(entryManager, mListContainer);
         mediaManager.setUpWithPresenter(mPresenter, entryManager);
         remoteInputManager.setUpWithPresenter(mPresenter, entryManager, mRemoteInputManagerCallback,
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 3cafaf4..7b0c0a0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationListenerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationListenerTest.java
@@ -85,13 +85,6 @@
     }
 
     @Test
-    public void testPostNotificationRemovesKeyKeptForRemoteInput() {
-        mListener.onNotificationPosted(mSbn, mRanking);
-        TestableLooper.get(this).processAllMessages();
-        verify(mEntryManager).removeKeyKeptForRemoteInput(mSbn.getKey());
-    }
-
-    @Test
     public void testNotificationUpdateCallsUpdateNotification() {
         when(mNotificationData.get(mSbn.getKey())).thenReturn(new NotificationData.Entry(mSbn));
         mListener.onNotificationPosted(mSbn, mRanking);
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 afe2cf6..8a59e96 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java
@@ -1,8 +1,10 @@
 package com.android.systemui.statusbar;
 
-import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertTrue;
+import static junit.framework.Assert.assertFalse;
 
+import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -10,6 +12,7 @@
 import android.content.Context;
 import android.os.Handler;
 import android.os.Looper;
+import android.os.SystemClock;
 import android.os.UserHandle;
 import android.service.notification.NotificationListenerService;
 import android.service.notification.StatusBarNotification;
@@ -22,6 +25,10 @@
 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.NotificationRemoteInputManager.RemoteInputActiveExtender;
+import com.android.systemui.statusbar.NotificationRemoteInputManager.RemoteInputHistoryExtender;
+import com.android.systemui.statusbar.NotificationRemoteInputManager.SmartReplyHistoryExtender;
+
 import com.google.android.collect.Sets;
 
 import org.junit.Before;
@@ -41,6 +48,7 @@
     @Mock private RemoteInputController.Delegate mDelegate;
     @Mock private NotificationRemoteInputManager.Callback mCallback;
     @Mock private RemoteInputController mController;
+    @Mock private SmartReplyController mSmartReplyController;
     @Mock private NotificationListenerService.RankingMap mRanking;
     @Mock private ExpandableNotificationRow mRow;
 
@@ -51,6 +59,9 @@
     private TestableNotificationRemoteInputManager mRemoteInputManager;
     private StatusBarNotification mSbn;
     private NotificationData.Entry mEntry;
+    private RemoteInputHistoryExtender mRemoteInputHistoryExtender;
+    private SmartReplyHistoryExtender mSmartReplyHistoryExtender;
+    private RemoteInputActiveExtender mRemoteInputActiveExtender;
 
     @Before
     public void setUp() {
@@ -58,9 +69,9 @@
         mDependency.injectTestDependency(NotificationEntryManager.class, mEntryManager);
         mDependency.injectTestDependency(NotificationLockscreenUserManager.class,
                 mLockscreenUserManager);
+        mDependency.injectTestDependency(SmartReplyController.class, mSmartReplyController);
 
         when(mPresenter.getHandler()).thenReturn(Handler.createAsync(Looper.myLooper()));
-        when(mEntryManager.getLatestRankingMap()).thenReturn(mRanking);
 
         mRemoteInputManager = new TestableNotificationRemoteInputManager(mContext);
         mSbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME, 0, null, TEST_UID,
@@ -70,20 +81,10 @@
 
         mRemoteInputManager.setUpWithPresenterForTest(mPresenter, mEntryManager, mCallback,
                 mDelegate, mController);
-    }
-
-    @Test
-    public void testOnRemoveNotificationNotKept() {
-        assertFalse(mRemoteInputManager.onRemoveNotification(mEntry));
-        assertTrue(mRemoteInputManager.getRemoteInputEntriesToRemoveOnCollapse().isEmpty());
-    }
-
-    @Test
-    public void testOnRemoveNotificationKept() {
-        when(mController.isRemoteInputActive(mEntry)).thenReturn(true);
-        assertTrue(mRemoteInputManager.onRemoveNotification(mEntry));
-        assertTrue(mRemoteInputManager.getRemoteInputEntriesToRemoveOnCollapse().equals(
-                Sets.newArraySet(mEntry)));
+        for (NotificationLifetimeExtender extender : mRemoteInputManager.getLifetimeExtenders()) {
+            extender.setCallback(
+                    mock(NotificationLifetimeExtender.NotificationSafeToRemoveCallback.class));
+        }
     }
 
     @Test
@@ -95,15 +96,104 @@
     }
 
     @Test
-    public void testRemoveRemoteInputEntriesKeptUntilCollapsed() {
-        mRemoteInputManager.getRemoteInputEntriesToRemoveOnCollapse().add(mEntry);
-        mRemoteInputManager.removeRemoteInputEntriesKeptUntilCollapsed();
+    public void testShouldExtendLifetime_remoteInputActive() {
+        when(mController.isRemoteInputActive(mEntry)).thenReturn(true);
 
-        assertTrue(mRemoteInputManager.getRemoteInputEntriesToRemoveOnCollapse().isEmpty());
-        verify(mController).removeRemoteInput(mEntry, null);
-        verify(mEntryManager).removeNotification(mEntry.key, mRanking);
+        assertTrue(mRemoteInputActiveExtender.shouldExtendLifetime(mEntry));
     }
 
+    @Test
+    public void testShouldExtendLifetime_isSpinning() {
+        NotificationRemoteInputManager.FORCE_REMOTE_INPUT_HISTORY = true;
+        when(mController.isSpinning(mEntry.key)).thenReturn(true);
+
+        assertTrue(mRemoteInputHistoryExtender.shouldExtendLifetime(mEntry));
+    }
+
+    @Test
+    public void testShouldExtendLifetime_recentRemoteInput() {
+        NotificationRemoteInputManager.FORCE_REMOTE_INPUT_HISTORY = true;
+        mEntry.lastRemoteInputSent = SystemClock.elapsedRealtime();
+
+        assertTrue(mRemoteInputHistoryExtender.shouldExtendLifetime(mEntry));
+    }
+
+    @Test
+    public void testShouldExtendLifetime_smartReplySending() {
+        NotificationRemoteInputManager.FORCE_REMOTE_INPUT_HISTORY = true;
+        when(mSmartReplyController.isSendingSmartReply(mEntry.key)).thenReturn(true);
+
+        assertTrue(mSmartReplyHistoryExtender.shouldExtendLifetime(mEntry));
+    }
+
+    @Test
+    public void testNotificationWithRemoteInputActiveIsRemovedOnCollapse() {
+        mRemoteInputActiveExtender.setShouldManageLifetime(mEntry, true /* shouldManage */);
+
+        assertEquals(mRemoteInputManager.getEntriesKeptForRemoteInputActive(),
+                Sets.newArraySet(mEntry));
+
+        mRemoteInputManager.onPanelCollapsed();
+
+        assertTrue(mRemoteInputManager.getEntriesKeptForRemoteInputActive().isEmpty());
+    }
+
+    @Test
+    public void testRebuildWithRemoteInput_noExistingInputNoSpinner() {
+        StatusBarNotification newSbn =
+                mRemoteInputManager.rebuildNotificationWithRemoteInput(mEntry, "A Reply", false);
+        CharSequence[] messages = newSbn.getNotification().extras
+                .getCharSequenceArray(Notification.EXTRA_REMOTE_INPUT_HISTORY);
+        assertEquals(1, messages.length);
+        assertEquals("A Reply", messages[0]);
+        assertFalse(newSbn.getNotification().extras
+                .getBoolean(Notification.EXTRA_SHOW_REMOTE_INPUT_SPINNER, false));
+        assertTrue(newSbn.getNotification().extras
+                .getBoolean(Notification.EXTRA_HIDE_SMART_REPLIES, false));
+    }
+
+    @Test
+    public void testRebuildWithRemoteInput_noExistingInputWithSpinner() {
+        StatusBarNotification newSbn =
+                mRemoteInputManager.rebuildNotificationWithRemoteInput(mEntry, "A Reply", true);
+        CharSequence[] messages = newSbn.getNotification().extras
+                .getCharSequenceArray(Notification.EXTRA_REMOTE_INPUT_HISTORY);
+        assertEquals(1, messages.length);
+        assertEquals("A Reply", messages[0]);
+        assertTrue(newSbn.getNotification().extras
+                .getBoolean(Notification.EXTRA_SHOW_REMOTE_INPUT_SPINNER, false));
+        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 =
+                mRemoteInputManager.rebuildNotificationWithRemoteInput(mEntry, "A Reply", false);
+        NotificationData.Entry entry = new NotificationData.Entry(newSbn);
+
+        // Try rebuilding to add another reply.
+        newSbn = mRemoteInputManager.rebuildNotificationWithRemoteInput(entry, "Reply 2", true);
+        CharSequence[] messages = newSbn.getNotification().extras
+                .getCharSequenceArray(Notification.EXTRA_REMOTE_INPUT_HISTORY);
+        assertEquals(2, messages.length);
+        assertEquals("Reply 2", messages[0]);
+        assertEquals("A Reply", messages[1]);
+    }
+
+    @Test
+    public void testRebuildNotificationForCanceledSmartReplies() {
+        // Try rebuilding to remove spinner and hide buttons.
+        StatusBarNotification newSbn =
+                mRemoteInputManager.rebuildNotificationForCanceledSmartReplies(mEntry);
+        assertFalse(newSbn.getNotification().extras
+                .getBoolean(Notification.EXTRA_SHOW_REMOTE_INPUT_SPINNER, false));
+        assertTrue(newSbn.getNotification().extras
+                .getBoolean(Notification.EXTRA_HIDE_SMART_REPLIES, false));
+    }
+
+
     private class TestableNotificationRemoteInputManager extends NotificationRemoteInputManager {
 
         public TestableNotificationRemoteInputManager(Context context) {
@@ -118,5 +208,15 @@
             super.setUpWithPresenter(presenter, entryManager, callback, delegate);
             mRemoteInputController = controller;
         }
+
+        @Override
+        protected void addLifetimeExtenders() {
+            mRemoteInputActiveExtender = new RemoteInputActiveExtender();
+            mRemoteInputHistoryExtender = new RemoteInputHistoryExtender();
+            mSmartReplyHistoryExtender = new SmartReplyHistoryExtender();
+            mLifetimeExtenders.add(mRemoteInputHistoryExtender);
+            mLifetimeExtenders.add(mSmartReplyHistoryExtender);
+            mLifetimeExtenders.add(mRemoteInputActiveExtender);
+        }
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/ScrimViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/ScrimViewTest.java
index 42dad11..c2611e4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/ScrimViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/ScrimViewTest.java
@@ -92,15 +92,6 @@
     }
 
     @Test
-    public void testOnDraw_ExcludeRectDrawable() {
-        mView.setExcludedArea(new Rect(10, 10, 20, 20));
-        Canvas canvas = mock(Canvas.class);
-        mView.onDraw(canvas);
-        // One time for each rect side
-        verify(canvas, times(8)).clipRect(anyInt(), anyInt(), anyInt(), anyInt());
-    }
-
-    @Test
     public void setTint_set() {
         int tint = Color.BLUE;
         mView.setTint(tint);
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 ada5785..17daaac 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java
@@ -23,8 +23,11 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.app.ActivityManager;
 import android.app.Notification;
 import android.os.RemoteException;
+import android.os.UserHandle;
+import android.service.notification.NotificationListenerService;
 import android.service.notification.StatusBarNotification;
 import android.support.test.filters.SmallTest;
 import android.testing.AndroidTestingRunner;
@@ -35,6 +38,7 @@
 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 org.junit.Before;
 import org.junit.Test;
@@ -46,97 +50,88 @@
 @TestableLooper.RunWithLooper
 @SmallTest
 public class SmartReplyControllerTest extends SysuiTestCase {
-    private static final String TEST_NOTIFICATION_KEY = "akey";
+    private static final String TEST_PACKAGE_NAME = "test";
+    private static final int TEST_UID = 0;
     private static final String TEST_CHOICE_TEXT = "A Reply";
     private static final int TEST_CHOICE_INDEX = 2;
     private static final int TEST_CHOICE_COUNT = 4;
 
     private Notification mNotification;
     private NotificationData.Entry mEntry;
+    private SmartReplyController mSmartReplyController;
+    private NotificationRemoteInputManager mRemoteInputManager;
 
-    @Mock
-    private NotificationEntryManager mNotificationEntryManager;
-    @Mock
-    private IStatusBarService mIStatusBarService;
+    @Mock private NotificationPresenter mPresenter;
+    @Mock private RemoteInputController.Delegate mDelegate;
+    @Mock private NotificationRemoteInputManager.Callback mCallback;
+    @Mock private StatusBarNotification mSbn;
+    @Mock private NotificationEntryManager mNotificationEntryManager;
+    @Mock private IStatusBarService mIStatusBarService;
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
-
         mDependency.injectTestDependency(NotificationEntryManager.class,
                 mNotificationEntryManager);
         mDependency.injectTestDependency(IStatusBarService.class, mIStatusBarService);
 
+        mSmartReplyController = new SmartReplyController();
+        mDependency.injectTestDependency(SmartReplyController.class,
+                mSmartReplyController);
+
+        mRemoteInputManager = new NotificationRemoteInputManager(mContext);
+        mRemoteInputManager.setUpWithPresenter(mPresenter, mNotificationEntryManager, mCallback,
+                mDelegate);
         mNotification = new Notification.Builder(mContext, "")
                 .setSmallIcon(R.drawable.ic_person)
                 .setContentTitle("Title")
                 .setContentText("Text").build();
-        StatusBarNotification sbn = mock(StatusBarNotification.class);
-        when(sbn.getNotification()).thenReturn(mNotification);
-        when(sbn.getKey()).thenReturn(TEST_NOTIFICATION_KEY);
-        mEntry = new NotificationData.Entry(sbn);
+
+        mSbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME, 0, null, TEST_UID,
+                0, mNotification, new UserHandle(ActivityManager.getCurrentUser()), null, 0);
+        mEntry = new NotificationData.Entry(mSbn);
     }
 
     @Test
     public void testSendSmartReply_updatesRemoteInput() {
-        StatusBarNotification sbn = mock(StatusBarNotification.class);
-        when(sbn.getKey()).thenReturn(TEST_NOTIFICATION_KEY);
-        when(mNotificationEntryManager.rebuildNotificationWithRemoteInput(
-                argThat(entry -> entry.notification.getKey().equals(TEST_NOTIFICATION_KEY)),
-                eq(TEST_CHOICE_TEXT), eq(true))).thenReturn(sbn);
-
-        SmartReplyController controller = new SmartReplyController();
-        controller.smartReplySent(mEntry, TEST_CHOICE_INDEX, TEST_CHOICE_TEXT);
+        mSmartReplyController.smartReplySent(mEntry, TEST_CHOICE_INDEX, TEST_CHOICE_TEXT);
 
         // Sending smart reply should make calls to NotificationEntryManager
         // to update the notification with reply and spinner.
-        verify(mNotificationEntryManager).rebuildNotificationWithRemoteInput(
-                argThat(entry -> entry.notification.getKey().equals(TEST_NOTIFICATION_KEY)),
-                eq(TEST_CHOICE_TEXT), eq(true));
         verify(mNotificationEntryManager).updateNotification(
-                argThat(sbn2 -> sbn2.getKey().equals(TEST_NOTIFICATION_KEY)), isNull());
+                argThat(sbn -> sbn.getKey().equals(mSbn.getKey())), isNull());
     }
 
     @Test
     public void testSendSmartReply_logsToStatusBar() throws RemoteException {
-        StatusBarNotification sbn = mock(StatusBarNotification.class);
-        when(sbn.getKey()).thenReturn(TEST_NOTIFICATION_KEY);
-        when(mNotificationEntryManager.rebuildNotificationWithRemoteInput(
-                argThat(entry -> entry.notification.getKey().equals(TEST_NOTIFICATION_KEY)),
-                eq(TEST_CHOICE_TEXT), eq(true))).thenReturn(sbn);
-
-        SmartReplyController controller = new SmartReplyController();
-        controller.smartReplySent(mEntry, TEST_CHOICE_INDEX, TEST_CHOICE_TEXT);
+        mSmartReplyController.smartReplySent(mEntry, TEST_CHOICE_INDEX, TEST_CHOICE_TEXT);
 
         // Check we log the result to the status bar service.
-        verify(mIStatusBarService).onNotificationSmartReplySent(TEST_NOTIFICATION_KEY,
+        verify(mIStatusBarService).onNotificationSmartReplySent(mSbn.getKey(),
                 TEST_CHOICE_INDEX);
     }
 
     @Test
     public void testShowSmartReply_logsToStatusBar() throws RemoteException {
-        SmartReplyController controller = new SmartReplyController();
-        controller.smartRepliesAdded(mEntry, TEST_CHOICE_COUNT);
+        mSmartReplyController.smartRepliesAdded(mEntry, TEST_CHOICE_COUNT);
 
         // Check we log the result to the status bar service.
-        verify(mIStatusBarService).onNotificationSmartRepliesAdded(TEST_NOTIFICATION_KEY,
+        verify(mIStatusBarService).onNotificationSmartRepliesAdded(mSbn.getKey(),
                 TEST_CHOICE_COUNT);
     }
 
     @Test
     public void testSendSmartReply_reportsSending() {
-        SmartReplyController controller = new SmartReplyController();
-        controller.smartReplySent(mEntry, TEST_CHOICE_INDEX, TEST_CHOICE_TEXT);
+        mSmartReplyController.smartReplySent(mEntry, TEST_CHOICE_INDEX, TEST_CHOICE_TEXT);
 
-        assertTrue(controller.isSendingSmartReply(TEST_NOTIFICATION_KEY));
+        assertTrue(mSmartReplyController.isSendingSmartReply(mSbn.getKey()));
     }
 
     @Test
     public void testSendingSmartReply_afterRemove_shouldReturnFalse() {
-        SmartReplyController controller = new SmartReplyController();
-        controller.isSendingSmartReply(TEST_NOTIFICATION_KEY);
-        controller.stopSending(mEntry);
+        mSmartReplyController.smartReplySent(mEntry, TEST_CHOICE_INDEX, TEST_CHOICE_TEXT);
+        mSmartReplyController.stopSending(mEntry);
 
-        assertFalse(controller.isSendingSmartReply(TEST_NOTIFICATION_KEY));
+        assertFalse(mSmartReplyController.isSendingSmartReply(mSbn.getKey()));
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
index 6543bdb..4e16b7f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
@@ -57,6 +57,7 @@
 import com.android.systemui.ForegroundServiceController;
 import com.android.systemui.R;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.NotificationLifetimeExtender;
 import com.android.systemui.statusbar.NotificationListener;
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
 import com.android.systemui.statusbar.NotificationMediaManager;
@@ -84,7 +85,6 @@
 
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.List;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
@@ -143,6 +143,10 @@
         public CountDownLatch getCountDownLatch() {
             return mCountDownLatch;
         }
+
+        public ArrayList<NotificationLifetimeExtender> getLifetimeExtenders() {
+            return mNotificationLifetimeExtenders;
+        }
     }
 
     private void setUserSentiment(String key, int sentiment) {
@@ -279,7 +283,6 @@
         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);
@@ -301,8 +304,6 @@
                 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();
@@ -313,17 +314,23 @@
     }
 
     @Test
-    public void testRemoveNotification_blockedBySendingSmartReply() throws Exception {
+    public void testRemoveNotification_blockedByLifetimeExtender() {
         com.android.systemui.util.Assert.isNotMainThread();
 
+        NotificationLifetimeExtender extender = mock(NotificationLifetimeExtender.class);
+        when(extender.shouldExtendLifetime(mEntry)).thenReturn(true);
+
+        ArrayList<NotificationLifetimeExtender> extenders = mEntryManager.getLifetimeExtenders();
+        extenders.clear();
+        extenders.add(extender);
+
         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));
+        verify(extender).setShouldManageLifetime(mEntry, true /* shouldManage */);
     }
 
     @Test
@@ -411,61 +418,6 @@
     }
 
     @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);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
index 676cb61..8edbf17 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
@@ -22,6 +22,8 @@
 
 import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE;
 import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertNull;
+import static junit.framework.Assert.assertTrue;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.fail;
@@ -30,6 +32,7 @@
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 import static org.mockito.Mockito.spy;
@@ -54,6 +57,7 @@
 
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
+import com.android.systemui.statusbar.notification.NotificationData;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.NotificationPresenter;
 import com.android.systemui.statusbar.NotificationTestHelper;
@@ -99,7 +103,7 @@
         mHelper = new NotificationTestHelper(mContext);
 
         mGutsManager = new NotificationGutsManager(mContext);
-        mGutsManager.setUpWithPresenter(mPresenter, mEntryManager, mStackScroller,
+        mGutsManager.setUpWithPresenter(mPresenter, mStackScroller,
                 mCheckSaveListener, mOnSettingsClickListener);
     }
 
@@ -346,6 +350,35 @@
                 eq(true) /* isUserSentimentNegative */);
     }
 
+    @Test
+    public void testShouldExtendLifetime() {
+        NotificationGuts guts = new NotificationGuts(mContext);
+        ExpandableNotificationRow row = spy(createTestNotificationRow());
+        doReturn(guts).when(row).getGuts();
+        NotificationData.Entry entry = row.getEntry();
+        entry.row = row;
+        mGutsManager.setExposedGuts(guts);
+
+        assertTrue(mGutsManager.shouldExtendLifetime(entry));
+    }
+
+    @Test
+    public void testSetShouldManageLifetime_setShouldManage() {
+        NotificationData.Entry entry = createTestNotificationRow().getEntry();
+        mGutsManager.setShouldManageLifetime(entry, true /* shouldManage */);
+
+        assertTrue(entry.key.equals(mGutsManager.mKeyToRemoveOnGutsClosed));
+    }
+
+    @Test
+    public void testSetShouldManageLifetime_setShouldNotManage() {
+        NotificationData.Entry entry = createTestNotificationRow().getEntry();
+        mGutsManager.mKeyToRemoveOnGutsClosed = entry.key;
+        mGutsManager.setShouldManageLifetime(entry, false /* shouldManage */);
+
+        assertNull(mGutsManager.mKeyToRemoveOnGutsClosed);
+    }
+
     ////////////////////////////////////////////////////////////////////////////////////////////////
     // Utility methods:
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
index c19188c..ce0bd58 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
@@ -112,7 +112,8 @@
 
         mEntryManager = new TestableNotificationEntryManager(mSystemServicesProxy, mPowerManager,
                 mContext);
-        mEntryManager.setUpForTest(mock(NotificationPresenter.class), null, null, null, mNotificationData);
+        mEntryManager.setUpForTest(mock(NotificationPresenter.class), null, null, mHeadsUpManager,
+                mNotificationData);
         mDependency.injectTestDependency(NotificationEntryManager.class, mEntryManager);
 
         NotificationShelf notificationShelf = spy(new NotificationShelf(getContext(), null));
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 bdf7cd3..a81d17f 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
@@ -23,6 +23,7 @@
 
 import com.android.systemui.statusbar.AlertingNotificationManager;
 import com.android.systemui.statusbar.AlertingNotificationManagerTest;
+import com.android.systemui.statusbar.notification.NotificationData;
 import com.android.systemui.statusbar.notification.VisualStabilityManager;
 
 import org.junit.Before;
@@ -83,4 +84,26 @@
 
         assertFalse(mHeadsUpManager.contains(mEntry.key));
     }
+
+    @Test
+    public void testShouldExtendLifetime_swipedOut() {
+        mHeadsUpManager.showNotification(mEntry);
+        mHeadsUpManager.addSwipedOutNotification(mEntry.key);
+
+        // Notification is swiped so its lifetime should not be extended even if it hasn't been
+        // shown long enough
+        assertFalse(mHeadsUpManager.shouldExtendLifetime(mEntry));
+    }
+
+    @Test
+    public void testShouldExtendLifetime_notTopEntry() {
+        NotificationData.Entry laterEntry = new NotificationData.Entry(createNewNotification(1));
+        laterEntry.row = mRow;
+        mHeadsUpManager.showNotification(mEntry);
+        mHeadsUpManager.showNotification(laterEntry);
+
+        // Notification is "behind" a higher priority notification so we have no reason to keep
+        // its lifetime extended
+        assertFalse(mHeadsUpManager.shouldExtendLifetime(mEntry));
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupManagerTest.java
new file mode 100644
index 0000000..6a3c8a8
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupManagerTest.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.systemui.statusbar.phone;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+
+import static org.junit.Assert.assertNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.verify;
+
+import android.app.ActivityManager;
+import android.app.Notification;
+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.notification.NotificationData;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.phone.NotificationGroupManager.OnGroupChangeListener;
+import com.android.systemui.statusbar.policy.HeadsUpManager;
+
+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 NotificationGroupManagerTest extends SysuiTestCase {
+    @Rule
+    public MockitoRule rule = MockitoJUnit.rule();
+
+    private static final String TEST_CHANNEL_ID = "test_channel";
+    private static final String TEST_GROUP_ID = "test_group";
+    private static final String TEST_PACKAGE_NAME = "test_pkg";
+    private NotificationGroupManager mGroupManager = new NotificationGroupManager();
+    private int mId = 0;
+
+    @Mock HeadsUpManager mHeadsUpManager;
+
+    @Before
+    public void setup() {
+         mGroupManager.setHeadsUpManager(mHeadsUpManager);
+         mGroupManager.setOnGroupChangeListener(mock(OnGroupChangeListener.class));
+    }
+
+    @Test
+    public void testIsOnlyChildInGroup() {
+        NotificationData.Entry childEntry = createChildNotification();
+        NotificationData.Entry summaryEntry = createSummaryNotification();
+
+        mGroupManager.onEntryAdded(summaryEntry);
+        mGroupManager.onEntryAdded(childEntry);
+
+        assertTrue(mGroupManager.isOnlyChildInGroup(childEntry.notification));
+    }
+
+    @Test
+    public void testIsChildInGroupWithSummary() {
+        NotificationData.Entry childEntry = createChildNotification();
+        NotificationData.Entry summaryEntry = createSummaryNotification();
+
+        mGroupManager.onEntryAdded(summaryEntry);
+        mGroupManager.onEntryAdded(childEntry);
+        mGroupManager.onEntryAdded(createChildNotification());
+
+        assertTrue(mGroupManager.isChildInGroupWithSummary(childEntry.notification));
+    }
+
+    @Test
+    public void testIsSummaryOfGroupWithChildren() {
+        NotificationData.Entry childEntry = createChildNotification();
+        NotificationData.Entry summaryEntry = createSummaryNotification();
+
+        mGroupManager.onEntryAdded(summaryEntry);
+        mGroupManager.onEntryAdded(childEntry);
+        mGroupManager.onEntryAdded(createChildNotification());
+
+        assertTrue(mGroupManager.isSummaryOfGroup(summaryEntry.notification));
+        assertEquals(summaryEntry.row, mGroupManager.getGroupSummary(childEntry.notification));
+    }
+
+    @Test
+    public void testRemoveChildFromGroupWithSummary() {
+        NotificationData.Entry childEntry = createChildNotification();
+        NotificationData.Entry summaryEntry = createSummaryNotification();
+        mGroupManager.onEntryAdded(summaryEntry);
+        mGroupManager.onEntryAdded(childEntry);
+        mGroupManager.onEntryAdded(createChildNotification());
+
+        mGroupManager.onEntryRemoved(childEntry);
+
+        assertFalse(mGroupManager.isChildInGroupWithSummary(childEntry.notification));
+    }
+
+    @Test
+    public void testRemoveSummaryFromGroupWithSummary() {
+        NotificationData.Entry childEntry = createChildNotification();
+        NotificationData.Entry summaryEntry = createSummaryNotification();
+        mGroupManager.onEntryAdded(summaryEntry);
+        mGroupManager.onEntryAdded(childEntry);
+        mGroupManager.onEntryAdded(createChildNotification());
+
+        mGroupManager.onEntryRemoved(summaryEntry);
+
+        assertNull(mGroupManager.getGroupSummary(childEntry.notification));
+        assertFalse(mGroupManager.isSummaryOfGroup(summaryEntry.notification));
+    }
+
+    @Test
+    public void testHeadsUpEntryIsIsolated() {
+        NotificationData.Entry childEntry = createChildNotification();
+        NotificationData.Entry summaryEntry = createSummaryNotification();
+        mGroupManager.onEntryAdded(summaryEntry);
+        mGroupManager.onEntryAdded(childEntry);
+        mGroupManager.onEntryAdded(createChildNotification());
+        when(childEntry.row.isHeadsUp()).thenReturn(true);
+        when(mHeadsUpManager.contains(childEntry.key)).thenReturn(true);
+
+        mGroupManager.onHeadsUpStateChanged(childEntry, true);
+
+        // Child entries that are heads upped should be considered separate groups visually even if
+        // they are the same group logically
+        assertEquals(childEntry.row, mGroupManager.getGroupSummary(childEntry.notification));
+        assertEquals(summaryEntry.row,
+                mGroupManager.getLogicalGroupSummary(childEntry.notification));
+    }
+
+    @Test
+    public void testSuppressedSummaryHeadsUpTransfersToChild() {
+        NotificationData.Entry summaryEntry = createSummaryNotification();
+        when(summaryEntry.row.isHeadsUp()).thenReturn(true);
+        when(mHeadsUpManager.contains(summaryEntry.key)).thenReturn(true);
+        NotificationData.Entry childEntry = createChildNotification();
+
+        // Summary will be suppressed because there is only one child
+        mGroupManager.onEntryAdded(summaryEntry);
+        mGroupManager.onEntryAdded(childEntry);
+
+        // A suppressed summary should transfer its heads up state to the child
+        verify(mHeadsUpManager, never()).showNotification(summaryEntry);
+        verify(mHeadsUpManager).showNotification(childEntry);
+    }
+
+    @Test
+    public void testSuppressedSummaryHeadsUpTransfersToChildButBackAgain() {
+        mHeadsUpManager = new HeadsUpManager(mContext) {};
+        mGroupManager.setHeadsUpManager(mHeadsUpManager);
+        NotificationData.Entry summaryEntry =
+                createSummaryNotification(Notification.GROUP_ALERT_SUMMARY);
+        when(summaryEntry.row.isHeadsUp()).thenReturn(true);
+        NotificationData.Entry childEntry =
+                createChildNotification(Notification.GROUP_ALERT_SUMMARY);
+        NotificationData.Entry childEntry2 =
+                createChildNotification(Notification.GROUP_ALERT_SUMMARY);
+        // Trigger a transfer of heads up state from summary to child.
+        mGroupManager.onEntryAdded(summaryEntry);
+        mGroupManager.onEntryAdded(childEntry);
+        when(summaryEntry.row.isHeadsUp()).thenReturn(false);
+        when(childEntry.row.isHeadsUp()).thenReturn(true);
+
+        // Add second child notification so that summary is no longer suppressed.
+        mGroupManager.onEntryAdded(childEntry2);
+
+        // The heads up state should transfer back to the summary as there is now more than one
+        // child and the summary should no longer be suppressed.
+        assertTrue(mHeadsUpManager.contains(summaryEntry.key));
+        assertFalse(mHeadsUpManager.contains(childEntry.key));
+    }
+
+    private NotificationData.Entry createSummaryNotification() {
+        return createSummaryNotification(Notification.GROUP_ALERT_ALL);
+    }
+
+    private NotificationData.Entry createSummaryNotification(int groupAlertBehavior) {
+        return createEntry(true, groupAlertBehavior);
+    }
+
+    private NotificationData.Entry createChildNotification() {
+        return createChildNotification(Notification.GROUP_ALERT_ALL);
+    }
+
+    private NotificationData.Entry createChildNotification(int groupAlertBehavior) {
+        return createEntry(false, groupAlertBehavior);
+    }
+
+    private NotificationData.Entry createEntry(boolean isSummary, int groupAlertBehavior) {
+        Notification notif = new Notification.Builder(mContext, TEST_CHANNEL_ID)
+                .setContentTitle("Title")
+                .setSmallIcon(R.drawable.ic_person)
+                .setGroupAlertBehavior(groupAlertBehavior)
+                .setGroupSummary(isSummary)
+                .setGroup(TEST_GROUP_ID)
+                .build();
+        StatusBarNotification sbn = new StatusBarNotification(
+                TEST_PACKAGE_NAME /* pkg */,
+                TEST_PACKAGE_NAME,
+                mId++,
+                null /* tag */,
+                0, /* uid */
+                0 /* initialPid */,
+                notif,
+                new UserHandle(ActivityManager.getCurrentUser()),
+                null /* overrideGroupKey */,
+                0 /* postTime */);
+        NotificationData.Entry entry = new NotificationData.Entry(sbn);
+        ExpandableNotificationRow row = mock(ExpandableNotificationRow.class);
+        entry.row = row;
+        when(row.getEntry()).thenReturn(entry);
+        when(row.getStatusBarNotification()).thenReturn(sbn);
+        return entry;
+    }
+}
diff --git a/packages/VpnDialogs/res/values-es-rUS/strings.xml b/packages/VpnDialogs/res/values-es-rUS/strings.xml
index 3732ebc..21cfc04 100644
--- a/packages/VpnDialogs/res/values-es-rUS/strings.xml
+++ b/packages/VpnDialogs/res/values-es-rUS/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">"Solicitud de conexión"</string>
-    <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> quiere configurar una conexión VPN que permite controlar el tráfico de la red. Acéptala solo si confías en la fuente. &lt;br /&gt; &lt;br /&gt; &lt;img src=vpn_icon /&gt; aparece en la parte superior de la pantalla cuando la VPN está activa."</string>
+    <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> quiere configurar una conexión VPN capaz de controlar el tráfico de la red. Acéptala solo si confías en la fuente. &lt;br /&gt; &lt;br /&gt; &lt;img src=vpn_icon /&gt; aparece en la parte superior de la pantalla cuando se activa la VPN."</string>
     <string name="legacy_title" msgid="192936250066580964">"La VPN está conectada."</string>
     <string name="session" msgid="6470628549473641030">"Sesión:"</string>
     <string name="duration" msgid="3584782459928719435">"Duración:"</string>
diff --git a/packages/VpnDialogs/res/values-ru/strings.xml b/packages/VpnDialogs/res/values-ru/strings.xml
index 0543937..f8fcfb8 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-vi/strings.xml b/packages/VpnDialogs/res/values-vi/strings.xml
index 097c9ae..fa5e114 100644
--- a/packages/VpnDialogs/res/values-vi/strings.xml
+++ b/packages/VpnDialogs/res/values-vi/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">"Yêu cầu kết nối"</string>
-    <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> muốn thiết lập kết nối VPN cho phép ứng dụng giám sát lưu lượng truy cập mạng. Chỉ chấp nhận nếu bạn tin tưởng nguồn. &lt;br /&gt; &lt;br /&gt; Biểu tượng &lt;img src=vpn_icon /&gt; xuất hiện ở đầu màn hình của bạn khi VPN đang hoạt động."</string>
+    <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> muốn thiết lập kết nối VPN cho phép ứng dụng giám sát lưu lượng truy cập mạng. Chỉ chấp nhận nếu bạn tin tưởng nguồn. Biểu tượng &lt;br /&gt; &lt;br /&gt; &lt;img src=vpn_icon /&gt; xuất hiện ở đầu màn hình của bạn khi VPN đang hoạt động."</string>
     <string name="legacy_title" msgid="192936250066580964">"VPN được kết nối"</string>
     <string name="session" msgid="6470628549473641030">"Phiên"</string>
     <string name="duration" msgid="3584782459928719435">"Thời lượng:"</string>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-bn/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-bn/strings.xml
new file mode 100644
index 0000000..41aa8045
--- /dev/null
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-bn/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <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
new file mode 100644
index 0000000..435b664
--- /dev/null
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-hi/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <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
new file mode 100644
index 0000000..4a31006
--- /dev/null
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-te/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"మూల కట్అవుట్‌"</string>
+</resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-bn/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-bn/strings.xml
new file mode 100644
index 0000000..d08874c
--- /dev/null
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-bn/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <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
new file mode 100644
index 0000000..d574f6c
--- /dev/null
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-hi/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <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
new file mode 100644
index 0000000..e32415c
--- /dev/null
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-te/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <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 d585d7e..b307ac7 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="5323179900047630217">"Kesimni ikki marta kattalashtirish"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"Kesimni ikkilantirish"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-bn/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-bn/strings.xml
new file mode 100644
index 0000000..27f8290
--- /dev/null
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-bn/strings.xml
@@ -0,0 +1,23 @@
+<?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="3947428012427075896">"ন্যারো কাট-আউট"</string>
+</resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-fr/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-fr/strings.xml
index 551aa19..577a948 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="3947428012427075896">"Encoche pour écran étroit"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"Encoche étroite"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-hi/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-hi/strings.xml
new file mode 100644
index 0000000..39747d1
--- /dev/null
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-hi/strings.xml
@@ -0,0 +1,23 @@
+<?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="3947428012427075896">"नैराे कटआउट"</string>
+</resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-te/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-te/strings.xml
new file mode 100644
index 0000000..9bde419
--- /dev/null
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-te/strings.xml
@@ -0,0 +1,23 @@
+<?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="3947428012427075896">"సన్నని కట్అవుట్‌"</string>
+</resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-bn/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-bn/strings.xml
new file mode 100644
index 0000000..a2825df
--- /dev/null
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-bn/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"টল কাট-আউট"</string>
+</resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-fr/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-fr/strings.xml
index 58c42b4..5f4d729 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="6424539415439220018">"Encoche pour écran haut"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"Encoche haute"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-hi/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-hi/strings.xml
new file mode 100644
index 0000000..a8bdf05
--- /dev/null
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-hi/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <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
new file mode 100644
index 0000000..2e6233d
--- /dev/null
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-te/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <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 5efafd5..f2e080a 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="6424539415439220018">"Kesimni balandroq qilish"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"Kesimni balandlatish"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-bn/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-bn/strings.xml
new file mode 100644
index 0000000..4492290
--- /dev/null
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-bn/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"ওয়াইড কাট-আউট"</string>
+</resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-fr/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-fr/strings.xml
index ce8e131..f9b15cf 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="4043478945358357737">"Encoche pour écran large"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"Encoche large"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-hi/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-hi/strings.xml
new file mode 100644
index 0000000..8f97495
--- /dev/null
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-hi/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <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
new file mode 100644
index 0000000..4da4f95
--- /dev/null
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-te/strings.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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"వెడల్పైన కట్అవుట్‌"</string>
+</resources>
diff --git a/proto/src/metrics_constants/OWNERS b/proto/src/metrics_constants/OWNERS
new file mode 100644
index 0000000..7009282
--- /dev/null
+++ b/proto/src/metrics_constants/OWNERS
@@ -0,0 +1,4 @@
+cwren@android.com
+yanglu@google.com
+yaochen@google.com
+yro@google.com
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants/metrics_constants.proto
similarity index 99%
rename from proto/src/metrics_constants.proto
rename to proto/src/metrics_constants/metrics_constants.proto
index b668623..41b3feb 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants/metrics_constants.proto
@@ -6508,6 +6508,15 @@
     // OS: Q
     ACTION_EMERGENCY_DIALER_FROM_POWER_MENU = 1569;
 
+    // OPEN: Settings > System > Input & Gesture > Wake screen
+    // OS: Q
+    SETTINGS_GESTURE_WAKE_SCREEN = 1570;
+
+    // OPEN: Settings > Network & internet > Mobile network
+    // CATEGORY: SETTINGS
+    // OS: Q
+    MOBILE_NETWORK = 1571;
+
     // ---- End Q Constants, all Q constants go above this line ----
 
     // Add new aosp constants above this line.
diff --git a/core/tests/webkit/apk_with_native_libs/jni/WebViewTestJniOnLoad.cpp b/proto/src/stats_enums.proto
similarity index 70%
rename from core/tests/webkit/apk_with_native_libs/jni/WebViewTestJniOnLoad.cpp
rename to proto/src/stats_enums.proto
index 0ced4ee..6c892cf 100644
--- a/core/tests/webkit/apk_with_native_libs/jni/WebViewTestJniOnLoad.cpp
+++ b/proto/src/stats_enums.proto
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 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.
@@ -14,8 +14,13 @@
  * limitations under the License.
  */
 
-#include <jni.h>
+syntax = "proto2";
 
-jint JNI_OnLoad(JavaVM * /*vm*/, void * /*reserved*/) {
-    return JNI_VERSION_1_4;
+package android.os.statsd;
+option java_package = "com.android.os";
+option java_outer_classname = "StatsEnums";
+
+enum EventType {
+  // Unknown.
+  TYPE_UNKNOWN = 0;
 }
diff --git a/services/accessibility/TEST_MAPPING b/services/accessibility/TEST_MAPPING
new file mode 100644
index 0000000..320924c
--- /dev/null
+++ b/services/accessibility/TEST_MAPPING
@@ -0,0 +1,105 @@
+{
+  "presubmit": [
+    {
+      "name": "CtsAccessibilityServiceTestCases",
+      "options": [
+        {
+          "include-annotation": "android.platform.test.annotations.Presubmit"
+        },
+        {
+          "exclude-annotation": "android.support.test.filters.FlakyTest"
+        }
+      ]
+    },
+    {
+      "name": "CtsAccessibilityTestCases",
+      "options": [
+        {
+          "include-annotation": "android.platform.test.annotations.Presubmit"
+        },
+        {
+          "exclude-annotation": "android.support.test.filters.FlakyTest"
+        }
+      ]
+    },
+    {
+      "name": "CtsUiAutomationTestCases",
+      "options": [
+        {
+          "include-annotation": "android.platform.test.annotations.Presubmit"
+        },
+        {
+          "exclude-annotation": "android.support.test.filters.FlakyTest"
+        }
+      ]
+    },
+    {
+      "name": "FrameworksServicesTests",
+      "options": [
+        {
+          "include-filter": "com.android.server.accessibility"
+        },
+        {
+          "exclude-annotation": "android.support.test.filters.FlakyTest"
+        }
+      ]
+    },
+    {
+      "name": "FrameworksCoreTests",
+      "options": [
+        {
+          "include-filter": "com.android.internal.accessibility"
+        },
+        {
+          "exclude-annotation": "android.support.test.filters.FlakyTest"
+        }
+      ]
+    },
+    {
+      "name": "FrameworksCoreTests",
+      "options": [
+        {
+          "include-filter": "android.view.accessibility"
+        },
+        {
+          "exclude-annotation": "android.support.test.filters.FlakyTest"
+        }
+      ]
+    }
+  ],
+  "postsubmit": [
+    {
+      "name": "CtsAccessibilityServiceTestCases"
+    },
+    {
+      "name": "CtsAccessibilityTestCases"
+    },
+    {
+      "name": "CtsUiAutomationTestCases"
+    },
+    {
+      "name": "FrameworksServicesTests",
+      "options": [
+        {
+          "include-filter": "com.android.server.accessibility"
+        }
+      ]
+    },
+    {
+      "name": "FrameworksCoreTests",
+      "options": [
+        {
+          "include-filter": "com.android.internal.accessibility"
+        }
+      ]
+    },
+    {
+      "name": "FrameworksCoreTests",
+      "options": [
+        {
+          "include-filter": "android.view.accessibility"
+        }
+      ]
+    }
+  ]
+}
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 6be9550..9bee8db 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -21,11 +21,13 @@
 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 android.view.accessibility.AccessibilityNodeInfo.ACTION_CLICK;
+import static android.view.accessibility.AccessibilityNodeInfo.ACTION_LONG_CLICK;
 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_IGNORE_HARD_KEYBOARD;
 import static android.accessibilityservice.AccessibilityService.SHOW_MODE_HARD_KEYBOARD_ORIGINAL_VALUE;
 import static android.accessibilityservice.AccessibilityService.SHOW_MODE_HARD_KEYBOARD_OVERRIDDEN;
 
@@ -1689,6 +1691,24 @@
                 this, userState));
     }
 
+    private void scheduleSetAllClientsMinimumUiTimeout(UserState userState) {
+        mMainHandler.sendMessage(obtainMessage(
+                AccessibilityManagerService::sendMinimumUiTimeoutChanged,
+                this, userState.mUserClients, userState.mMinimumUiTimeout));
+    }
+
+    private void sendMinimumUiTimeoutChanged(
+            RemoteCallbackList<IAccessibilityManagerClient> userClients, int uiTimeout) {
+        notifyClientsOfServicesMinimumUiTimeoutChange(mGlobalClients, uiTimeout);
+        notifyClientsOfServicesMinimumUiTimeoutChange(userClients, uiTimeout);
+    }
+
+    private void notifyClientsOfServicesMinimumUiTimeoutChange(
+            RemoteCallbackList<IAccessibilityManagerClient> clients, int uiTimeout) {
+        clients.broadcast(ignoreRemoteException(
+                client -> client.setMinimumUiTimeout(uiTimeout)));
+    }
+
     private void updateInputFilter(UserState userState) {
         if (mUiAutomationManager.suppressingAccessibilityServicesLocked()) return;
 
@@ -1822,6 +1842,7 @@
         scheduleUpdateClientsIfNeededLocked(userState);
         updateRelevantEventsLocked(userState);
         updateAccessibilityButtonTargetsLocked(userState);
+        updateMinimumUiTimeoutLocked(userState);
     }
 
     private void updateAccessibilityFocusBehaviorLocked(UserState userState) {
@@ -1940,6 +1961,7 @@
         somethingChanged |= readAutoclickEnabledSettingLocked(userState);
         somethingChanged |= readAccessibilityShortcutSettingLocked(userState);
         somethingChanged |= readAccessibilityButtonSettingsLocked(userState);
+        somethingChanged |= readUserMinimumUiTimeoutSettingsLocked(userState);
         return somethingChanged;
     }
 
@@ -2084,6 +2106,22 @@
         return true;
     }
 
+    private boolean readUserMinimumUiTimeoutSettingsLocked(UserState userState) {
+        final boolean enabled = Settings.Secure.getIntForUser(mContext.getContentResolver(),
+                Settings.Secure.ACCESSIBILITY_MINIMUM_UI_TIMEOUT_ENABLED, 0,
+                userState.mUserId) == 1;
+        final int timeout = Settings.Secure.getIntForUser(mContext.getContentResolver(),
+                Settings.Secure.ACCESSIBILITY_MINIMUM_UI_TIMEOUT_MS, 0,
+                userState.mUserId);
+        if (enabled != userState.mUserMinimumUiTimeoutEnabled
+                || timeout != userState.mUserMinimumUiTimeout) {
+            userState.mUserMinimumUiTimeoutEnabled = enabled;
+            userState.mUserMinimumUiTimeout = timeout;
+            return true;
+        }
+        return false;
+    }
+
     /**
      * Check if the service that will be enabled by the shortcut is installed. If it isn't,
      * clear the value and the associated setting so a sideloaded service can't spoof the
@@ -2250,6 +2288,27 @@
         }
     }
 
+    private void updateMinimumUiTimeoutLocked(UserState userState) {
+        int newUiTimeout = 0;
+        if (userState.mUserMinimumUiTimeoutEnabled) {
+            newUiTimeout = userState.mUserMinimumUiTimeout;
+        } else {
+            final List<AccessibilityServiceConnection> services = userState.mBoundServices;
+            final int numServices = services.size();
+            for (int i = 0; i < numServices; i++) {
+                final int serviceUiTimeout = services.get(i).getServiceInfo()
+                        .getMinimumUiTimeoutMillis();
+                if (newUiTimeout < serviceUiTimeout) {
+                    newUiTimeout = serviceUiTimeout;
+                }
+            }
+        }
+        if (newUiTimeout != userState.mMinimumUiTimeout) {
+            userState.mMinimumUiTimeout = newUiTimeout;
+            scheduleSetAllClientsMinimumUiTimeout(userState);
+        }
+    }
+
     @GuardedBy("mLock")
     @Override
     public MagnificationSpec getCompatibleMagnificationSpecLocked(int windowId) {
@@ -2388,6 +2447,20 @@
         return mFingerprintGestureDispatcher.onFingerprintGesture(gestureKeyCode);
     }
 
+    /**
+     * Get the minimum timeout for changes to the UI needed by this user. Controls should remain
+     * on the screen for at least this long to give users time to react.
+     *
+     * @return The minimum timeout for the current user in milliseconds.
+     */
+    @Override
+    public int getMinimumUiTimeout() {
+        synchronized(mLock) {
+            final UserState userState = getCurrentUserStateLocked();
+            return userState.mMinimumUiTimeout;
+        }
+    }
+
     @Override
     public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
         if (!DumpUtils.checkDumpPermission(mContext, LOG_TAG, pw)) return;
@@ -2405,6 +2478,7 @@
                 pw.append(", navBarMagnificationEnabled="
                         + userState.mIsNavBarMagnificationEnabled);
                 pw.append(", autoclickEnabled=" + userState.mIsAutoclickEnabled);
+                pw.append(", minimumUiTimeout=" + userState.mMinimumUiTimeout);
                 if (mUiAutomationManager.isUiAutomationRunningLocked()) {
                     pw.append(", ");
                     mUiAutomationManager.dumpUiAutomationService(fd, pw, args);
@@ -2549,6 +2623,38 @@
         return -1;
     }
 
+    private void notifyOutsideTouchIfNeeded(int targetWindowId, int action, Bundle arguments,
+            int interactionId, IAccessibilityInteractionConnectionCallback callback, int fetchFlags,
+            int interrogatingPid, long interrogatingTid) {
+        if (action != ACTION_CLICK && action != ACTION_LONG_CLICK) {
+            return;
+        }
+
+        final List<Integer> outsideWindowsIds;
+        final List<RemoteAccessibilityConnection> connectionList = new ArrayList<>();
+        synchronized (mLock) {
+            outsideWindowsIds = mSecurityPolicy.getWatchOutsideTouchWindowId(targetWindowId);
+            for (int i = 0; i < outsideWindowsIds.size(); i++) {
+                connectionList.add(getConnectionLocked(outsideWindowsIds.get(i)));
+            }
+        }
+        for (int i = 0; i < connectionList.size(); i++) {
+            final RemoteAccessibilityConnection connection = connectionList.get(i);
+            if (connection != null) {
+                try {
+                    connection.mConnection.performAccessibilityAction(
+                            AccessibilityNodeInfo.ROOT_ITEM_ID,
+                            R.id.accessibilityActionOutsideTouch, arguments, interactionId,
+                            callback, fetchFlags, interrogatingPid, interrogatingTid);
+                } catch (RemoteException re) {
+                    if (DEBUG) {
+                        Slog.e(LOG_TAG, "Error calling performAccessibilityAction: " + re);
+                    }
+                }
+            }
+        }
+    }
+
     @Override
     public void ensureWindowsAvailableTimed() {
         synchronized (mLock) {
@@ -2628,6 +2734,8 @@
             mPowerManager.userActivity(SystemClock.uptimeMillis(),
                     PowerManager.USER_ACTIVITY_EVENT_ACCESSIBILITY, 0);
 
+            notifyOutsideTouchIfNeeded(resolvedWindowId, action, arguments, interactionId, callback,
+                    fetchFlags, interrogatingPid, interrogatingTid);
             if (activityToken != null) {
                 LocalServices.getService(ActivityTaskManagerInternal.class)
                         .setFocusedActivity(activityToken);
@@ -2955,6 +3063,7 @@
         public long mAccessibilityFocusNodeId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
 
         private boolean mTouchInteractionInProgress;
+        private boolean mHasWatchOutsideTouchWindow;
 
         private boolean canDispatchAccessibilityEventLocked(AccessibilityEvent event) {
             final int eventType = event.getEventType();
@@ -3112,6 +3221,7 @@
                 mWindowInfoById.valueAt(i).recycle();
             }
             mWindowInfoById.clear();
+            mHasWatchOutsideTouchWindow = false;
 
             mFocusedWindowId = INVALID_WINDOW_ID;
             if (!mTouchInteractionInProgress) {
@@ -3156,6 +3266,9 @@
                                 activeWindowGone = false;
                             }
                         }
+                        if (!mHasWatchOutsideTouchWindow && windowInfo.hasFlagWatchOutsideTouch) {
+                            mHasWatchOutsideTouchWindow = true;
+                        }
                         mWindows.add(window);
                         mA11yWindowInfoById.put(windowId, window);
                         mWindowInfoById.put(windowId, WindowInfo.obtain(windowInfo));
@@ -3574,6 +3687,22 @@
             return mWindowInfoById.get(windowId);
         }
 
+        private List<Integer> getWatchOutsideTouchWindowId(int targetWindowId) {
+            if (mWindowInfoById != null && mHasWatchOutsideTouchWindow) {
+                final List<Integer> outsideWindowsId = new ArrayList<>();
+                final WindowInfo targetWindow = mWindowInfoById.get(targetWindowId);
+                for (int i = 0; i < mWindowInfoById.size(); i++) {
+                    WindowInfo window = mWindowInfoById.valueAt(i);
+                    if (window.layer < targetWindow.layer
+                            && window.hasFlagWatchOutsideTouch) {
+                        outsideWindowsId.add(mWindowInfoById.keyAt(i));
+                    }
+                }
+                return outsideWindowsId;
+            }
+            return Collections.emptyList();
+        }
+
         private AccessibilityWindowInfo getPictureInPictureWindow() {
             if (mWindows != null) {
                 final int windowCount = mWindows.size();
@@ -3660,6 +3789,7 @@
         public ComponentName mServiceToEnableWithShortcut;
 
         public int mLastSentClientState = -1;
+        public int mMinimumUiTimeout = 0;
 
         private int mSoftKeyboardShowMode = 0;
 
@@ -3674,6 +3804,8 @@
         public boolean mIsPerformGesturesEnabled;
         public boolean mIsFilterKeyEventsEnabled;
         public boolean mAccessibilityFocusOnlyInActiveWindow;
+        public boolean mUserMinimumUiTimeoutEnabled;
+        public int mUserMinimumUiTimeout;
 
         public boolean mBindInstantServiceAllowed;
 
@@ -3713,6 +3845,9 @@
             // Clear event management state.
             mLastSentClientState = -1;
 
+            // clear minimum ui timeout
+            mMinimumUiTimeout = 0;
+
             // Clear state persisted in settings.
             mEnabledServices.clear();
             mTouchExplorationGrantedServices.clear();
@@ -3722,6 +3857,8 @@
             mServiceAssignedToAccessibilityButton = null;
             mIsNavBarMagnificationAssignedToAccessibilityButton = false;
             mIsAutoclickEnabled = false;
+            mUserMinimumUiTimeoutEnabled = false;
+            mUserMinimumUiTimeout = 0;
         }
 
         public void addServiceLocked(AccessibilityServiceConnection serviceConnection) {
@@ -3796,14 +3933,14 @@
          */
         public boolean setSoftKeyboardModeLocked(int newMode, @Nullable ComponentName requester) {
             if ((newMode != SHOW_MODE_AUTO) && (newMode != SHOW_MODE_HIDDEN)
-                    && (newMode != SHOW_MODE_WITH_HARD_KEYBOARD))
+                    && (newMode != SHOW_MODE_IGNORE_HARD_KEYBOARD))
             {
                 Slog.w(LOG_TAG, "Invalid soft keyboard mode");
                 return false;
             }
             if (mSoftKeyboardShowMode == newMode) return true;
 
-            if (newMode == SHOW_MODE_WITH_HARD_KEYBOARD) {
+            if (newMode == SHOW_MODE_IGNORE_HARD_KEYBOARD) {
                 if (hasUserOverriddenHardKeyboardSettingLocked()) {
                     // The user has specified a default for this setting
                     return false;
@@ -3811,13 +3948,13 @@
                 // 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) {
+                if (getSoftKeyboardValueFromSettings() != SHOW_MODE_IGNORE_HARD_KEYBOARD) {
                     setOriginalHardKeyboardValue(
                             Settings.Secure.getInt(mContext.getContentResolver(),
                                     Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD, 0) != 0);
                 }
                 putSecureIntForUser(Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD, 1, mUserId);
-            } else if (mSoftKeyboardShowMode == SHOW_MODE_WITH_HARD_KEYBOARD) {
+            } else if (mSoftKeyboardShowMode == SHOW_MODE_IGNORE_HARD_KEYBOARD) {
                 putSecureIntForUser(Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD,
                         getOriginalHardKeyboardValue() ? 1 : 0, mUserId);
             }
@@ -3837,7 +3974,7 @@
             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 (mSoftKeyboardShowMode == SHOW_MODE_IGNORE_HARD_KEYBOARD) {
                 if (!showWithHardKeyboardSettings) {
                     // The user has overridden the setting. Respect that and prevent further changes
                     // to this behavior.
@@ -3948,6 +4085,12 @@
         private final Uri mAccessibilityButtonComponentIdUri = Settings.Secure.getUriFor(
                 Settings.Secure.ACCESSIBILITY_BUTTON_TARGET_COMPONENT);
 
+        private final Uri mUserMinimumUiTimeoutEnabledUri = Settings.Secure.getUriFor(
+                Settings.Secure.ACCESSIBILITY_MINIMUM_UI_TIMEOUT_ENABLED);
+
+        private final Uri mUserMinimumUiTimeoutUri = Settings.Secure.getUriFor(
+                Settings.Secure.ACCESSIBILITY_MINIMUM_UI_TIMEOUT_MS);
+
         public AccessibilityContentObserver(Handler handler) {
             super(handler);
         }
@@ -3982,6 +4125,10 @@
                     mAccessibilityShortcutServiceIdUri, false, this, UserHandle.USER_ALL);
             contentResolver.registerContentObserver(
                     mAccessibilityButtonComponentIdUri, false, this, UserHandle.USER_ALL);
+            contentResolver.registerContentObserver(
+                    mUserMinimumUiTimeoutEnabledUri, false, this, UserHandle.USER_ALL);
+            contentResolver.registerContentObserver(
+                    mUserMinimumUiTimeoutUri, false, this, UserHandle.USER_ALL);
         }
 
         @Override
@@ -4032,6 +4179,11 @@
                     if (readAccessibilityButtonSettingsLocked(userState)) {
                         onUserStateChangedLocked(userState);
                     }
+                } else if (mUserMinimumUiTimeoutEnabledUri.equals(uri)
+                        || mUserMinimumUiTimeoutUri.equals(uri)) {
+                    if (readUserMinimumUiTimeoutSettingsLocked(userState)) {
+                        updateMinimumUiTimeoutLocked(userState);
+                    }
                 }
             }
         }
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 5b7332d..c9eb2d2 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -395,16 +395,42 @@
      * or {@code null} when not found on either of them.
      */
     @GuardedBy("mLock")
-    private AutofillValue findValueLocked(@NonNull AutofillId id) {
-        final ViewState state = mViewStates.get(id);
+    @Nullable
+    private AutofillValue findValueLocked(@NonNull AutofillId autofillId) {
+        final AutofillValue value = findValueFromThisSessionOnlyLocked(autofillId);
+        if (value != null) return value;
+
+        // TODO(b/113281366): rather than explicitly look for previous session, it might be better
+        // to merge the sessions when created (see note on mergePreviousSessionLocked())
+        final ArrayList<Session> previousSessions = mService.getPreviousSessionsLocked(this);
+        if (previousSessions != null) {
+            if (sDebug) {
+                Slog.d(TAG, "findValueLocked(): looking on " + previousSessions.size()
+                        + " previous sessions for autofillId " + autofillId);
+            }
+            for (int i = 0; i < previousSessions.size(); i++) {
+                final Session previousSession = previousSessions.get(i);
+                final AutofillValue previousValue = previousSession
+                        .findValueFromThisSessionOnlyLocked(autofillId);
+                if (previousValue != null) {
+                    return previousValue;
+                }
+            }
+        }
+        return null;
+    }
+
+    @Nullable
+    private AutofillValue findValueFromThisSessionOnlyLocked(@NonNull AutofillId autofillId) {
+        final ViewState state = mViewStates.get(autofillId);
         if (state == null) {
-            if (sDebug) Slog.d(TAG, "findValueLocked(): no view state for " + id);
+            if (sDebug) Slog.d(TAG, "findValueLocked(): no view state for " + autofillId);
             return null;
         }
         AutofillValue value = state.getCurrentValue();
         if (value == null) {
-            if (sDebug) Slog.d(TAG, "findValueLocked(): no current value for " + id);
-            value = getValueFromContextsLocked(id);
+            if (sDebug) Slog.d(TAG, "findValueLocked(): no current value for " + autofillId);
+            value = getValueFromContextsLocked(autofillId);
         }
         return value;
     }
@@ -1769,15 +1795,16 @@
      */
     @GuardedBy("mLock")
     @Nullable
-    private AutofillValue getValueFromContextsLocked(AutofillId id) {
+    private AutofillValue getValueFromContextsLocked(@NonNull AutofillId autofillId) {
         final int numContexts = mContexts.size();
         for (int i = numContexts - 1; i >= 0; i--) {
             final FillContext context = mContexts.get(i);
-            final ViewNode node = Helper.findViewNodeByAutofillId(context.getStructure(), id);
+            final ViewNode node = Helper.findViewNodeByAutofillId(context.getStructure(),
+                    autofillId);
             if (node != null) {
                 final AutofillValue value = node.getAutofillValue();
                 if (sDebug) {
-                    Slog.d(TAG, "getValueFromContexts(" + id + ") at " + i + ": " + value);
+                    Slog.d(TAG, "getValueFromContexts(" + autofillId + ") at " + i + ": " + value);
                 }
                 if (value != null && !value.isEmpty()) {
                     return value;
@@ -2954,11 +2981,13 @@
         mMetricsLogger.write(newLogMaker(category));
     }
 
+    @GuardedBy("mLock")
     private void logAuthenticationStatusLocked(int requestId, int status) {
         addTaggedDataToRequestLogLocked(requestId,
                 MetricsEvent.FIELD_AUTOFILL_AUTHENTICATION_STATUS, status);
     }
 
+    @GuardedBy("mLock")
     private void addTaggedDataToRequestLogLocked(int requestId, int tag, @Nullable Object value) {
         final LogMaker requestLog = mRequestLogs.get(requestId);
         if (requestLog == null) {
diff --git a/services/autofill/java/com/android/server/autofill/ViewState.java b/services/autofill/java/com/android/server/autofill/ViewState.java
index bb97e4a..e6cd7e0 100644
--- a/services/autofill/java/com/android/server/autofill/ViewState.java
+++ b/services/autofill/java/com/android/server/autofill/ViewState.java
@@ -212,20 +212,20 @@
     public String toString() {
         final StringBuilder builder = new StringBuilder("ViewState: [id=").append(id);
         if (mDatasetId != null) {
-            builder.append("datasetId:" ).append(mDatasetId);
+            builder.append(", datasetId:" ).append(mDatasetId);
         }
         builder.append("state:" ).append(getStateAsString());
         if (mCurrentValue != null) {
-            builder.append("currentValue:" ).append(mCurrentValue);
+            builder.append(", currentValue:" ).append(mCurrentValue);
         }
         if (mAutofilledValue != null) {
-            builder.append("autofilledValue:" ).append(mAutofilledValue);
+            builder.append(", autofilledValue:" ).append(mAutofilledValue);
         }
         if (mSanitizedValue != null) {
-            builder.append("sanitizedValue:" ).append(mSanitizedValue);
+            builder.append(", sanitizedValue:" ).append(mSanitizedValue);
         }
         if (mVirtualBounds != null) {
-            builder.append("virtualBounds:" ).append(mVirtualBounds);
+            builder.append(", virtualBounds:" ).append(mVirtualBounds);
         }
         return builder.toString();
     }
diff --git a/services/backup/java/com/android/server/backup/BackupAgentTimeoutParameters.java b/services/backup/java/com/android/server/backup/BackupAgentTimeoutParameters.java
index 49fa1cc..df46d260b 100644
--- a/services/backup/java/com/android/server/backup/BackupAgentTimeoutParameters.java
+++ b/services/backup/java/com/android/server/backup/BackupAgentTimeoutParameters.java
@@ -57,6 +57,10 @@
     public static final String SETTING_RESTORE_AGENT_FINISHED_TIMEOUT_MILLIS =
             "restore_agent_finished_timeout_millis";
 
+    @VisibleForTesting
+    public static final String SETTING_QUOTA_EXCEEDED_TIMEOUT_MILLIS =
+            "quota_exceeded_timeout_millis";
+
     // Default values
     @VisibleForTesting public static final long DEFAULT_KV_BACKUP_AGENT_TIMEOUT_MILLIS = 30 * 1000;
 
@@ -71,6 +75,9 @@
     @VisibleForTesting
     public static final long DEFAULT_RESTORE_AGENT_FINISHED_TIMEOUT_MILLIS = 30 * 1000;
 
+    @VisibleForTesting
+    public static final long DEFAULT_QUOTA_EXCEEDED_TIMEOUT_MILLIS = 3 * 1000;
+
     @GuardedBy("mLock")
     private long mKvBackupAgentTimeoutMillis;
 
@@ -86,6 +93,9 @@
     @GuardedBy("mLock")
     private long mRestoreAgentFinishedTimeoutMillis;
 
+    @GuardedBy("mLock")
+    private long mQuotaExceededTimeoutMillis;
+
     private final Object mLock = new Object();
 
     public BackupAgentTimeoutParameters(Handler handler, ContentResolver resolver) {
@@ -118,6 +128,10 @@
                     parser.getLong(
                             SETTING_RESTORE_AGENT_FINISHED_TIMEOUT_MILLIS,
                             DEFAULT_RESTORE_AGENT_FINISHED_TIMEOUT_MILLIS);
+            mQuotaExceededTimeoutMillis =
+                    parser.getLong(
+                            SETTING_QUOTA_EXCEEDED_TIMEOUT_MILLIS,
+                            DEFAULT_QUOTA_EXCEEDED_TIMEOUT_MILLIS);
         }
     }
 
@@ -170,4 +184,16 @@
             return mRestoreAgentFinishedTimeoutMillis;
         }
     }
+
+    public long getQuotaExceededTimeoutMillis() {
+        synchronized (mLock) {
+            if (BackupManagerService.DEBUG_SCHEDULING) {
+                Slog.v(
+                        TAG,
+                        "getQuotaExceededTimeoutMillis(): "
+                                + mQuotaExceededTimeoutMillis);
+            }
+            return mQuotaExceededTimeoutMillis;
+        }
+    }
 }
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index c26ac17..1b97926 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -698,8 +698,6 @@
     @GuardedBy("mQueueLock")
     private ArrayList<FullBackupEntry> mFullBackupQueue;
 
-    private BackupPolicyEnforcer mBackupPolicyEnforcer;
-
     // Utility: build a new random integer token. The low bits are the ordinal of the
     // operation for near-time uniqueness, and the upper bits are random for app-
     // side unpredictability.
@@ -899,8 +897,6 @@
 
         // Power management
         mWakelock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*backup*");
-
-        mBackupPolicyEnforcer = new BackupPolicyEnforcer(context);
     }
 
     private void initPackageTracking() {
@@ -2827,10 +2823,6 @@
     public void setBackupEnabled(boolean enable) {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP,
                 "setBackupEnabled");
-        if (!enable && mBackupPolicyEnforcer.getMandatoryBackupTransport() != null) {
-            Slog.w(TAG, "Cannot disable backups when the mandatory backups policy is active.");
-            return;
-        }
 
         Slog.i(TAG, "Backup enabled => " + enable);
 
@@ -3085,12 +3077,6 @@
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.BACKUP, "selectBackupTransport");
 
-        if (!isAllowedByMandatoryBackupTransportPolicy(transportName)) {
-            // Don't change the transport if it is not allowed.
-            Slog.w(TAG, "Failed to select transport - disallowed by device owner policy.");
-            return mTransportManager.getCurrentTransportName();
-        }
-
         final long oldId = Binder.clearCallingIdentity();
         try {
             String previousTransportName = mTransportManager.selectTransport(transportName);
@@ -3105,20 +3091,10 @@
 
     @Override
     public void selectBackupTransportAsync(
-            ComponentName transportComponent, @Nullable ISelectBackupTransportCallback listener) {
+            ComponentName transportComponent, ISelectBackupTransportCallback listener) {
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.BACKUP, "selectBackupTransportAsync");
-        if (!isAllowedByMandatoryBackupTransportPolicy(transportComponent)) {
-            try {
-                if (listener != null) {
-                    Slog.w(TAG, "Failed to select transport - disallowed by device owner policy.");
-                    listener.onFailure(BackupManager.ERROR_BACKUP_NOT_ALLOWED);
-                }
-            } catch (RemoteException e) {
-                Slog.e(TAG, "ISelectBackupTransportCallback listener not available");
-            }
-            return;
-        }
+
         final long oldId = Binder.clearCallingIdentity();
         try {
             String transportString = transportComponent.flattenToShortString();
@@ -3140,12 +3116,10 @@
                         }
 
                         try {
-                            if (listener != null) {
-                                if (transportName != null) {
-                                    listener.onSuccess(transportName);
-                                } else {
-                                    listener.onFailure(result);
-                                }
+                            if (transportName != null) {
+                                listener.onSuccess(transportName);
+                            } else {
+                                listener.onFailure(result);
                             }
                         } catch (RemoteException e) {
                             Slog.e(TAG, "ISelectBackupTransportCallback listener not available");
@@ -3156,38 +3130,6 @@
         }
     }
 
-    /**
-     * Returns if the specified transport can be set as the current transport without violating the
-     * mandatory backup transport policy.
-     */
-    private boolean isAllowedByMandatoryBackupTransportPolicy(String transportName) {
-        ComponentName mandatoryBackupTransport = mBackupPolicyEnforcer.getMandatoryBackupTransport();
-        if (mandatoryBackupTransport == null) {
-            return true;
-        }
-        final String mandatoryBackupTransportName;
-        try {
-            mandatoryBackupTransportName =
-                    mTransportManager.getTransportName(mandatoryBackupTransport);
-        } catch (TransportNotRegisteredException e) {
-            Slog.e(TAG, "mandatory backup transport not registered!");
-            return false;
-        }
-        return TextUtils.equals(mandatoryBackupTransportName, transportName);
-    }
-
-    /**
-     * Returns if the specified transport can be set as the current transport without violating the
-     * mandatory backup transport policy.
-     */
-    private boolean isAllowedByMandatoryBackupTransportPolicy(ComponentName transport) {
-        ComponentName mandatoryBackupTransport = mBackupPolicyEnforcer.getMandatoryBackupTransport();
-        if (mandatoryBackupTransport == null) {
-            return true;
-        }
-        return mandatoryBackupTransport.equals(transport);
-    }
-
     private void updateStateForTransport(String newTransportName) {
         // Publish the name change
         Settings.Secure.putString(mContext.getContentResolver(),
diff --git a/services/backup/java/com/android/server/backup/BackupPolicyEnforcer.java b/services/backup/java/com/android/server/backup/BackupPolicyEnforcer.java
deleted file mode 100644
index 158084a..0000000
--- a/services/backup/java/com/android/server/backup/BackupPolicyEnforcer.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.android.server.backup;
-
-import android.app.admin.DevicePolicyManager;
-import android.content.ComponentName;
-import android.content.Context;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-/**
- * A helper class to decouple this service from {@link DevicePolicyManager} in order to improve
- * testability.
- */
-@VisibleForTesting
-public class BackupPolicyEnforcer {
-    private DevicePolicyManager mDevicePolicyManager;
-
-    public BackupPolicyEnforcer(Context context) {
-        mDevicePolicyManager =
-                (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
-    }
-
-    public ComponentName getMandatoryBackupTransport() {
-        return mDevicePolicyManager.getMandatoryBackupTransport();
-    }
-}
diff --git a/services/backup/java/com/android/server/backup/KeyValueAdbBackupEngine.java b/services/backup/java/com/android/server/backup/KeyValueAdbBackupEngine.java
index 30ec8ab..125c225 100644
--- a/services/backup/java/com/android/server/backup/KeyValueAdbBackupEngine.java
+++ b/services/backup/java/com/android/server/backup/KeyValueAdbBackupEngine.java
@@ -9,9 +9,9 @@
 
 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.app.backup.IBackupCallback;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
@@ -21,6 +21,7 @@
 import android.util.Slog;
 
 import com.android.internal.util.Preconditions;
+import com.android.server.backup.fullbackup.AppMetadataBackupWriter;
 import com.android.server.backup.remote.ServiceBackupCallback;
 import com.android.server.backup.utils.FullBackupUtils;
 
@@ -202,16 +203,20 @@
         public void run() {
             try {
                 FullBackupDataOutput output = new FullBackupDataOutput(mPipe);
+                AppMetadataBackupWriter writer =
+                        new AppMetadataBackupWriter(output, mPackageManager);
 
                 if (DEBUG) {
                     Slog.d(TAG, "Writing manifest for " + mPackage.packageName);
                 }
-                FullBackupUtils.writeAppManifest(
-                        mPackage, mPackageManager, mManifestFile, false, false);
-                FullBackup.backupToTar(mPackage.packageName, FullBackup.KEY_VALUE_DATA_TOKEN, null,
-                        mDataDir.getAbsolutePath(),
-                        mManifestFile.getAbsolutePath(),
-                        output);
+
+                writer.backupManifest(
+                        mPackage,
+                        mManifestFile,
+                        mDataDir,
+                        FullBackup.KEY_VALUE_DATA_TOKEN,
+                        /* linkDomain */ null,
+                        /* withApk */ false);
                 mManifestFile.delete();
 
                 if (DEBUG) {
diff --git a/services/backup/java/com/android/server/backup/encryption/chunk/ChunkHash.java b/services/backup/java/com/android/server/backup/encryption/chunk/ChunkHash.java
new file mode 100644
index 0000000..1ae598e
--- /dev/null
+++ b/services/backup/java/com/android/server/backup/encryption/chunk/ChunkHash.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 com.android.server.backup.encryption.chunk;
+
+import com.android.internal.util.Preconditions;
+import java.util.Arrays;
+import java.util.Base64;
+
+/**
+ * Represents the SHA-256 hash of the plaintext of a chunk, which is frequently used as a key.
+ *
+ * <p>This class is {@link Comparable} and implements {@link #equals(Object)} and {@link
+ * #hashCode()}.
+ */
+public class ChunkHash implements Comparable<ChunkHash> {
+    /** The length of the hash in bytes. The hash is a SHA-256, so this is 256 bits. */
+    public static final int HASH_LENGTH_BYTES = 256 / 8;
+
+    private static final int UNSIGNED_MASK = 0xFF;
+
+    private final byte[] mHash;
+
+    /** Constructs a new instance which wraps the given SHA-256 hash bytes. */
+    public ChunkHash(byte[] hash) {
+        Preconditions.checkArgument(hash.length == HASH_LENGTH_BYTES, "Hash must have 256 bits");
+        mHash = hash;
+    }
+
+    public byte[] getHash() {
+        return mHash;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (!(o instanceof ChunkHash)) {
+            return false;
+        }
+
+        ChunkHash chunkHash = (ChunkHash) o;
+        return Arrays.equals(mHash, chunkHash.mHash);
+    }
+
+    @Override
+    public int hashCode() {
+        return Arrays.hashCode(mHash);
+    }
+
+    @Override
+    public int compareTo(ChunkHash other) {
+        return lexicographicalCompareUnsignedBytes(getHash(), other.getHash());
+    }
+
+    @Override
+    public String toString() {
+        return Base64.getEncoder().encodeToString(mHash);
+    }
+
+    private static int lexicographicalCompareUnsignedBytes(byte[] left, byte[] right) {
+        int minLength = Math.min(left.length, right.length);
+        for (int i = 0; i < minLength; i++) {
+            int result = toInt(left[i]) - toInt(right[i]);
+            if (result != 0) {
+                return result;
+            }
+        }
+        return left.length - right.length;
+    }
+
+    private static int toInt(byte value) {
+        return value & UNSIGNED_MASK;
+    }
+}
diff --git a/services/backup/java/com/android/server/backup/fullbackup/AppMetadataBackupWriter.java b/services/backup/java/com/android/server/backup/fullbackup/AppMetadataBackupWriter.java
new file mode 100644
index 0000000..94365d7
--- /dev/null
+++ b/services/backup/java/com/android/server/backup/fullbackup/AppMetadataBackupWriter.java
@@ -0,0 +1,283 @@
+package com.android.server.backup.fullbackup;
+
+import static com.android.server.backup.BackupManagerService.BACKUP_MANIFEST_VERSION;
+import static com.android.server.backup.BackupManagerService.BACKUP_METADATA_VERSION;
+import static com.android.server.backup.BackupManagerService.BACKUP_WIDGET_METADATA_TOKEN;
+import static com.android.server.backup.BackupManagerService.MORE_DEBUG;
+import static com.android.server.backup.BackupManagerService.TAG;
+
+import android.annotation.Nullable;
+import android.app.backup.FullBackup;
+import android.app.backup.FullBackupDataOutput;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.Signature;
+import android.content.pm.SigningInfo;
+import android.os.Build;
+import android.os.Environment;
+import android.os.UserHandle;
+import android.util.Log;
+import android.util.StringBuilderPrinter;
+
+import com.android.internal.util.Preconditions;
+
+import java.io.BufferedOutputStream;
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+/**
+ * Writes the backup of app-specific metadata to {@link FullBackupDataOutput}. This data is not
+ * backed up by the app's backup agent and is written before the agent writes its own data. This
+ * includes the app's:
+ *
+ * <ul>
+ *   <li>manifest
+ *   <li>widget data
+ *   <li>apk
+ *   <li>obb content
+ * </ul>
+ */
+// TODO(b/113807190): Fix or remove apk and obb implementation (only used for adb).
+public class AppMetadataBackupWriter {
+    private final FullBackupDataOutput mOutput;
+    private final PackageManager mPackageManager;
+
+    /** The destination of the backup is specified by {@code output}. */
+    public AppMetadataBackupWriter(FullBackupDataOutput output, PackageManager packageManager) {
+        mOutput = output;
+        mPackageManager = packageManager;
+    }
+
+    /**
+     * Back up the app's manifest without specifying a pseudo-directory for the TAR stream.
+     *
+     * @see #backupManifest(PackageInfo, File, File, String, String, boolean)
+     */
+    public void backupManifest(
+            PackageInfo packageInfo, File manifestFile, File filesDir, boolean withApk)
+            throws IOException {
+        backupManifest(
+                packageInfo,
+                manifestFile,
+                filesDir,
+                /* domain */ null,
+                /* linkDomain */ null,
+                withApk);
+    }
+
+    /**
+     * Back up the app's manifest.
+     *
+     * <ol>
+     *   <li>Write the app's manifest data to the specified temporary file {@code manifestFile}.
+     *   <li>Backup the file in TAR format to the backup destination {@link #mOutput}.
+     * </ol>
+     *
+     * <p>Note: {@code domain} and {@code linkDomain} are only used by adb to specify a
+     * pseudo-directory for the TAR stream.
+     */
+    // TODO(b/113806991): Look into streaming the backup data directly.
+    public void backupManifest(
+            PackageInfo packageInfo,
+            File manifestFile,
+            File filesDir,
+            @Nullable String domain,
+            @Nullable String linkDomain,
+            boolean withApk)
+            throws IOException {
+        byte[] manifestBytes = getManifestBytes(packageInfo, withApk);
+        FileOutputStream outputStream = new FileOutputStream(manifestFile);
+        outputStream.write(manifestBytes);
+        outputStream.close();
+
+        // We want the manifest block in the archive stream to be constant each time we generate
+        // a backup stream for the app. However, the underlying TAR mechanism sees it as a file and
+        // will propagate its last modified time. We pin the last modified time to zero to prevent
+        // the TAR header from varying.
+        manifestFile.setLastModified(0);
+
+        FullBackup.backupToTar(
+                packageInfo.packageName,
+                domain,
+                linkDomain,
+                filesDir.getAbsolutePath(),
+                manifestFile.getAbsolutePath(),
+                mOutput);
+    }
+
+    /**
+     * Gets the app's manifest as a byte array. All data are strings ending in LF.
+     *
+     * <p>The manifest format is:
+     *
+     * <pre>
+     *     BACKUP_MANIFEST_VERSION
+     *     package name
+     *     package version code
+     *     platform version code
+     *     installer package name (can be empty)
+     *     boolean (1 if archive includes .apk, otherwise 0)
+     *     # of signatures N
+     *     N* (signature byte array in ascii format per Signature.toCharsString())
+     * </pre>
+     */
+    private byte[] getManifestBytes(PackageInfo packageInfo, boolean withApk) {
+        String packageName = packageInfo.packageName;
+        StringBuilder builder = new StringBuilder(4096);
+        StringBuilderPrinter printer = new StringBuilderPrinter(builder);
+
+        printer.println(Integer.toString(BACKUP_MANIFEST_VERSION));
+        printer.println(packageName);
+        printer.println(Long.toString(packageInfo.getLongVersionCode()));
+        printer.println(Integer.toString(Build.VERSION.SDK_INT));
+
+        String installerName = mPackageManager.getInstallerPackageName(packageName);
+        printer.println((installerName != null) ? installerName : "");
+
+        printer.println(withApk ? "1" : "0");
+
+        // Write the signature block.
+        SigningInfo signingInfo = packageInfo.signingInfo;
+        if (signingInfo == null) {
+            printer.println("0");
+        } else {
+            // Retrieve the newest signatures to write.
+            // TODO (b/73988180) use entire signing history in case of rollbacks.
+            Signature[] signatures = signingInfo.getApkContentsSigners();
+            printer.println(Integer.toString(signatures.length));
+            for (Signature sig : signatures) {
+                printer.println(sig.toCharsString());
+            }
+        }
+        return builder.toString().getBytes();
+    }
+
+    /**
+     * Backup specified widget data. The widget data is prefaced by a metadata header.
+     *
+     * <ol>
+     *   <li>Write a metadata header to the specified temporary file {@code metadataFile}.
+     *   <li>Write widget data bytes to the same file.
+     *   <li>Backup the file in TAR format to the backup destination {@link #mOutput}.
+     * </ol>
+     *
+     * @throws IllegalArgumentException if the widget data provided is empty.
+     */
+    // TODO(b/113806991): Look into streaming the backup data directly.
+    public void backupWidget(
+            PackageInfo packageInfo, File metadataFile, File filesDir, byte[] widgetData)
+            throws IOException {
+        Preconditions.checkArgument(widgetData.length > 0, "Can't backup widget with no data.");
+
+        String packageName = packageInfo.packageName;
+        FileOutputStream fileOutputStream = new FileOutputStream(metadataFile);
+        BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
+        DataOutputStream dataOutputStream = new DataOutputStream(bufferedOutputStream);
+
+        byte[] metadata = getMetadataBytes(packageName);
+        bufferedOutputStream.write(metadata); // bypassing DataOutputStream
+        writeWidgetData(dataOutputStream, widgetData);
+        bufferedOutputStream.flush();
+        dataOutputStream.close();
+
+        // As with the manifest file, guarantee consistency of the archive metadata for the widget
+        // block by using a fixed last modified time on the metadata file.
+        metadataFile.setLastModified(0);
+
+        FullBackup.backupToTar(
+                packageName,
+                /* domain */ null,
+                /* linkDomain */ null,
+                filesDir.getAbsolutePath(),
+                metadataFile.getAbsolutePath(),
+                mOutput);
+    }
+
+    /**
+     * Gets the app's metadata as a byte array. All entries are strings ending in LF.
+     *
+     * <p>The metadata format is:
+     *
+     * <pre>
+     *     BACKUP_METADATA_VERSION
+     *     package name
+     * </pre>
+     */
+    private byte[] getMetadataBytes(String packageName) {
+        StringBuilder builder = new StringBuilder(512);
+        StringBuilderPrinter printer = new StringBuilderPrinter(builder);
+        printer.println(Integer.toString(BACKUP_METADATA_VERSION));
+        printer.println(packageName);
+        return builder.toString().getBytes();
+    }
+
+    /**
+     * Write a byte array of widget data to the specified output stream. All integers are binary in
+     * network byte order.
+     *
+     * <p>The widget data format:
+     *
+     * <pre>
+     *     4 : Integer token identifying the widget data blob.
+     *     4 : Integer size of the widget data.
+     *     N : Raw bytes of the widget data.
+     * </pre>
+     */
+    private void writeWidgetData(DataOutputStream out, byte[] widgetData) throws IOException {
+        out.writeInt(BACKUP_WIDGET_METADATA_TOKEN);
+        out.writeInt(widgetData.length);
+        out.write(widgetData);
+    }
+
+    /**
+     * Backup the app's .apk to the backup destination {@link #mOutput}. Currently only used for
+     * 'adb backup'.
+     */
+    // TODO(b/113807190): Investigate and potentially remove.
+    public void backupApk(PackageInfo packageInfo) {
+        // TODO: handle backing up split APKs
+        String appSourceDir = packageInfo.applicationInfo.getBaseCodePath();
+        String apkDir = new File(appSourceDir).getParent();
+        FullBackup.backupToTar(
+                packageInfo.packageName,
+                FullBackup.APK_TREE_TOKEN,
+                /* linkDomain */ null,
+                apkDir,
+                appSourceDir,
+                mOutput);
+    }
+
+    /**
+     * Backup the app's .obb files to the backup destination {@link #mOutput}. Currently only used
+     * for 'adb backup'.
+     */
+    // TODO(b/113807190): Investigate and potentially remove.
+    public void backupObb(PackageInfo packageInfo) {
+        // TODO: migrate this to SharedStorageBackup, since AID_SYSTEM doesn't have access to
+        // external storage.
+        // TODO: http://b/22388012
+        Environment.UserEnvironment userEnv =
+                new Environment.UserEnvironment(UserHandle.USER_SYSTEM);
+        File obbDir = userEnv.buildExternalStorageAppObbDirs(packageInfo.packageName)[0];
+        if (obbDir != null) {
+            if (MORE_DEBUG) {
+                Log.i(TAG, "obb dir: " + obbDir.getAbsolutePath());
+            }
+            File[] obbFiles = obbDir.listFiles();
+            if (obbFiles != null) {
+                String obbDirName = obbDir.getAbsolutePath();
+                for (File obb : obbFiles) {
+                    FullBackup.backupToTar(
+                            packageInfo.packageName,
+                            FullBackup.OBB_TREE_TOKEN,
+                            /* linkDomain */ null,
+                            obbDirName,
+                            obb.getAbsolutePath(),
+                            mOutput);
+                }
+            }
+        }
+    }
+}
diff --git a/services/backup/java/com/android/server/backup/fullbackup/FullBackupEngine.java b/services/backup/java/com/android/server/backup/fullbackup/FullBackupEngine.java
index 5694659..c9f7218 100644
--- a/services/backup/java/com/android/server/backup/fullbackup/FullBackupEngine.java
+++ b/services/backup/java/com/android/server/backup/fullbackup/FullBackupEngine.java
@@ -18,8 +18,6 @@
 
 import static com.android.server.backup.BackupManagerService.BACKUP_MANIFEST_FILENAME;
 import static com.android.server.backup.BackupManagerService.BACKUP_METADATA_FILENAME;
-import static com.android.server.backup.BackupManagerService.BACKUP_METADATA_VERSION;
-import static com.android.server.backup.BackupManagerService.BACKUP_WIDGET_METADATA_TOKEN;
 import static com.android.server.backup.BackupManagerService.DEBUG;
 import static com.android.server.backup.BackupManagerService.MORE_DEBUG;
 import static com.android.server.backup.BackupManagerService.OP_TYPE_BACKUP_WAIT;
@@ -29,46 +27,37 @@
 import android.app.ApplicationThreadConstants;
 import android.app.IBackupAgent;
 import android.app.backup.BackupTransport;
-import android.app.backup.FullBackup;
 import android.app.backup.FullBackupDataOutput;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
-import android.os.Environment.UserEnvironment;
+import android.content.pm.PackageManager;
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
 import android.os.UserHandle;
-import android.util.Log;
 import android.util.Slog;
-import android.util.StringBuilderPrinter;
 
 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.remote.RemoteCall;
 import com.android.server.backup.utils.FullBackupUtils;
 
-import java.io.BufferedOutputStream;
-import java.io.DataOutputStream;
 import java.io.File;
-import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.OutputStream;
 
 /**
- * Core logic for performing one package's full backup, gathering the tarball from the
- * application and emitting it to the designated OutputStream.
+ * Core logic for performing one package's full backup, gathering the tarball from the application
+ * and emitting it to the designated OutputStream.
  */
 public class FullBackupEngine {
-
     private BackupManagerService backupManagerService;
     OutputStream mOutput;
     FullBackupPreflight mPreflightHook;
     BackupRestoreTask mTimeoutMonitor;
     IBackupAgent mAgent;
-    File mFilesDir;
-    File mManifestFile;
-    File mMetadataFile;
     boolean mIncludeApks;
     PackageInfo mPkg;
     private final long mQuota;
@@ -77,79 +66,91 @@
     private final BackupAgentTimeoutParameters mAgentTimeoutParameters;
 
     class FullBackupRunner implements Runnable {
+        private final PackageManager mPackageManager;
+        private final PackageInfo mPackage;
+        private final IBackupAgent mAgent;
+        private final ParcelFileDescriptor mPipe;
+        private final int mToken;
+        private final boolean mIncludeApks;
+        private final File mFilesDir;
 
-        PackageInfo mPackage;
-        byte[] mWidgetData;
-        IBackupAgent mAgent;
-        ParcelFileDescriptor mPipe;
-        int mToken;
-        boolean mSendApk;
-        boolean mWriteManifest;
-
-        FullBackupRunner(PackageInfo pack, IBackupAgent agent, ParcelFileDescriptor pipe,
-                int token, boolean sendApk, boolean writeManifest, byte[] widgetData)
+        FullBackupRunner(
+                PackageInfo packageInfo,
+                IBackupAgent agent,
+                ParcelFileDescriptor pipe,
+                int token,
+                boolean includeApks)
                 throws IOException {
-            mPackage = pack;
-            mWidgetData = widgetData;
+            mPackageManager = backupManagerService.getPackageManager();
+            mPackage = packageInfo;
             mAgent = agent;
             mPipe = ParcelFileDescriptor.dup(pipe.getFileDescriptor());
             mToken = token;
-            mSendApk = sendApk;
-            mWriteManifest = writeManifest;
+            mIncludeApks = includeApks;
+            mFilesDir = new File("/data/system");
         }
 
         @Override
         public void run() {
             try {
-                FullBackupDataOutput output = new FullBackupDataOutput(
-                        mPipe, -1, mTransportFlags);
+                FullBackupDataOutput output =
+                        new FullBackupDataOutput(mPipe, /* quota */ -1, mTransportFlags);
+                AppMetadataBackupWriter appMetadataBackupWriter =
+                        new AppMetadataBackupWriter(output, mPackageManager);
 
-                if (mWriteManifest) {
-                    final boolean writeWidgetData = mWidgetData != null;
+                String packageName = mPackage.packageName;
+                boolean isSharedStorage = SHARED_BACKUP_AGENT_PACKAGE.equals(packageName);
+                boolean writeApk =
+                        shouldWriteApk(mPackage.applicationInfo, mIncludeApks, isSharedStorage);
+
+                if (!isSharedStorage) {
                     if (MORE_DEBUG) {
-                        Slog.d(TAG, "Writing manifest for " + mPackage.packageName);
+                        Slog.d(TAG, "Writing manifest for " + packageName);
                     }
-                    FullBackupUtils
-                            .writeAppManifest(mPackage, backupManagerService.getPackageManager(),
-                                    mManifestFile, mSendApk,
-                                    writeWidgetData);
-                    FullBackup.backupToTar(mPackage.packageName, null, null,
-                            mFilesDir.getAbsolutePath(),
-                            mManifestFile.getAbsolutePath(),
-                            output);
-                    mManifestFile.delete();
 
-                    // We only need to write a metadata file if we have widget data to stash
-                    if (writeWidgetData) {
-                        writeMetadata(mPackage, mMetadataFile, mWidgetData);
-                        FullBackup.backupToTar(mPackage.packageName, null, null,
-                                mFilesDir.getAbsolutePath(),
-                                mMetadataFile.getAbsolutePath(),
-                                output);
-                        mMetadataFile.delete();
+                    File manifestFile = new File(mFilesDir, BACKUP_MANIFEST_FILENAME);
+                    appMetadataBackupWriter.backupManifest(
+                            mPackage, manifestFile, mFilesDir, writeApk);
+                    manifestFile.delete();
+
+                    // Write widget data.
+                    // TODO: http://b/22388012
+                    byte[] widgetData =
+                            AppWidgetBackupBridge.getWidgetState(
+                                    packageName, UserHandle.USER_SYSTEM);
+                    if (widgetData != null && widgetData.length > 0) {
+                        File metadataFile = new File(mFilesDir, BACKUP_METADATA_FILENAME);
+                        appMetadataBackupWriter.backupWidget(
+                                mPackage, metadataFile, mFilesDir, widgetData);
+                        metadataFile.delete();
                     }
                 }
 
-                if (mSendApk) {
-                    writeApkToBackup(mPackage, output);
+                // TODO(b/113807190): Look into removing, only used for 'adb backup'.
+                if (writeApk) {
+                    appMetadataBackupWriter.backupApk(mPackage);
+                    appMetadataBackupWriter.backupObb(mPackage);
                 }
 
-                final boolean isSharedStorage =
-                        mPackage.packageName.equals(SHARED_BACKUP_AGENT_PACKAGE);
-                final long timeout = isSharedStorage ?
-                        mAgentTimeoutParameters.getSharedBackupAgentTimeoutMillis() :
-                        mAgentTimeoutParameters.getFullBackupAgentTimeoutMillis();
-
                 if (DEBUG) {
-                    Slog.d(TAG, "Calling doFullBackup() on " + mPackage.packageName);
+                    Slog.d(TAG, "Calling doFullBackup() on " + packageName);
                 }
-                backupManagerService
-                        .prepareOperationTimeout(mToken,
-                                timeout,
-                                mTimeoutMonitor /* in parent class */,
-                                OP_TYPE_BACKUP_WAIT);
-                mAgent.doFullBackup(mPipe, mQuota, mToken,
-                        backupManagerService.getBackupManagerBinder(), mTransportFlags);
+
+                long timeout =
+                        isSharedStorage
+                                ? mAgentTimeoutParameters.getSharedBackupAgentTimeoutMillis()
+                                : mAgentTimeoutParameters.getFullBackupAgentTimeoutMillis();
+                backupManagerService.prepareOperationTimeout(
+                        mToken,
+                        timeout,
+                        mTimeoutMonitor /* in parent class */,
+                        OP_TYPE_BACKUP_WAIT);
+                mAgent.doFullBackup(
+                        mPipe,
+                        mQuota,
+                        mToken,
+                        backupManagerService.getBackupManagerBinder(),
+                        mTransportFlags);
             } catch (IOException e) {
                 Slog.e(TAG, "Error running full backup for " + mPackage.packageName);
             } catch (RemoteException e) {
@@ -161,12 +162,33 @@
                 }
             }
         }
+
+        /**
+         * Don't write apks for forward-locked apps or system-bundled apps that are not upgraded.
+         */
+        private boolean shouldWriteApk(
+                ApplicationInfo applicationInfo, boolean includeApks, boolean isSharedStorage) {
+            boolean isForwardLocked =
+                    (applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK) != 0;
+            boolean isSystemApp = (applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
+            boolean isUpdatedSystemApp =
+                    (applicationInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0;
+            return includeApks
+                    && !isSharedStorage
+                    && !isForwardLocked
+                    && (!isSystemApp || isUpdatedSystemApp);
+        }
     }
 
-    public FullBackupEngine(BackupManagerService backupManagerService,
+    public FullBackupEngine(
+            BackupManagerService backupManagerService,
             OutputStream output,
-            FullBackupPreflight preflightHook, PackageInfo pkg,
-            boolean alsoApks, BackupRestoreTask timeoutMonitor, long quota, int opToken,
+            FullBackupPreflight preflightHook,
+            PackageInfo pkg,
+            boolean alsoApks,
+            BackupRestoreTask timeoutMonitor,
+            long quota,
+            int opToken,
             int transportFlags) {
         this.backupManagerService = backupManagerService;
         mOutput = output;
@@ -174,15 +196,13 @@
         mPkg = pkg;
         mIncludeApks = alsoApks;
         mTimeoutMonitor = timeoutMonitor;
-        mFilesDir = new File("/data/system");
-        mManifestFile = new File(mFilesDir, BACKUP_MANIFEST_FILENAME);
-        mMetadataFile = new File(mFilesDir, BACKUP_METADATA_FILENAME);
         mQuota = quota;
         mOpToken = opToken;
         mTransportFlags = transportFlags;
-        mAgentTimeoutParameters = Preconditions.checkNotNull(
-                backupManagerService.getAgentTimeoutParameters(),
-                "Timeout parameters cannot be null");
+        mAgentTimeoutParameters =
+                Preconditions.checkNotNull(
+                        backupManagerService.getAgentTimeoutParameters(),
+                        "Timeout parameters cannot be null");
     }
 
     public int preflightCheck() throws RemoteException {
@@ -212,27 +232,13 @@
             try {
                 pipes = ParcelFileDescriptor.createPipe();
 
-                ApplicationInfo app = mPkg.applicationInfo;
-                final boolean isSharedStorage =
-                        mPkg.packageName.equals(SHARED_BACKUP_AGENT_PACKAGE);
-                final boolean sendApk = mIncludeApks
-                        && !isSharedStorage
-                        && ((app.privateFlags & ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK) == 0)
-                        && ((app.flags & ApplicationInfo.FLAG_SYSTEM) == 0 ||
-                        (app.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0);
-
-                // TODO: http://b/22388012
-                byte[] widgetBlob = AppWidgetBackupBridge.getWidgetState(mPkg.packageName,
-                        UserHandle.USER_SYSTEM);
-
-                FullBackupRunner runner = new FullBackupRunner(mPkg, mAgent, pipes[1],
-                        mOpToken, sendApk, !isSharedStorage, widgetBlob);
-                pipes[1].close();   // the runner has dup'd it
+                FullBackupRunner runner =
+                        new FullBackupRunner(mPkg, mAgent, pipes[1], mOpToken, mIncludeApks);
+                pipes[1].close(); // the runner has dup'd it
                 pipes[1] = null;
                 Thread t = new Thread(runner, "app-data-runner");
                 t.start();
 
-                // Now pull data from the app and stuff it into the output
                 FullBackupUtils.routeSocketDataToOutput(pipes[0], mOutput);
 
                 if (!backupManagerService.waitUntilOperationComplete(mOpToken)) {
@@ -270,10 +276,12 @@
         return result;
     }
 
-    public void sendQuotaExceeded(final long backupDataBytes, final long quotaBytes) {
+    public void sendQuotaExceeded(long backupDataBytes, long quotaBytes) {
         if (initializeAgent()) {
             try {
-                mAgent.doQuotaExceeded(backupDataBytes, quotaBytes);
+                RemoteCall.execute(
+                        callback -> mAgent.doQuotaExceeded(backupDataBytes, quotaBytes, callback),
+                        mAgentTimeoutParameters.getQuotaExceededTimeoutMillis());
             } catch (RemoteException e) {
                 Slog.e(TAG, "Remote exception while telling agent about quota exceeded");
             }
@@ -285,84 +293,13 @@
             if (MORE_DEBUG) {
                 Slog.d(TAG, "Binding to full backup agent : " + mPkg.packageName);
             }
-            mAgent = backupManagerService.bindToAgentSynchronous(mPkg.applicationInfo,
-                    ApplicationThreadConstants.BACKUP_MODE_FULL);
+            mAgent =
+                    backupManagerService.bindToAgentSynchronous(
+                            mPkg.applicationInfo, ApplicationThreadConstants.BACKUP_MODE_FULL);
         }
         return mAgent != null;
     }
 
-    private void writeApkToBackup(PackageInfo pkg, FullBackupDataOutput output) {
-        // Forward-locked apps, system-bundled .apks, etc are filtered out before we get here
-        // TODO: handle backing up split APKs
-        final String appSourceDir = pkg.applicationInfo.getBaseCodePath();
-        final String apkDir = new File(appSourceDir).getParent();
-        FullBackup.backupToTar(pkg.packageName, FullBackup.APK_TREE_TOKEN, null,
-                apkDir, appSourceDir, output);
-
-        // TODO: migrate this to SharedStorageBackup, since AID_SYSTEM
-        // doesn't have access to external storage.
-
-        // Save associated .obb content if it exists and we did save the apk
-        // check for .obb and save those too
-        // TODO: http://b/22388012
-        final UserEnvironment userEnv = new UserEnvironment(UserHandle.USER_SYSTEM);
-        final File obbDir = userEnv.buildExternalStorageAppObbDirs(pkg.packageName)[0];
-        if (obbDir != null) {
-            if (MORE_DEBUG) {
-                Log.i(TAG, "obb dir: " + obbDir.getAbsolutePath());
-            }
-            File[] obbFiles = obbDir.listFiles();
-            if (obbFiles != null) {
-                final String obbDirName = obbDir.getAbsolutePath();
-                for (File obb : obbFiles) {
-                    FullBackup.backupToTar(pkg.packageName, FullBackup.OBB_TREE_TOKEN, null,
-                            obbDirName, obb.getAbsolutePath(), output);
-                }
-            }
-        }
-    }
-
-    // Widget metadata format. All header entries are strings ending in LF:
-    //
-    // Version 1 header:
-    //     BACKUP_METADATA_VERSION, currently "1"
-    //     package name
-    //
-    // File data (all integers are binary in network byte order)
-    // *N: 4 : integer token identifying which metadata blob
-    //     4 : integer size of this blob = N
-    //     N : raw bytes of this metadata blob
-    //
-    // Currently understood blobs (always in network byte order):
-    //
-    //     widgets : metadata token = 0x01FFED01 (BACKUP_WIDGET_METADATA_TOKEN)
-    //
-    // Unrecognized blobs are *ignored*, not errors.
-    private void writeMetadata(PackageInfo pkg, File destination, byte[] widgetData)
-            throws IOException {
-        StringBuilder b = new StringBuilder(512);
-        StringBuilderPrinter printer = new StringBuilderPrinter(b);
-        printer.println(Integer.toString(BACKUP_METADATA_VERSION));
-        printer.println(pkg.packageName);
-
-        FileOutputStream fout = new FileOutputStream(destination);
-        BufferedOutputStream bout = new BufferedOutputStream(fout);
-        DataOutputStream out = new DataOutputStream(bout);
-        bout.write(b.toString().getBytes());    // bypassing DataOutputStream
-
-        if (widgetData != null && widgetData.length > 0) {
-            out.writeInt(BACKUP_WIDGET_METADATA_TOKEN);
-            out.writeInt(widgetData.length);
-            out.write(widgetData);
-        }
-        bout.flush();
-        out.close();
-
-        // As with the manifest file, guarantee idempotence of the archive metadata
-        // for the widget block by using a fixed mtime on the transient file.
-        destination.setLastModified(0);
-    }
-
     private void tearDown() {
         if (mPkg != null) {
             backupManagerService.tearDownAgentAndKill(mPkg.applicationInfo);
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 f7c1c10..e108026 100644
--- a/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java
+++ b/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java
@@ -51,6 +51,7 @@
 import com.android.server.backup.TransportManager;
 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.transport.TransportClient;
 import com.android.server.backup.transport.TransportNotAvailableException;
 import com.android.server.backup.utils.AppBackupUtils;
@@ -739,7 +740,9 @@
                         Slog.d(TAG, "Package hit quota limit on preflight " +
                                 pkg.packageName + ": " + totalSize + " of " + mQuota);
                     }
-                    agent.doQuotaExceeded(totalSize, mQuota);
+                    RemoteCall.execute(
+                            callback -> agent.doQuotaExceeded(totalSize, mQuota, callback),
+                            mAgentTimeoutParameters.getQuotaExceededTimeoutMillis());
                 }
             } catch (Exception e) {
                 Slog.w(TAG, "Exception preflighting " + pkg.packageName + ": " + e.getMessage());
diff --git a/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupReporter.java b/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupReporter.java
index 8fbca4b..54e6b1d 100644
--- a/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupReporter.java
+++ b/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupReporter.java
@@ -26,6 +26,7 @@
 import android.util.EventLog;
 import android.util.Slog;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.server.EventLogTags;
 import com.android.server.backup.BackupManagerService;
 import com.android.server.backup.DataChangedJournal;
@@ -49,10 +50,17 @@
  */
 // 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";
+@VisibleForTesting
+public class KeyValueBackupReporter {
+    @VisibleForTesting static final String TAG = "KeyValueBackupTask";
     private static final boolean DEBUG = BackupManagerService.DEBUG;
-    private static final boolean MORE_DEBUG = BackupManagerService.MORE_DEBUG || true;
+    @VisibleForTesting static final boolean MORE_DEBUG = BackupManagerService.MORE_DEBUG || true;
+
+    static void onNewThread(String threadName) {
+        if (DEBUG) {
+            Slog.d(TAG, "Spinning thread " + threadName);
+        }
+    }
 
     private final BackupManagerService mBackupManagerService;
     private final IBackupObserver mObserver;
@@ -61,7 +69,7 @@
     KeyValueBackupReporter(
             BackupManagerService backupManagerService,
             IBackupObserver observer,
-            IBackupManagerMonitor monitor) {
+            @Nullable IBackupManagerMonitor monitor) {
         mBackupManagerService = backupManagerService;
         mObserver = observer;
         mMonitor = monitor;
@@ -73,6 +81,10 @@
         return mMonitor;
     }
 
+    IBackupObserver getObserver() {
+        return mObserver;
+    }
+
     void onSkipBackup() {
         if (DEBUG) {
             Slog.d(TAG, "Skipping backup since one is already in progress");
@@ -118,12 +130,6 @@
         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);
     }
@@ -237,10 +243,6 @@
         }
     }
 
-    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);
@@ -353,11 +355,19 @@
                                 null, BackupManagerMonitor.EXTRA_LOG_CANCEL_ALL, true));
     }
 
+    void onAgentResultError(@Nullable PackageInfo packageInfo) {
+        String packageName = getPackageName(packageInfo);
+        BackupObserverUtils.sendBackupOnPackageResult(
+                mObserver, packageName, BackupManager.ERROR_AGENT_FAILURE);
+        EventLog.writeEvent(EventLogTags.BACKUP_AGENT_FAILURE, packageName, "result error");
+        Slog.w(TAG, "Agent " + packageName + " error in onBackup()");
+    }
+
     private String getPackageName(@Nullable PackageInfo packageInfo) {
         return (packageInfo != null) ? packageInfo.packageName : "no_package_yet";
     }
 
-    void onRevertBackup() {
+    void onRevertTask() {
         if (MORE_DEBUG) {
             Slog.i(TAG, "Reverting backup queue, re-staging everything");
         }
@@ -367,9 +377,9 @@
         Slog.w(TAG, "Unable to contact transport for recommended backoff: " + e);
     }
 
-    void onRemoteCallReturned(RemoteResult result) {
+    void onRemoteCallReturned(RemoteResult result, String logIdentifier) {
         if (MORE_DEBUG) {
-            Slog.v(TAG, "Agent call returned " + result);
+            Slog.v(TAG, "Agent call " + logIdentifier + " returned " + result);
         }
     }
 
@@ -391,6 +401,10 @@
         Slog.w(TAG, "Failed to query transport name for pending init: " + e);
     }
 
+    /**
+     * This is a bit different from {@link #onTaskFinished()}, it's only called if there is no
+     * full-backup requests associated with the key-value task.
+     */
     void onBackupFinished(int status) {
         BackupObserverUtils.sendBackupFinished(mObserver, status);
     }
@@ -399,7 +413,7 @@
         Slog.d(TAG, "Starting full backups for: " + pendingFullBackups);
     }
 
-    void onKeyValueBackupFinished() {
+    void onTaskFinished() {
         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
index 91af6f1..e915ce1 100644
--- a/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java
+++ b/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java
@@ -24,7 +24,6 @@
 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;
@@ -48,11 +47,9 @@
 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.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.backup.IBackupTransport;
 import com.android.internal.util.Preconditions;
@@ -172,9 +169,6 @@
 // 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";
@@ -218,6 +212,8 @@
             List<String> pendingFullBackups,
             boolean userInitiated,
             boolean nonIncremental) {
+        KeyValueBackupReporter reporter =
+                new KeyValueBackupReporter(backupManagerService, observer, monitor);
         KeyValueBackupTask task =
                 new KeyValueBackupTask(
                         backupManagerService,
@@ -225,17 +221,14 @@
                         transportDirName,
                         queue,
                         dataChangedJournal,
-                        observer,
-                        monitor,
+                        reporter,
                         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();
+        KeyValueBackupReporter.onNewThread(thread.getName());
         return task;
     }
 
@@ -244,28 +237,29 @@
     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 File mStateDirectory;
+    private final File mDataDirectory;
     private final List<String> mOriginalQueue;
     private final List<String> mQueue;
     private final List<String> mPendingFullBackups;
+    private final Object mQueueLock;
     @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;
+    @Nullable private PerformFullTransportBackupTask mFullBackupTask;
+    @Nullable private IBackupAgent mAgent;
+    @Nullable private PackageInfo mCurrentPackage;
+    @Nullable private File mSavedStateFile;
+    @Nullable private File mBackupDataFile;
+    @Nullable private File mNewStateFile;
+    @Nullable private ParcelFileDescriptor mSavedState;
+    @Nullable private ParcelFileDescriptor mBackupData;
+    @Nullable private ParcelFileDescriptor mNewState;
 
     /**
      * This {@link ConditionVariable} is used to signal that the cancel operation has been
@@ -296,8 +290,7 @@
             String transportDirName,
             List<String> queue,
             @Nullable DataChangedJournal journal,
-            IBackupObserver observer,
-            @Nullable IBackupManagerMonitor monitor,
+            KeyValueBackupReporter reporter,
             OnTaskFinishedListener taskFinishedListener,
             List<String> pendingFullBackups,
             boolean userInitiated,
@@ -310,8 +303,7 @@
         // 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);
+        mReporter = reporter;
         mTaskFinishedListener = taskFinishedListener;
         mPendingFullBackups = pendingFullBackups;
         mUserInitiated = userInitiated;
@@ -320,8 +312,10 @@
                 Preconditions.checkNotNull(
                         backupManagerService.getAgentTimeoutParameters(),
                         "Timeout parameters cannot be null");
-        mStateDir = new File(backupManagerService.getBaseStateDir(), transportDirName);
+        mStateDirectory = new File(backupManagerService.getBaseStateDir(), transportDirName);
+        mDataDirectory = mBackupManagerService.getDataDir();
         mCurrentOpToken = backupManagerService.generateRandomIntegerToken();
+        mQueueLock = mBackupManagerService.getQueueLock();
     }
 
     private void registerTask() {
@@ -337,44 +331,45 @@
     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;
+        boolean processQueue = startTask();
+        while (processQueue && !mQueue.isEmpty() && !mCancelled) {
+            String packageName = mQueue.remove(0);
+            if (PM_PACKAGE.equals(packageName)) {
+                processQueue = backupPm();
+            } else {
+                processQueue = backupPackage(packageName);
             }
         }
-        finishBackup();
+        finishTask();
     }
 
-    private BackupState handleAgentResult(RemoteResult result) {
+    /** Returns whether to consume next queue package. */
+    private boolean handleAgentResult(@Nullable PackageInfo packageInfo, RemoteResult result) {
         if (result == RemoteResult.FAILED_THREAD_INTERRUPTED) {
             // Not an explicit cancel, we need to flag it.
             mCancelled = true;
-            handleAgentCancelled();
-            return BackupState.CANCELLED;
+            mReporter.onAgentCancelled(packageInfo);
+            cleanUpAgentForAgentError();
+            return false;
         }
         if (result == RemoteResult.FAILED_CANCELLED) {
-            handleAgentCancelled();
-            return BackupState.CANCELLED;
+            mReporter.onAgentCancelled(packageInfo);
+            cleanUpAgentForAgentError();
+            return false;
         }
         if (result == RemoteResult.FAILED_TIMED_OUT) {
-            handleAgentTimeout();
-            return BackupState.RUNNING_QUEUE;
+            mReporter.onAgentTimedOut(packageInfo);
+            cleanUpAgentForAgentError();
+            return true;
         }
-        Preconditions.checkState(result.succeeded());
-        return sendDataToTransport(result.get());
+        Preconditions.checkState(result.isPresent());
+        long agentResult = result.get();
+        if (agentResult == BackupAgent.RESULT_ERROR) {
+            mReporter.onAgentResultError(packageInfo);
+            cleanUpAgentForAgentError();
+            return true;
+        }
+        return sendDataToTransport();
     }
 
     @Override
@@ -383,53 +378,43 @@
     @Override
     public void operationComplete(long unusedResult) {}
 
-    private BackupState startBackup() {
-        synchronized (mBackupManagerService.getCurrentOpLock()) {
-            if (mBackupManagerService.isBackupOperationInProgress()) {
-                mReporter.onSkipBackup();
-                return BackupState.FINAL;
-            }
+    /** Returns whether to consume next queue package. */
+    private boolean startTask() {
+        if (mBackupManagerService.isBackupOperationInProgress()) {
+            mReporter.onSkipBackup();
+            return false;
         }
 
-        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);
+        // Unfortunately full backup task constructor registers the task with BMS, so we have to
+        // create it here instead of in our constructor.
+        mFullBackupTask = createFullBackupTask(mPendingFullBackups);
         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()) {
+        if (mQueue.isEmpty() && mPendingFullBackups.isEmpty()) {
             mReporter.onEmptyQueueAtStart();
-            return BackupState.FINAL;
+            return false;
         }
-
         // We only backup PM if it was explicitly in the queue or if it's incremental.
         boolean backupPm = mQueue.remove(PM_PACKAGE) || !mNonIncremental;
+        if (backupPm) {
+            mQueue.add(0, PM_PACKAGE);
+        } else {
+            mReporter.onSkipPm();
+        }
 
         mReporter.onQueueReady(mQueue);
-        File pmState = new File(mStateDir, PM_PACKAGE);
+        File pmState = new File(mStateDirectory, PM_PACKAGE);
         try {
-            IBackupTransport transport = mTransportClient.connectOrThrow("KVBT.startBackup()");
+            IBackupTransport transport = mTransportClient.connectOrThrow("KVBT.startTask()");
             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);
+                mBackupManagerService.resetBackupState(mStateDirectory);
                 mStatus = transport.initializeDevice();
                 mReporter.onTransportInitialized(mStatus);
             }
@@ -439,19 +424,30 @@
         }
 
         if (mStatus != BackupTransport.TRANSPORT_OK) {
-            mBackupManagerService.resetBackupState(mStateDir);
-            return BackupState.FINAL;
+            mBackupManagerService.resetBackupState(mStateDirectory);
+            return false;
         }
 
-        if (!backupPm) {
-            mReporter.onSkipPm();
-            return BackupState.RUNNING_QUEUE;
-        }
-
-        return BackupState.BACKUP_PM;
+        return true;
     }
 
-    private BackupState backupPm() {
+    private PerformFullTransportBackupTask createFullBackupTask(List<String> packages) {
+        return new PerformFullTransportBackupTask(
+                mBackupManagerService,
+                mTransportClient,
+                /* fullBackupRestoreObserver */ null,
+                packages.toArray(new String[packages.size()]),
+                /* updateSchedule */ false,
+                /* runningJob */ null,
+                new CountDownLatch(1),
+                mReporter.getObserver(),
+                mReporter.getMonitor(),
+                mTaskFinishedListener,
+                mUserInitiated);
+    }
+
+    /** Returns whether to consume next queue package. */
+    private boolean backupPm() {
         RemoteResult agentResult = null;
         try {
             mCurrentPackage = new PackageInfo();
@@ -459,10 +455,9 @@
 
             // 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()));
+            mAgent = IBackupAgent.Stub.asInterface(pmAgent.onBind());
+
+            Pair<Integer, RemoteResult> statusAndResult = extractAgentData(PM_PACKAGE, mAgent);
             mStatus = statusAndResult.first;
             agentResult = statusAndResult.second;
         } catch (Exception e) {
@@ -471,32 +466,20 @@
         }
 
         if (mStatus != BackupTransport.TRANSPORT_OK) {
-            mBackupManagerService.resetBackupState(mStateDir);
-            return BackupState.FINAL;
+            // In this case either extractAgentData() already made the agent clean-up or we haven't
+            // prepared the state for calling the agent, in either case we don't need to clean-up.
+            mBackupManagerService.resetBackupState(mStateDirectory);
+            return false;
         }
 
         Preconditions.checkNotNull(agentResult);
-        return handleAgentResult(agentResult);
+        return handleAgentResult(mCurrentPackage, 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);
+    /** Returns whether to consume next queue package. */
+    private boolean backupPackage(String packageName) {
         mReporter.onStartPackageBackup(packageName);
+        mStatus = BackupTransport.TRANSPORT_OK;
 
         // Verify that the requested app is eligible for key-value backup.
         RemoteResult agentResult = null;
@@ -508,19 +491,19 @@
                 // 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);
+                return true;
             }
 
             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);
+                return true;
             }
 
             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);
+                return true;
             }
 
             try {
@@ -530,7 +513,7 @@
                                 applicationInfo,
                                 ApplicationThreadConstants.BACKUP_MODE_INCREMENTAL);
                 if (agent != null) {
-                    mAgentBinder = agent;
+                    mAgent = agent;
                     Pair<Integer, RemoteResult> statusAndResult =
                             extractAgentData(packageName, agent);
                     mStatus = statusAndResult.first;
@@ -550,31 +533,33 @@
         }
 
         if (mStatus != BackupTransport.TRANSPORT_OK) {
-            mAgentBinder = null;
+            // In this case either extractAgentData() already made the agent clean-up or we haven't
+            // prepared the state for calling the agent, in either case we don't need to clean-up.
+            Preconditions.checkState(mAgent == null);
 
             if (mStatus == BackupTransport.AGENT_ERROR) {
                 mReporter.onAgentError(packageName);
                 mBackupManagerService.dataChangedImpl(packageName);
                 mStatus = BackupTransport.TRANSPORT_OK;
-                return Pair.create(BackupState.RUNNING_QUEUE, null);
+                return true;
             }
 
             if (mStatus == BackupTransport.AGENT_UNKNOWN) {
                 mReporter.onAgentUnknown(packageName);
                 mStatus = BackupTransport.TRANSPORT_OK;
-                return Pair.create(BackupState.RUNNING_QUEUE, null);
+                return true;
             }
 
             // Transport-level failure, re-enqueue everything.
-            revertBackup();
-            return Pair.create(BackupState.FINAL, null);
+            revertTask();
+            return false;
         }
 
-        // Success: caller will figure out the state based on call result
-        return Pair.create(null, agentResult);
+        Preconditions.checkNotNull(agentResult);
+        return handleAgentResult(mCurrentPackage, agentResult);
     }
 
-    private void finishBackup() {
+    private void finishTask() {
         // Mark packages that we couldn't backup as pending backup.
         for (String packageName : mQueue) {
             mBackupManagerService.dataChangedImpl(packageName);
@@ -586,7 +571,7 @@
             mReporter.onJournalDeleteFailed(mJournal);
         }
 
-        String callerLogString = "KVBT.finishBackup()";
+        String callerLogString = "KVBT.finishTask()";
 
         // If we succeeded and this is the first time we've done a backup, we can record the current
         // backup dataset token.
@@ -602,23 +587,16 @@
             }
         }
 
-        synchronized (mBackupManagerService.getQueueLock()) {
+        synchronized (mQueueLock) {
             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);
-                }
+                triggerTransportInitializationLocked();
             }
         }
 
         unregisterTask();
-        mReporter.onKeyValueBackupFinished();
+        mReporter.onTaskFinished();
 
         if (mCancelled) {
             // We acknowledge the cancel as soon as we unregister the task, allowing other backups
@@ -663,14 +641,25 @@
         }
     }
 
-    /** 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();
+    @GuardedBy("mQueueLock")
+    private void triggerTransportInitializationLocked() {
+        try {
+            IBackupTransport transport =
+                    mTransportClient.connectOrThrow("KVBT.triggerTransportInitializationLocked");
+            mBackupManagerService.getPendingInits().add(transport.name());
+            deletePmStateFile();
+            mBackupManagerService.backupNow();
+        } catch (Exception e) {
+            mReporter.onPendingInitializeTransportError(e);
+            mStatus = BackupTransport.TRANSPORT_ERROR;
         }
     }
 
+    /** Removes PM state, triggering initialization in the next key-value task. */
+    private void deletePmStateFile() {
+        new File(mStateDirectory, PM_PACKAGE).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,
@@ -679,12 +668,10 @@
     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);
+        File blankStateFile = new File(mStateDirectory, BLANK_STATE_FILE_NAME);
+        mSavedStateFile = new File(mStateDirectory, packageName);
+        mBackupDataFile = new File(mDataDirectory, packageName + STAGING_FILE_SUFFIX);
+        mNewStateFile = new File(mStateDirectory, packageName + NEW_STATE_FILE_SUFFIX);
         mReporter.onAgentFilesReady(mBackupDataFile);
 
         mSavedState = null;
@@ -694,6 +681,7 @@
         boolean callingAgent = false;
         final RemoteResult agentResult;
         try {
+            File savedStateFileForAgent = (mNonIncremental) ? blankStateFile : mSavedStateFile;
             // MODE_CREATE to make an empty file if necessary
             mSavedState = ParcelFileDescriptor.open(
                     savedStateFileForAgent, MODE_READ_ONLY | MODE_CREATE);
@@ -709,8 +697,6 @@
             IBackupTransport transport = mTransportClient.connectOrThrow("KVBT.extractAgentData()");
             long quota = transport.getBackupQuota(packageName, /* isFullBackup */ false);
             int transportFlags = transport.getTransportFlags();
-            long kvBackupAgentTimeoutMillis =
-                    mAgentTimeoutParameters.getKvBackupAgentTimeoutMillis();
 
             callingAgent = true;
             agentResult =
@@ -723,10 +709,11 @@
                                             quota,
                                             callback,
                                             transportFlags),
-                            kvBackupAgentTimeoutMillis);
+                            mAgentTimeoutParameters.getKvBackupAgentTimeoutMillis(),
+                            "doBackup()");
         } catch (Exception e) {
             mReporter.onCallAgentDoBackupError(packageName, callingAgent, e);
-            errorCleanup();
+            cleanUpAgentForAgentError();
             // TODO: Remove the check on callingAgent when RemoteCall supports local agent calls.
             int status =
                     callingAgent ? BackupTransport.AGENT_ERROR : BackupTransport.TRANSPORT_ERROR;
@@ -737,7 +724,7 @@
         return Pair.create(BackupTransport.TRANSPORT_OK, agentResult);
     }
 
-    private void failAgent(IBackupAgent agent, String message) {
+    private void agentFail(IBackupAgent agent, String message) {
         try {
             agent.fail(message);
         } catch (Exception e) {
@@ -767,7 +754,7 @@
             throws IOException {
         // TODO: http://b/22388012
         byte[] widgetState = AppWidgetBackupBridge.getWidgetState(pkgName, UserHandle.USER_SYSTEM);
-        File widgetFile = new File(mStateDir, pkgName + "_widget");
+        File widgetFile = new File(mStateDirectory, pkgName + "_widget");
         boolean priorStateExists = widgetFile.exists();
         if (!priorStateExists && widgetState == null) {
             return;
@@ -814,159 +801,148 @@
         }
     }
 
-    private BackupState sendDataToTransport(long agentResult) {
+    /** Returns whether to consume next queue package. */
+    private boolean sendDataToTransport() {
         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();
-                }
+            if (!validateBackupData(applicationInfo, mBackupDataFile)) {
+                cleanUpAgentForAgentError();
+                return true;
             }
-
             writingWidgetData = true;
-            writeWidgetPayloadIfAppropriate(fd, packageName);
+            writeWidgetPayloadIfAppropriate(mBackupData.getFileDescriptor(), 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();
-            }
+            cleanUpAgentForAgentError();
+            revertTask();
+            return false;
         }
 
-        clearAgentState();
+        boolean nonIncremental = mSavedStateFile.length() == 0;
+        long size = mBackupDataFile.length();
+        if (size > 0) {
+            try (ParcelFileDescriptor backupData =
+                         ParcelFileDescriptor.open(mBackupDataFile, MODE_READ_ONLY)) {
+                IBackupTransport transport =
+                        mTransportClient.connectOrThrow("KVBT.sendDataToTransport()");
+                mReporter.onSendDataToTransport(packageName);
+                int flags = getPerformBackupFlags(mUserInitiated, nonIncremental);
 
-        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;
-                }
-
+                mStatus = transport.performBackup(mCurrentPackage, backupData, flags);
                 if (mStatus == BackupTransport.TRANSPORT_OK) {
                     mStatus = transport.finishBackup();
                 }
-            } else {
-                mReporter.onEmptyData(mCurrentPackage);
+            } catch (Exception e) {
+                mReporter.onPackageBackupError(packageName, e);
+                mStatus = BackupTransport.TRANSPORT_ERROR;
             }
-
-            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;
+            mReporter.onEmptyData(mCurrentPackage);
+            mStatus = BackupTransport.TRANSPORT_OK;
         }
 
-        return nextState;
+        if (nonIncremental
+                && mStatus == BackupTransport.TRANSPORT_NON_INCREMENTAL_BACKUP_REQUIRED) {
+            mReporter.onNonIncrementalAndNonIncrementalRequired();
+            mStatus = BackupTransport.TRANSPORT_ERROR;
+        }
+
+
+        boolean processQueue = handleTransportStatus(mStatus, packageName, size);
+        // We might report quota exceeded to the agent in handleTransportStatus() above, so we
+        // only clean-up after it.
+        cleanUpAgentForTransportStatus(mStatus);
+        return processQueue;
+    }
+
+    /** Returns whether to consume next queue package. */
+    private boolean handleTransportStatus(int status, String packageName, long size) {
+        if (status == BackupTransport.TRANSPORT_OK) {
+            mReporter.onPackageBackupComplete(packageName, size);
+            return true;
+        }
+        if (status == BackupTransport.TRANSPORT_PACKAGE_REJECTED) {
+            mReporter.onPackageBackupRejected(packageName);
+            return true;
+        }
+        if (status == BackupTransport.TRANSPORT_NON_INCREMENTAL_BACKUP_REQUIRED) {
+            mReporter.onPackageBackupNonIncrementalRequired(mCurrentPackage);
+            // Immediately retry the current package.
+            mQueue.add(0, packageName);
+            return true;
+        }
+        if (status == BackupTransport.TRANSPORT_QUOTA_EXCEEDED) {
+            mReporter.onPackageBackupQuotaExceeded(packageName);
+            agentDoQuotaExceeded(mAgent, packageName, size);
+            return true;
+        }
+        // Any other error here indicates a transport-level failure.
+        mReporter.onPackageBackupTransportFailure(packageName);
+        revertTask();
+        return false;
+    }
+
+    private void agentDoQuotaExceeded(@Nullable IBackupAgent agent, String packageName, long size) {
+        if (agent != null) {
+            try {
+                IBackupTransport transport =
+                        mTransportClient.connectOrThrow("KVBT.agentDoQuotaExceeded()");
+                long quota = transport.getBackupQuota(packageName, false);
+                remoteCall(
+                        callback -> agent.doQuotaExceeded(size, quota, callback),
+                        mAgentTimeoutParameters.getQuotaExceededTimeoutMillis(),
+                        "doQuotaExceeded()");
+            } catch (Exception e) {
+                mReporter.onAgentDoQuotaExceededError(e);
+            }
+        }
+    }
+
+    /**
+     * For system apps and pseudo-apps always return {@code true}. For regular apps returns whether
+     * {@code backupDataFile} doesn't have any protected keys.
+     *
+     * <p>If the app has attempted to write any protected keys we also crash them.
+     */
+    private boolean validateBackupData(
+            @Nullable ApplicationInfo applicationInfo, File backupDataFile) throws IOException {
+        if (applicationInfo == null || (applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
+            // System apps and pseudo-apps can write what they want.
+            return true;
+        }
+        try (ParcelFileDescriptor backupData =
+                     ParcelFileDescriptor.open(backupDataFile, MODE_READ_ONLY)) {
+            BackupDataInput backupDataInput = new BackupDataInput(backupData.getFileDescriptor());
+            while (backupDataInput.readNextHeader()) {
+                String key = backupDataInput.getKey();
+                if (key != null && key.charAt(0) >= 0xff00) {
+                    mReporter.onAgentIllegalKey(mCurrentPackage, key);
+                    // Crash them if they wrote any protected keys.
+                    agentFail(mAgent, "Illegal backup key: " + key);
+                    return false;
+                }
+                backupDataInput.skipEntityData();
+            }
+        }
+        return true;
+    }
+
+    private int getPerformBackupFlags(boolean userInitiated, boolean nonIncremental) {
+        int userInitiatedFlag = userInitiated ? BackupTransport.FLAG_USER_INITIATED : 0;
+        int incrementalFlag =
+                nonIncremental
+                        ? BackupTransport.FLAG_NON_INCREMENTAL
+                        : BackupTransport.FLAG_INCREMENTAL;
+        return userInitiatedFlag | incrementalFlag;
     }
 
     /**
@@ -1013,22 +989,12 @@
         mCancelAcknowledged.block();
     }
 
-    private void handleAgentTimeout() {
-        mReporter.onAgentTimedOut(mCurrentPackage);
-        errorCleanup();
-    }
-
-    private void handleAgentCancelled() {
-        mReporter.onAgentCancelled(mCurrentPackage);
-        errorCleanup();
-    }
-
-    private void revertBackup() {
-        mReporter.onRevertBackup();
+    private void revertTask() {
+        mReporter.onRevertTask();
         long delay;
         try {
             IBackupTransport transport =
-                    mTransportClient.connectOrThrow("KVBT.revertBackup()");
+                    mTransportClient.connectOrThrow("KVBT.revertTask()");
             delay = transport.requestBackupTime();
         } catch (Exception e) {
             mReporter.onTransportRequestBackupTimeError(e);
@@ -1043,21 +1009,50 @@
         }
     }
 
-    private void errorCleanup() {
-        mBackupDataFile.delete();
-        mNewStateFile.delete();
-        clearAgentState();
+    /** Cleans-up after having called the agent. */
+    private void cleanUpAgentForTransportStatus(int status) {
+        updateFiles(status);
+        cleanUpAgent();
     }
 
-    private void clearAgentState() {
-        // Cleanup common to both success and failure cases.
+    /** Cleans-up if we failed to call the agent. */
+    private void cleanUpAgentForAgentError() {
+        mBackupDataFile.delete();
+        mNewStateFile.delete();
+        cleanUpAgent();
+    }
+
+    private void updateFiles(int status) {
+        switch (status) {
+            case BackupTransport.TRANSPORT_OK:
+                mBackupDataFile.delete();
+                mNewStateFile.renameTo(mSavedStateFile);
+                break;
+            case BackupTransport.TRANSPORT_NON_INCREMENTAL_BACKUP_REQUIRED:
+                mSavedStateFile.delete();
+                mBackupDataFile.delete();
+                mNewStateFile.delete();
+                break;
+            default:
+                // Includes:
+                // * BackupTransport.TRANSPORT_PACKAGE_REJECTED
+                // * BackupTransport.TRANSPORT_QUOTA_EXCEEDED
+                // * BackupTransport.TRANSPORT_ERROR
+                mBackupDataFile.delete();
+                mNewStateFile.delete();
+                break;
+        }
+    }
+
+    /** Cleans-up file-descriptors and unbinds agent. */
+    private void cleanUpAgent() {
+        mAgent = null;
         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;
-        }
+        mSavedState = null;
+        mBackupData = null;
+        mNewState = null;
 
         // For PM metadata (for which applicationInfo is null) there is no agent-bound state.
         if (mCurrentPackage.applicationInfo != null) {
@@ -1075,20 +1070,13 @@
         }
     }
 
-    private RemoteResult remoteCall(RemoteCallable<IBackupCallback> remoteCallable, long timeoutMs)
+    private RemoteResult remoteCall(
+            RemoteCallable<IBackupCallback> remoteCallable, long timeoutMs, String logIdentifier)
             throws RemoteException {
         mPendingCall = new RemoteCall(mCancelled, remoteCallable, timeoutMs);
         RemoteResult result = mPendingCall.call();
-        mReporter.onRemoteCallReturned(result);
+        mReporter.onRemoteCallReturned(result, logIdentifier);
         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
index 1445cc3..1ea4249 100644
--- a/services/backup/java/com/android/server/backup/remote/FutureBackupCallback.java
+++ b/services/backup/java/com/android/server/backup/remote/FutureBackupCallback.java
@@ -23,7 +23,7 @@
 
 /**
  * An implementation of {@link IBackupCallback} that completes the {@link CompletableFuture}
- * provided in the constructor with a successful {@link RemoteResult}.
+ * provided in the constructor with a present {@link RemoteResult}.
  */
 public class FutureBackupCallback extends IBackupCallback.Stub {
     private final CompletableFuture<RemoteResult> mFuture;
@@ -34,6 +34,6 @@
 
     @Override
     public void operationComplete(long result) throws RemoteException {
-        mFuture.complete(RemoteResult.successful(result));
+        mFuture.complete(RemoteResult.of(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
index ac84811..3af9e1d 100644
--- a/services/backup/java/com/android/server/backup/remote/RemoteCall.java
+++ b/services/backup/java/com/android/server/backup/remote/RemoteCall.java
@@ -44,6 +44,21 @@
  */
 // TODO: Kick-off callable in dedicated thread (because of local calls, which are synchronous)
 public class RemoteCall {
+    /**
+     * Creates a {@link RemoteCall} object with {@code callable} and {@code timeoutMs} and calls
+     * {@link #call()} on it immediately after.
+     *
+     * <p>Note that you won't be able to cancel the call, to do that construct an object regularly
+     * first, then use {@link #call()}.
+     *
+     * @see #RemoteCall(RemoteCallable, long)
+     * @see #call()
+     */
+    public static RemoteResult execute(RemoteCallable<IBackupCallback> callable, long timeoutMs)
+            throws RemoteException {
+        return new RemoteCall(callable, timeoutMs).call();
+    }
+
     private final RemoteCallable<IBackupCallback> mCallable;
     private final CompletableFuture<RemoteResult> mFuture;
     private final long mTimeoutMs;
@@ -83,7 +98,7 @@
      *
      * <ul>
      *   <li>The callback passed to {@link RemoteCallable} is called with the result. We return a
-     *       successful {@link RemoteResult} with the result.
+     *       present {@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}.
diff --git a/services/backup/java/com/android/server/backup/remote/RemoteResult.java b/services/backup/java/com/android/server/backup/remote/RemoteResult.java
index 7f4f469..63c79db 100644
--- a/services/backup/java/com/android/server/backup/remote/RemoteResult.java
+++ b/services/backup/java/com/android/server/backup/remote/RemoteResult.java
@@ -29,7 +29,7 @@
  * #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
+ * <p>Use {@link #isPresent()} to check for successful result, or direct identity comparison to
  * check for specific failures, like {@code result == RemoteResult.FAILED_CANCELLED}.
  */
 public class RemoteResult {
@@ -38,7 +38,7 @@
     public static final RemoteResult FAILED_THREAD_INTERRUPTED =
             new RemoteResult(Type.FAILED_THREAD_INTERRUPTED, 0);
 
-    public static RemoteResult successful(long value) {
+    public static RemoteResult of(long value) {
         return new RemoteResult(Type.SUCCESS, value);
     }
 
@@ -50,7 +50,7 @@
         mValue = value;
     }
 
-    public boolean succeeded() {
+    public boolean isPresent() {
         return mType == Type.SUCCESS;
     }
 
@@ -60,7 +60,7 @@
      * @throws IllegalStateException in case this is not a successful result.
      */
     public long get() {
-        Preconditions.checkState(succeeded(), "Can't obtain value of failed result");
+        Preconditions.checkState(isPresent(), "Can't obtain value of failed result");
         return mValue;
     }
 
@@ -79,8 +79,9 @@
                 return "FAILED_CANCELLED";
             case Type.FAILED_THREAD_INTERRUPTED:
                 return "FAILED_THREAD_INTERRUPTED";
+            default:
+                throw new AssertionError("Unknown type");
         }
-        throw new AssertionError("Unknown type");
     }
 
     @Override
diff --git a/services/backup/java/com/android/server/backup/utils/FullBackupUtils.java b/services/backup/java/com/android/server/backup/utils/FullBackupUtils.java
index a3d5601..dbe3cd9 100644
--- a/services/backup/java/com/android/server/backup/utils/FullBackupUtils.java
+++ b/services/backup/java/com/android/server/backup/utils/FullBackupUtils.java
@@ -16,23 +16,14 @@
 
 package com.android.server.backup.utils;
 
-import static com.android.server.backup.BackupManagerService.BACKUP_MANIFEST_VERSION;
 import static com.android.server.backup.BackupManagerService.TAG;
 
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.Signature;
-import android.content.pm.SigningInfo;
-import android.os.Build;
 import android.os.ParcelFileDescriptor;
 import android.util.Slog;
-import android.util.StringBuilderPrinter;
 
 import java.io.DataInputStream;
 import java.io.EOFException;
-import java.io.File;
 import java.io.FileInputStream;
-import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.OutputStream;
 
@@ -68,67 +59,4 @@
             }
         }
     }
-
-    /**
-     * Writes app manifest to the given manifest file.
-     *
-     * @param pkg - app package, which manifest to write.
-     * @param packageManager - {@link PackageManager} instance.
-     * @param manifestFile - target manifest file.
-     * @param withApk - whether include apk or not.
-     * @param withWidgets - whether to write widgets data.
-     * @throws IOException - in case of an error.
-     */
-    // TODO: withWidgets is not used, decide whether it is needed.
-    public static void writeAppManifest(PackageInfo pkg, PackageManager packageManager,
-            File manifestFile, boolean withApk, boolean withWidgets) throws IOException {
-        // Manifest format. All data are strings ending in LF:
-        //     BACKUP_MANIFEST_VERSION, currently 1
-        //
-        // Version 1:
-        //     package name
-        //     package's versionCode
-        //     platform versionCode
-        //     getInstallerPackageName() for this package (maybe empty)
-        //     boolean: "1" if archive includes .apk; any other string means not
-        //     number of signatures == N
-        // N*:    signature byte array in ascii format per Signature.toCharsString()
-        StringBuilder builder = new StringBuilder(4096);
-        StringBuilderPrinter printer = new StringBuilderPrinter(builder);
-
-        printer.println(Integer.toString(BACKUP_MANIFEST_VERSION));
-        printer.println(pkg.packageName);
-        printer.println(Long.toString(pkg.getLongVersionCode()));
-        printer.println(Integer.toString(Build.VERSION.SDK_INT));
-
-        String installerName = packageManager.getInstallerPackageName(pkg.packageName);
-        printer.println((installerName != null) ? installerName : "");
-
-        printer.println(withApk ? "1" : "0");
-
-        // write the signature block
-        SigningInfo signingInfo = pkg.signingInfo;
-        if (signingInfo == null) {
-            printer.println("0");
-        } else {
-            // retrieve the newest sigs to write
-            // TODO (b/73988180) use entire signing history in case of rollbacks
-            Signature[] signatures = signingInfo.getApkContentsSigners();
-            printer.println(Integer.toString(signatures.length));
-            for (Signature sig : signatures) {
-                printer.println(sig.toCharsString());
-            }
-        }
-
-        FileOutputStream outstream = new FileOutputStream(manifestFile);
-        outstream.write(builder.toString().getBytes());
-        outstream.close();
-
-        // We want the manifest block in the archive stream to be idempotent:
-        // each time we generate a backup stream for the app, we want the manifest
-        // block to be identical.  The underlying tar mechanism sees it as a file,
-        // though, and will propagate its mtime, causing the tar header to vary.
-        // Avoid this problem by pinning the mtime to zero.
-        manifestFile.setLastModified(0);
-    }
 }
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index 26ef42f..ad2f82c 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -52,6 +52,7 @@
 import android.os.Environment;
 import android.os.Handler;
 import android.os.IBinder;
+import android.os.Looper;
 import android.os.Message;
 import android.os.ParcelableException;
 import android.os.PowerManager;
@@ -80,6 +81,7 @@
 import android.util.SparseArray;
 import android.util.SparseBooleanArray;
 import android.util.SparseLongArray;
+import android.util.StatsLog;
 import android.util.TimeUtils;
 import android.util.proto.ProtoOutputStream;
 
@@ -111,7 +113,7 @@
 import java.util.function.Predicate;
 
 /**
- * Alarm manager implementaion.
+ * Alarm manager implementation.
  *
  * Unit test:
  atest $ANDROID_BUILD_TOP/frameworks/base/services/tests/servicestests/src/com/android/server/AlarmManagerServiceTest.java
@@ -138,7 +140,6 @@
     static final boolean DEBUG_STANDBY = localLOGV || false;
     static final boolean RECORD_ALARMS_IN_HISTORY = true;
     static final boolean RECORD_DEVICE_IDLE_ALARMS = false;
-    static final int ALARM_EVENT = 1;
     static final String TIMEZONE_PROPERTY = "persist.sys.timezone";
 
     // Indices into the APP_STANDBY_MIN_DELAYS and KEYS_APP_STANDBY_DELAY arrays
@@ -169,7 +170,6 @@
 
     // List of alarms per uid deferred due to user applied background restrictions on the source app
     SparseArray<ArrayList<Alarm>> mPendingBackgroundAlarms = new SparseArray<>();
-    long mNativeData;
     private long mNextWakeup;
     private long mNextNonWakeup;
     private long mNextWakeUpSetAt;
@@ -181,15 +181,14 @@
     private long mLastTickReceived;
     private long mLastTickAdded;
     private long mLastTickRemoved;
+    private final Injector mInjector;
     int mBroadcastRefCount = 0;
     PowerManager.WakeLock mWakeLock;
     boolean mLastWakeLockUnimportantForLogging;
     ArrayList<Alarm> mPendingNonWakeupAlarms = new ArrayList<>();
     ArrayList<InFlight> mInFlight = new ArrayList<>();
-    final AlarmHandler mHandler = new AlarmHandler();
+    AlarmHandler mHandler;
     ClockReceiver mClockReceiver;
-    InteractiveStateReceiver mInteractiveStateReceiver;
-    private UninstallReceiver mUninstallReceiver;
     final DeliveryTracker mDeliveryTracker = new DeliveryTracker();
     PendingIntent mTimeTickSender;
     PendingIntent mDateChangeSender;
@@ -277,7 +276,8 @@
      * global Settings. Any access to this class or its fields should be done while
      * holding the AlarmManagerService.mLock lock.
      */
-    private final class Constants extends ContentObserver {
+    @VisibleForTesting
+    final class Constants extends ContentObserver {
         // Key names stored in the settings value.
         private static final String KEY_MIN_FUTURITY = "min_futurity";
         private static final String KEY_MIN_INTERVAL = "min_interval";
@@ -456,7 +456,7 @@
         }
     }
 
-    final Constants mConstants;
+    Constants mConstants;
 
     // Alarm delivery ordering bookkeeping
     static final int PRIO_TICK = 0;
@@ -510,7 +510,7 @@
             flags = seed.flags;
             alarms.add(seed);
             if (seed.operation == mTimeTickSender) {
-                mLastTickAdded = System.currentTimeMillis();
+                mLastTickAdded = mInjector.getCurrentTimeMillis();
             }
         }
 
@@ -535,7 +535,7 @@
             }
             alarms.add(index, alarm);
             if (alarm.operation == mTimeTickSender) {
-                mLastTickAdded = System.currentTimeMillis();
+                mLastTickAdded = mInjector.getCurrentTimeMillis();
             }
             if (DEBUG_BATCH) {
                 Slog.v(TAG, "Adding " + alarm + " to " + this);
@@ -573,7 +573,7 @@
                         mNextAlarmClockMayChange = true;
                     }
                     if (alarm.operation == mTimeTickSender) {
-                        mLastTickRemoved = System.currentTimeMillis();
+                        mLastTickRemoved = mInjector.getCurrentTimeMillis();
                     }
                 } else {
                     if (alarm.whenElapsed > newStart) {
@@ -734,17 +734,20 @@
     Alarm mNextWakeFromIdle = null;
     ArrayList<Alarm> mPendingWhileIdleAlarms = new ArrayList<>();
 
-    public AlarmManagerService(Context context) {
+    @VisibleForTesting
+    AlarmManagerService(Context context, Injector injector) {
         super(context);
-        mConstants = new Constants(mHandler);
-
-        publishLocalService(AlarmManagerInternal.class, new LocalService());
+        mInjector = injector;
     }
 
-    static long convertToElapsed(long when, int type) {
+    AlarmManagerService(Context context) {
+        this(context, new Injector(context));
+    }
+
+    private long convertToElapsed(long when, int type) {
         final boolean isRtc = (type == RTC || type == RTC_WAKEUP);
         if (isRtc) {
-            when -= System.currentTimeMillis() - SystemClock.elapsedRealtime();
+            when -= mInjector.getCurrentTimeMillis() - mInjector.getElapsedRealtime();
         }
         return when;
     }
@@ -854,7 +857,7 @@
         ArrayList<Batch> oldSet = (ArrayList<Batch>) mAlarmBatches.clone();
         mAlarmBatches.clear();
         Alarm oldPendingIdleUntil = mPendingIdleUntil;
-        final long nowElapsed = SystemClock.elapsedRealtime();
+        final long nowElapsed = mInjector.getElapsedRealtime();
         final int oldBatches = oldSet.size();
         for (int batchNum = 0; batchNum < oldBatches; batchNum++) {
             Batch batch = oldSet.get(batchNum);
@@ -984,7 +987,7 @@
             alarmsToDeliver = alarmsForUid;
             mPendingBackgroundAlarms.remove(uid);
         }
-        deliverPendingBackgroundAlarmsLocked(alarmsToDeliver, SystemClock.elapsedRealtime());
+        deliverPendingBackgroundAlarmsLocked(alarmsToDeliver, mInjector.getElapsedRealtime());
     }
 
     /**
@@ -1001,7 +1004,7 @@
                 mPendingBackgroundAlarms, alarmsToDeliver, this::isBackgroundRestricted);
 
         if (alarmsToDeliver.size() > 0) {
-            deliverPendingBackgroundAlarmsLocked(alarmsToDeliver, SystemClock.elapsedRealtime());
+            deliverPendingBackgroundAlarmsLocked(alarmsToDeliver, mInjector.getElapsedRealtime());
         }
     }
 
@@ -1088,7 +1091,7 @@
             IdleDispatchEntry ent = new IdleDispatchEntry();
             ent.uid = 0;
             ent.pkg = "FINISH IDLE";
-            ent.elapsedRealtime = SystemClock.elapsedRealtime();
+            ent.elapsedRealtime = mInjector.getElapsedRealtime();
             mAllowWhileIdleDispatches.add(ent);
         }
 
@@ -1096,7 +1099,7 @@
         if (mPendingWhileIdleAlarms.size() > 0) {
             ArrayList<Alarm> alarms = mPendingWhileIdleAlarms;
             mPendingWhileIdleAlarms = new ArrayList<>();
-            final long nowElapsed = SystemClock.elapsedRealtime();
+            final long nowElapsed = mInjector.getElapsedRealtime();
             for (int i=alarms.size() - 1; i >= 0; i--) {
                 Alarm a = alarms.get(i);
                 reAddAlarmLocked(a, nowElapsed, false);
@@ -1282,121 +1285,114 @@
 
     @Override
     public void onStart() {
-        mNativeData = init();
-        mNextWakeup = mNextNonWakeup = 0;
+        mInjector.init();
 
-        // We have to set current TimeZone info to kernel
-        // because kernel doesn't keep this after reboot
-        setTimeZoneImpl(SystemProperties.get(TIMEZONE_PROPERTY));
+        synchronized (mLock) {
+            mHandler = new AlarmHandler(Looper.myLooper());
+            mConstants = new Constants(mHandler);
 
-        // Also sure that we're booting with a halfway sensible current time
-        if (mNativeData != 0) {
+            mNextWakeup = mNextNonWakeup = 0;
+
+            // We have to set current TimeZone info to kernel
+            // because kernel doesn't keep this after reboot
+            setTimeZoneImpl(SystemProperties.get(TIMEZONE_PROPERTY));
+
+            // Also sure that we're booting with a halfway sensible current time
             final long systemBuildTime = Environment.getRootDirectory().lastModified();
-            if (System.currentTimeMillis() < systemBuildTime) {
-                Slog.i(TAG, "Current time only " + System.currentTimeMillis()
+            if (mInjector.getCurrentTimeMillis() < systemBuildTime) {
+                Slog.i(TAG, "Current time only " + mInjector.getCurrentTimeMillis()
                         + ", advancing to build time " + systemBuildTime);
-                setKernelTime(mNativeData, systemBuildTime);
+                mInjector.setKernelTime(systemBuildTime);
             }
-        }
 
-        // Determine SysUI's uid
-        final PackageManager packMan = getContext().getPackageManager();
-        try {
-            PermissionInfo sysUiPerm = packMan.getPermissionInfo(SYSTEM_UI_SELF_PERMISSION, 0);
-            ApplicationInfo sysUi = packMan.getApplicationInfo(sysUiPerm.packageName, 0);
-            if ((sysUi.privateFlags&ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0) {
-                mSystemUiUid = sysUi.uid;
+            // Determine SysUI's uid
+            mSystemUiUid = mInjector.getSystemUiUid();
+            if (mSystemUiUid <= 0) {
+                Slog.wtf(TAG, "SysUI package not found!");
+            }
+            mWakeLock = mInjector.getAlarmWakeLock();
+
+            mTimeTickSender = PendingIntent.getBroadcastAsUser(getContext(), 0,
+                    new Intent(Intent.ACTION_TIME_TICK).addFlags(
+                            Intent.FLAG_RECEIVER_REGISTERED_ONLY
+                                    | Intent.FLAG_RECEIVER_FOREGROUND
+                                    | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS), 0,
+                    UserHandle.ALL);
+            Intent intent = new Intent(Intent.ACTION_DATE_CHANGED);
+            intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
+                    | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
+            mDateChangeSender = PendingIntent.getBroadcastAsUser(getContext(), 0, intent,
+                    Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT, UserHandle.ALL);
+
+            mClockReceiver = mInjector.getClockReceiver(this);
+            new InteractiveStateReceiver();
+            new UninstallReceiver();
+
+            if (mInjector.isAlarmDriverPresent()) {
+                AlarmThread waitThread = new AlarmThread();
+                waitThread.start();
             } else {
-                Slog.e(TAG, "SysUI permission " + SYSTEM_UI_SELF_PERMISSION
-                        + " defined by non-privileged app " + sysUi.packageName
-                        + " - ignoring");
+                Slog.w(TAG, "Failed to open alarm driver. Falling back to a handler.");
             }
-        } catch (NameNotFoundException e) {
+
+            try {
+                ActivityManager.getService().registerUidObserver(new UidObserver(),
+                        ActivityManager.UID_OBSERVER_GONE | ActivityManager.UID_OBSERVER_IDLE
+                                | ActivityManager.UID_OBSERVER_ACTIVE,
+                        ActivityManager.PROCESS_STATE_UNKNOWN, null);
+            } catch (RemoteException e) {
+                // ignored; both services live in system_server
+            }
         }
-
-        if (mSystemUiUid <= 0) {
-            Slog.wtf(TAG, "SysUI package not found!");
-        }
-
-        PowerManager pm = (PowerManager) getContext().getSystemService(Context.POWER_SERVICE);
-        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*alarm*");
-
-        mTimeTickSender = PendingIntent.getBroadcastAsUser(getContext(), 0,
-                new Intent(Intent.ACTION_TIME_TICK).addFlags(
-                        Intent.FLAG_RECEIVER_REGISTERED_ONLY
-                        | Intent.FLAG_RECEIVER_FOREGROUND
-                        | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS), 0,
-                        UserHandle.ALL);
-        Intent intent = new Intent(Intent.ACTION_DATE_CHANGED);
-        intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
-                | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
-        mDateChangeSender = PendingIntent.getBroadcastAsUser(getContext(), 0, intent,
-                Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT, UserHandle.ALL);
-
-        // now that we have initied the driver schedule the alarm
-        mClockReceiver = new ClockReceiver();
-        mClockReceiver.scheduleTimeTickEvent();
-        mClockReceiver.scheduleDateChangedEvent();
-        mInteractiveStateReceiver = new InteractiveStateReceiver();
-        mUninstallReceiver = new UninstallReceiver();
-
-        if (mNativeData != 0) {
-            AlarmThread waitThread = new AlarmThread();
-            waitThread.start();
-        } else {
-            Slog.w(TAG, "Failed to open alarm driver. Falling back to a handler.");
-        }
-
-        try {
-            ActivityManager.getService().registerUidObserver(new UidObserver(),
-                    ActivityManager.UID_OBSERVER_GONE | ActivityManager.UID_OBSERVER_IDLE
-                            | ActivityManager.UID_OBSERVER_ACTIVE,
-                    ActivityManager.PROCESS_STATE_UNKNOWN, null);
-        } catch (RemoteException e) {
-            // ignored; both services live in system_server
-        }
+        publishLocalService(AlarmManagerInternal.class, new LocalService());
         publishBinderService(Context.ALARM_SERVICE, mService);
     }
 
     @Override
     public void onBootPhase(int phase) {
         if (phase == PHASE_SYSTEM_SERVICES_READY) {
-            mConstants.start(getContext().getContentResolver());
-            mAppOps = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE);
-            mLocalDeviceIdleController
-                    = LocalServices.getService(DeviceIdleController.LocalService.class);
-            mUsageStatsManagerInternal = LocalServices.getService(UsageStatsManagerInternal.class);
-            mUsageStatsManagerInternal.addAppIdleStateChangeListener(new AppStandbyTracker());
+            synchronized (mLock) {
+                mConstants.start(getContext().getContentResolver());
+                mAppOps = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE);
+                mLocalDeviceIdleController =
+                        LocalServices.getService(DeviceIdleController.LocalService.class);
+                mUsageStatsManagerInternal =
+                        LocalServices.getService(UsageStatsManagerInternal.class);
+                mUsageStatsManagerInternal.addAppIdleStateChangeListener(new AppStandbyTracker());
 
-            mAppStateTracker = LocalServices.getService(AppStateTracker.class);
-            mAppStateTracker.addListener(mForceAppStandbyListener);
+                mAppStateTracker = LocalServices.getService(AppStateTracker.class);
+                mAppStateTracker.addListener(mForceAppStandbyListener);
+
+                mClockReceiver.scheduleTimeTickEvent();
+                mClockReceiver.scheduleDateChangedEvent();
+            }
         }
     }
 
     @Override
     protected void finalize() throws Throwable {
         try {
-            close(mNativeData);
+            mInjector.close();
         } finally {
             super.finalize();
         }
     }
 
     boolean setTimeImpl(long millis) {
-        if (mNativeData == 0) {
+        if (!mInjector.isAlarmDriverPresent()) {
             Slog.w(TAG, "Not setting time since no alarm driver is available.");
             return false;
         }
 
         synchronized (mLock) {
-            final long currentTimeMillis = System.currentTimeMillis();
-            setKernelTime(mNativeData, millis);
+            final long currentTimeMillis = mInjector.getCurrentTimeMillis();
+            mInjector.setKernelTime(millis);
             final TimeZone timeZone = TimeZone.getDefault();
             final int currentTzOffset = timeZone.getOffset(currentTimeMillis);
             final int newTzOffset = timeZone.getOffset(millis);
             if (currentTzOffset != newTzOffset) {
                 Slog.i(TAG, "Timezone offset has changed, updating kernel timezone");
-                setKernelTimezone(mNativeData, -(newTzOffset / 60000));
+                mInjector.setKernelTimezone(-(newTzOffset / 60000));
             }
             // The native implementation of setKernelTime can return -1 even when the kernel
             // time was set correctly, so assume setting kernel time was successful and always
@@ -1426,8 +1422,8 @@
 
             // Update the kernel timezone information
             // Kernel tracks time offsets as 'minutes west of GMT'
-            int gmtOffset = zone.getOffset(System.currentTimeMillis());
-            setKernelTimezone(mNativeData, -(gmtOffset / 60000));
+            int gmtOffset = zone.getOffset(mInjector.getCurrentTimeMillis());
+            mInjector.setKernelTimezone(-(gmtOffset / 60000));
         }
 
         TimeZone.setDefault(null);
@@ -1498,7 +1494,7 @@
             triggerAtTime = 0;
         }
 
-        final long nowElapsed = SystemClock.elapsedRealtime();
+        final long nowElapsed = mInjector.getElapsedRealtime();
         final long nominalTrigger = convertToElapsed(triggerAtTime, type);
         // Try to prevent spamming by making sure we aren't firing alarms in the immediate future
         final long minTrigger = nowElapsed + mConstants.MIN_FUTURITY;
@@ -1551,7 +1547,8 @@
      * Return the minimum time that should elapse before an app in the specified bucket
      * can receive alarms again
      */
-    private long getMinDelayForBucketLocked(int bucket) {
+    @VisibleForTesting
+    long getMinDelayForBucketLocked(int bucket) {
         // UsageStats bucket values are treated as floors of their behavioral range.
         // In other words, a bucket value between WORKING and ACTIVE is treated as
         // WORKING, not as ACTIVE.  The ACTIVE and NEVER bucket apply only at specific
@@ -1591,7 +1588,7 @@
         final String sourcePackage = alarm.sourcePackage;
         final int sourceUserId = UserHandle.getUserId(alarm.creatorUid);
         final int standbyBucket = mUsageStatsManagerInternal.getAppStandbyBucket(
-                sourcePackage, sourceUserId, SystemClock.elapsedRealtime());
+                sourcePackage, sourceUserId, mInjector.getElapsedRealtime());
 
         final Pair<String, Integer> packageUser = Pair.create(sourcePackage, sourceUserId);
         final long lastElapsed = mLastAlarmDeliveredForPackage.getOrDefault(packageUser, 0L);
@@ -1619,7 +1616,7 @@
                 a.when = a.whenElapsed = a.maxWhenElapsed = mNextWakeFromIdle.whenElapsed;
             }
             // Add fuzz to make the alarm go off some time before the actual desired time.
-            final long nowElapsed = SystemClock.elapsedRealtime();
+            final long nowElapsed = mInjector.getElapsedRealtime();
             final int fuzz = fuzzForDuration(a.whenElapsed-nowElapsed);
             if (fuzz > 0) {
                 if (mRandom == null) {
@@ -1655,7 +1652,7 @@
                 ent.pkg = a.operation.getCreatorPackage();
                 ent.tag = a.operation.getTag("");
                 ent.op = "SET";
-                ent.elapsedRealtime = SystemClock.elapsedRealtime();
+                ent.elapsedRealtime = mInjector.getElapsedRealtime();
                 ent.argRealtime = a.whenElapsed;
                 mAllowWhileIdleDispatches.add(ent);
             }
@@ -1675,7 +1672,7 @@
                     IdleDispatchEntry ent = new IdleDispatchEntry();
                     ent.uid = 0;
                     ent.pkg = "START IDLE";
-                    ent.elapsedRealtime = SystemClock.elapsedRealtime();
+                    ent.elapsedRealtime = mInjector.getElapsedRealtime();
                     mAllowWhileIdleDispatches.add(ent);
                 }
             }
@@ -1890,8 +1887,8 @@
             pw.println("  App Standby Parole: " + mAppStandbyParole);
             pw.println();
 
-            final long nowRTC = System.currentTimeMillis();
-            final long nowELAPSED = SystemClock.elapsedRealtime();
+            final long nowRTC = mInjector.getCurrentTimeMillis();
+            final long nowELAPSED = mInjector.getElapsedRealtime();
             final long nowUPTIME = SystemClock.uptimeMillis();
             SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
 
@@ -1958,10 +1955,10 @@
                     pw.println();
 
             pw.print("  Next kernel non-wakeup alarm: ");
-            TimeUtils.formatDuration(getNextAlarm(mNativeData, ELAPSED_REALTIME), pw);
+            TimeUtils.formatDuration(mInjector.getNextAlarm(ELAPSED_REALTIME), pw);
             pw.println();
             pw.print("  Next kernel wakeup alarm: ");
-            TimeUtils.formatDuration(getNextAlarm(mNativeData, ELAPSED_REALTIME_WAKEUP), pw);
+            TimeUtils.formatDuration(mInjector.getNextAlarm(ELAPSED_REALTIME_WAKEUP), pw);
             pw.println();
 
             pw.print("  Last wakeup: "); TimeUtils.formatDuration(mLastWakeup, nowELAPSED, pw);
@@ -2257,8 +2254,8 @@
         final ProtoOutputStream proto = new ProtoOutputStream(fd);
 
         synchronized (mLock) {
-            final long nowRTC = System.currentTimeMillis();
-            final long nowElapsed = SystemClock.elapsedRealtime();
+            final long nowRTC = mInjector.getCurrentTimeMillis();
+            final long nowElapsed = mInjector.getElapsedRealtime();
             proto.write(AlarmManagerServiceDumpProto.CURRENT_TIME, nowRTC);
             proto.write(AlarmManagerServiceDumpProto.ELAPSED_REALTIME, nowElapsed);
             proto.write(AlarmManagerServiceDumpProto.LAST_TIME_CHANGE_CLOCK_TIME,
@@ -2494,8 +2491,8 @@
     private void logBatchesLocked(SimpleDateFormat sdf) {
         ByteArrayOutputStream bs = new ByteArrayOutputStream(2048);
         PrintWriter pw = new PrintWriter(bs);
-        final long nowRTC = System.currentTimeMillis();
-        final long nowELAPSED = SystemClock.elapsedRealtime();
+        final long nowRTC = mInjector.getCurrentTimeMillis();
+        final long nowELAPSED = mInjector.getElapsedRealtime();
         final int NZ = mAlarmBatches.size();
         for (int iz = 0; iz < NZ; iz++) {
             Batch bz = mAlarmBatches.get(iz);
@@ -2693,7 +2690,7 @@
             TimeUtils.formatDuration(mNextNonWakeUpSetAt - nowElapsed, errorMsg);
             errorMsg.append(", mLastWakeup=");
             TimeUtils.formatDuration(mLastWakeup - nowElapsed, errorMsg);
-            errorMsg.append(", timerfd_gettime=" + getNextAlarm(mNativeData, ELAPSED_REALTIME));
+            errorMsg.append(", timerfd_gettime=" + mInjector.getNextAlarm(ELAPSED_REALTIME));
             errorMsg.append("];");
         }
         if (mNextWakeup < (nowElapsed - 10_000) && mLastWakeup < mNextWakeup) {
@@ -2705,7 +2702,7 @@
             errorMsg.append(", mLastWakeup=");
             TimeUtils.formatDuration(mLastWakeup - nowElapsed, errorMsg);
             errorMsg.append(", timerfd_gettime="
-                    + getNextAlarm(mNativeData, ELAPSED_REALTIME_WAKEUP));
+                    + mInjector.getNextAlarm(ELAPSED_REALTIME_WAKEUP));
             errorMsg.append("];");
         }
         if (stuck) {
@@ -2716,7 +2713,7 @@
     void rescheduleKernelAlarmsLocked() {
         // Schedule the next upcoming wakeup alarm.  If there is a deliverable batch
         // prior to that which contains no wakeups, we schedule that as well.
-        final long nowElapsed = SystemClock.elapsedRealtime();
+        final long nowElapsed = mInjector.getElapsedRealtime();
         validateLastAlarmExpiredLocked(nowElapsed);
         long nextNonWakeup = 0;
         if (mAlarmBatches.size() > 0) {
@@ -2743,7 +2740,7 @@
         }
     }
 
-    private void removeLocked(PendingIntent operation, IAlarmListener directReceiver) {
+    void removeLocked(PendingIntent operation, IAlarmListener directReceiver) {
         if (operation == null && directReceiver == null) {
             if (localLOGV) {
                 Slog.w(TAG, "requested remove() of null operation",
@@ -2983,7 +2980,7 @@
     void interactiveStateChangedLocked(boolean interactive) {
         if (mInteractive != interactive) {
             mInteractive = interactive;
-            final long nowELAPSED = SystemClock.elapsedRealtime();
+            final long nowELAPSED = mInjector.getElapsedRealtime();
             if (interactive) {
                 if (mPendingNonWakeupAlarms.size() > 0) {
                     final long thisDelayTime = nowELAPSED - mStartCurrentDelayTime;
@@ -3023,31 +3020,13 @@
     }
 
     private void setLocked(int type, long when) {
-        if (mNativeData != 0) {
-            // The kernel never triggers alarms with negative wakeup times
-            // so we ensure they are positive.
-            long alarmSeconds, alarmNanoseconds;
-            if (when < 0) {
-                alarmSeconds = 0;
-                alarmNanoseconds = 0;
-            } else {
-                alarmSeconds = when / 1000;
-                alarmNanoseconds = (when % 1000) * 1000 * 1000;
-            }
-
-            final int result = set(mNativeData, type, alarmSeconds, alarmNanoseconds);
-            if (result != 0) {
-                final long nowElapsed = SystemClock.elapsedRealtime();
-                Slog.wtf(TAG, "Unable to set kernel alarm, now=" + nowElapsed
-                        + " type=" + type + " when=" + when
-                        + " @ (" + alarmSeconds + "," + alarmNanoseconds
-                        + "), ret = " + result + " = " + Os.strerror(result));
-            }
+        if (mInjector.isAlarmDriverPresent()) {
+            mInjector.setAlarm(type, when);
         } else {
             Message msg = Message.obtain();
-            msg.what = ALARM_EVENT;
+            msg.what = AlarmHandler.ALARM_EVENT;
 
-            mHandler.removeMessages(ALARM_EVENT);
+            mHandler.removeMessages(msg.what);
             mHandler.sendMessageAtTime(msg, when);
         }
     }
@@ -3106,13 +3085,13 @@
                         exemptOnBatterySaver);
     }
 
-    private native long init();
-    private native void close(long nativeData);
-    private native int set(long nativeData, int type, long seconds, long nanoseconds);
-    private native int waitForAlarm(long nativeData);
-    private native int setKernelTime(long nativeData, long millis);
-    private native int setKernelTimezone(long nativeData, int minuteswest);
-    private native long getNextAlarm(long nativeData, int type);
+    private static native long init();
+    private static native void close(long nativeData);
+    private static native int set(long nativeData, int type, long seconds, long nanoseconds);
+    private static native int waitForAlarm(long nativeData);
+    private static native int setKernelTime(long nativeData, long millis);
+    private static native int setKernelTimezone(long nativeData, int minuteswest);
+    private static native long getNextAlarm(long nativeData, int type);
 
     private long getWhileIdleMinIntervalLocked(int uid) {
         final boolean dozing = mPendingIdleUntil != null;
@@ -3516,6 +3495,103 @@
                 || (a.flags & FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED) != 0;
     }
 
+    @VisibleForTesting
+    static class Injector {
+        private long mNativeData;
+        private Context mContext;
+
+        Injector(Context context) {
+            mContext = context;
+        }
+
+        void init() {
+            mNativeData = AlarmManagerService.init();
+        }
+
+        int waitForAlarm() {
+            return AlarmManagerService.waitForAlarm(mNativeData);
+        }
+
+        boolean isAlarmDriverPresent() {
+            return mNativeData != 0;
+        }
+
+        void setAlarm(int type, long millis) {
+            // The kernel never triggers alarms with negative wakeup times
+            // so we ensure they are positive.
+            final long alarmSeconds, alarmNanoseconds;
+            if (millis < 0) {
+                alarmSeconds = 0;
+                alarmNanoseconds = 0;
+            } else {
+                alarmSeconds = millis / 1000;
+                alarmNanoseconds = (millis % 1000) * 1000 * 1000;
+            }
+
+            final int result = AlarmManagerService.set(mNativeData, type, alarmSeconds,
+                    alarmNanoseconds);
+            if (result != 0) {
+                final long nowElapsed = SystemClock.elapsedRealtime();
+                Slog.wtf(TAG, "Unable to set kernel alarm, now=" + nowElapsed
+                        + " type=" + type + " @ (" + alarmSeconds + "," + alarmNanoseconds
+                        + "), ret = " + result + " = " + Os.strerror(result));
+            }
+        }
+
+        long getNextAlarm(int type) {
+            return AlarmManagerService.getNextAlarm(mNativeData, type);
+        }
+
+        void setKernelTimezone(int minutesWest) {
+            AlarmManagerService.setKernelTimezone(mNativeData, minutesWest);
+        }
+
+        void setKernelTime(long millis) {
+            if (mNativeData != 0) {
+                AlarmManagerService.setKernelTime(mNativeData, millis);
+            }
+        }
+
+        void close() {
+            AlarmManagerService.close(mNativeData);
+        }
+
+        long getElapsedRealtime() {
+            return SystemClock.elapsedRealtime();
+        }
+
+        long getCurrentTimeMillis() {
+            return System.currentTimeMillis();
+        }
+
+        PowerManager.WakeLock getAlarmWakeLock() {
+            final PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
+            return pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*alarm*");
+        }
+
+        int getSystemUiUid() {
+            int sysUiUid = -1;
+            final PackageManager pm = mContext.getPackageManager();
+            try {
+                PermissionInfo sysUiPerm = pm.getPermissionInfo(SYSTEM_UI_SELF_PERMISSION, 0);
+                ApplicationInfo sysUi = pm.getApplicationInfo(sysUiPerm.packageName, 0);
+                if ((sysUi.privateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0) {
+                    sysUiUid = sysUi.uid;
+                } else {
+                    Slog.e(TAG, "SysUI permission " + SYSTEM_UI_SELF_PERMISSION
+                            + " defined by non-privileged app " + sysUi.packageName
+                            + " - ignoring");
+                }
+            } catch (NameNotFoundException e) {
+            }
+            return sysUiUid;
+        }
+
+        ClockReceiver getClockReceiver(AlarmManagerService service) {
+            return service.new ClockReceiver();
+        }
+    }
+
     private class AlarmThread extends Thread
     {
         private int mFalseWakeups;
@@ -3524,7 +3600,7 @@
         {
             super("AlarmManager");
             mFalseWakeups = 0;
-            mWtfThreshold = 10;
+            mWtfThreshold = 100;
         }
 
         public void run()
@@ -3533,14 +3609,16 @@
 
             while (true)
             {
-                int result = waitForAlarm(mNativeData);
-
-                final long nowRTC = System.currentTimeMillis();
-                final long nowELAPSED = SystemClock.elapsedRealtime();
+                int result = mInjector.waitForAlarm();
+                final long nowRTC = mInjector.getCurrentTimeMillis();
+                final long nowELAPSED = mInjector.getElapsedRealtime();
                 synchronized (mLock) {
                     mLastWakeup = nowELAPSED;
                 }
-
+                if (result == 0) {
+                    Slog.wtf(TAG, "waitForAlarm returned 0, nowRTC = " + nowRTC
+                            + ", nowElapsed = " + nowELAPSED);
+                }
                 triggerList.clear();
 
                 if ((result & TIME_CHANGED_MASK) != 0) {
@@ -3560,6 +3638,8 @@
                         if (DEBUG_BATCH) {
                             Slog.v(TAG, "Time changed notification from kernel; rebatching");
                         }
+                        // StatsLog requires currentTimeMillis(), which == nowRTC to within usecs.
+                        StatsLog.write(StatsLog.WALL_CLOCK_TIME_SHIFTED, nowRTC);
                         removeImpl(mTimeTickSender);
                         removeImpl(mDateChangeSender);
                         rebatchAllAlarms();
@@ -3720,7 +3800,8 @@
         public static final int APP_STANDBY_PAROLE_CHANGED = 6;
         public static final int REMOVE_FOR_STOPPED = 7;
 
-        public AlarmHandler() {
+        AlarmHandler(Looper looper) {
+            super(looper);
         }
 
         public void postRemoveForStopped(int uid) {
@@ -3732,8 +3813,8 @@
                 case ALARM_EVENT: {
                     ArrayList<Alarm> triggerList = new ArrayList<Alarm>();
                     synchronized (mLock) {
-                        final long nowRTC = System.currentTimeMillis();
-                        final long nowELAPSED = SystemClock.elapsedRealtime();
+                        final long nowRTC = mInjector.getCurrentTimeMillis();
+                        final long nowELAPSED = mInjector.getElapsedRealtime();
                         triggerAlarmsLocked(triggerList, nowELAPSED, nowRTC);
                         updateNextAlarmClockLocked();
                     }
@@ -3817,7 +3898,7 @@
                     Slog.v(TAG, "Received TIME_TICK alarm; rescheduling");
                 }
                 synchronized (mLock) {
-                    mLastTickReceived = System.currentTimeMillis();
+                    mLastTickReceived = mInjector.getCurrentTimeMillis();
                 }
                 scheduleTimeTickEvent();
             } else if (intent.getAction().equals(Intent.ACTION_DATE_CHANGED)) {
@@ -3826,14 +3907,14 @@
                 // based off of the current Zone gmt offset + userspace tracked
                 // daylight savings information.
                 TimeZone zone = TimeZone.getTimeZone(SystemProperties.get(TIMEZONE_PROPERTY));
-                int gmtOffset = zone.getOffset(System.currentTimeMillis());
-                setKernelTimezone(mNativeData, -(gmtOffset / 60000));
+                int gmtOffset = zone.getOffset(mInjector.getCurrentTimeMillis());
+                mInjector.setKernelTimezone(-(gmtOffset / 60000));
                 scheduleDateChangedEvent();
             }
         }
 
         public void scheduleTimeTickEvent() {
-            final long currentTime = System.currentTimeMillis();
+            final long currentTime = mInjector.getCurrentTimeMillis();
             final long nextTime = 60000 * ((currentTime / 60000) + 1);
 
             // Schedule this event for the amount of time that it would take to get to
@@ -3841,7 +3922,7 @@
             final long tickEventDelay = nextTime - currentTime;
 
             final WorkSource workSource = null; // Let system take blame for time tick events.
-            setImpl(ELAPSED_REALTIME, SystemClock.elapsedRealtime() + tickEventDelay, 0,
+            setImpl(ELAPSED_REALTIME, mInjector.getElapsedRealtime() + tickEventDelay, 0,
                     0, mTimeTickSender, null, null, AlarmManager.FLAG_STANDALONE, workSource,
                     null, Process.myUid(), "android");
 
@@ -3853,7 +3934,7 @@
 
         public void scheduleDateChangedEvent() {
             Calendar calendar = Calendar.getInstance();
-            calendar.setTimeInMillis(System.currentTimeMillis());
+            calendar.setTimeInMillis(mInjector.getCurrentTimeMillis());
             calendar.set(Calendar.HOUR_OF_DAY, 0);
             calendar.set(Calendar.MINUTE, 0);
             calendar.set(Calendar.SECOND, 0);
@@ -4122,7 +4203,7 @@
         }
 
         private void updateStatsLocked(InFlight inflight) {
-            final long nowELAPSED = SystemClock.elapsedRealtime();
+            final long nowELAPSED = mInjector.getElapsedRealtime();
             BroadcastStats bs = inflight.mBroadcastStats;
             bs.nesting--;
             if (bs.nesting <= 0) {
diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java
index 50f15ca0..a85b69b 100644
--- a/services/core/java/com/android/server/BatteryService.java
+++ b/services/core/java/com/android/server/BatteryService.java
@@ -399,6 +399,12 @@
 
     private void update(android.hardware.health.V2_0.HealthInfo info) {
         traceBegin("HealthInfoUpdate");
+
+        Trace.traceCounter(Trace.TRACE_TAG_POWER, "BatteryChargeCounter",
+                info.legacy.batteryChargeCounter);
+        Trace.traceCounter(Trace.TRACE_TAG_POWER, "BatteryCurrent",
+                info.legacy.batteryCurrent);
+
         synchronized (mLock) {
             if (!mUpdatesStopped) {
                 mHealthInfo = info.legacy;
diff --git a/services/core/java/com/android/server/BinderCallsStatsService.java b/services/core/java/com/android/server/BinderCallsStatsService.java
index 9a7c345..15673a7 100644
--- a/services/core/java/com/android/server/BinderCallsStatsService.java
+++ b/services/core/java/com/android/server/BinderCallsStatsService.java
@@ -33,7 +33,7 @@
 
 import com.android.internal.os.BackgroundThread;
 import com.android.internal.os.BinderCallsStats;
-import com.android.internal.os.BinderInternal;
+import com.android.internal.os.CachedDeviceState;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -41,7 +41,6 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.Random;
 
 public class BinderCallsStatsService extends Binder {
 
@@ -156,8 +155,10 @@
         @Override
         public void onBootPhase(int phase) {
             if (SystemService.PHASE_SYSTEM_SERVICES_READY == phase) {
+                CachedDeviceState.Readonly deviceState = getLocalService(
+                        CachedDeviceState.Readonly.class);
                 mService.systemReady(getContext());
-                mBinderCallsStats.systemReady(getContext());
+                mBinderCallsStats.setDeviceState(deviceState);
             }
         }
     }
diff --git a/services/core/java/com/android/server/CachedDeviceStateService.java b/services/core/java/com/android/server/CachedDeviceStateService.java
new file mode 100644
index 0000000..38269d3
--- /dev/null
+++ b/services/core/java/com/android/server/CachedDeviceStateService.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 com.android.server;
+
+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.OsProtoEnums;
+import android.os.PowerManager;
+import android.util.Slog;
+
+import com.android.internal.os.CachedDeviceState;
+
+/**
+ * Tracks changes to the device state (e.g. charging/on battery, screen on/off) to share it with
+ * the System Server telemetry services.
+ *
+ * @hide Only for use within the system server.
+ */
+public class CachedDeviceStateService extends SystemService {
+    private static final String TAG = "CachedDeviceStateService";
+    private final CachedDeviceState mDeviceState = new CachedDeviceState();
+    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            switch (intent.getAction()) {
+                case Intent.ACTION_BATTERY_CHANGED:
+                    mDeviceState.setCharging(
+                            intent.getIntExtra(BatteryManager.EXTRA_PLUGGED,
+                                    OsProtoEnums.BATTERY_PLUGGED_NONE)
+                                    != OsProtoEnums.BATTERY_PLUGGED_NONE);
+                    break;
+                case Intent.ACTION_SCREEN_ON:
+                    mDeviceState.setScreenInteractive(true);
+                    break;
+                case Intent.ACTION_SCREEN_OFF:
+                    mDeviceState.setScreenInteractive(false);
+                    break;
+            }
+        }
+    };
+
+    public CachedDeviceStateService(Context context) {
+        super(context);
+    }
+
+    @Override
+    public void onStart() {
+        publishLocalService(CachedDeviceState.Readonly.class, mDeviceState.getReadonlyClient());
+    }
+
+    @Override
+    public void onBootPhase(int phase) {
+        if (SystemService.PHASE_SYSTEM_SERVICES_READY == phase) {
+            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);
+            getContext().registerReceiver(mBroadcastReceiver, filter);
+            mDeviceState.setCharging(queryIsCharging());
+            mDeviceState.setScreenInteractive(queryScreenInteractive(getContext()));
+        }
+    }
+
+    private boolean queryIsCharging() {
+        final BatteryManagerInternal batteryManager =
+                LocalServices.getService(BatteryManagerInternal.class);
+        if (batteryManager == null) {
+            Slog.wtf(TAG, "BatteryManager null while starting CachedDeviceStateService");
+            // 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);
+        if (powerManager == null) {
+            Slog.wtf(TAG, "PowerManager null while starting CachedDeviceStateService");
+            return false;
+        } else {
+            return powerManager.isInteractive();
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index ba5f323..7602090 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -183,6 +183,7 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.Comparator;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
@@ -202,6 +203,8 @@
     private static final String DIAG_ARG = "--diag";
     public static final String SHORT_ARG = "--short";
     private static final String TETHERING_ARG = "tethering";
+    private static final String NETWORK_ARG = "networks";
+    private static final String REQUEST_ARG = "requests";
 
     private static final boolean DBG = true;
     private static final boolean VDBG = false;
@@ -1978,7 +1981,7 @@
     private void dumpNetworkDiagnostics(IndentingPrintWriter pw) {
         final List<NetworkDiagnostics> netDiags = new ArrayList<NetworkDiagnostics>();
         final long DIAG_TIME_MS = 5000;
-        for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
+        for (NetworkAgentInfo nai : networksSortedById()) {
             // Start gathering diagnostic information.
             netDiags.add(new NetworkDiagnostics(
                     nai.network,
@@ -2009,6 +2012,12 @@
         } else if (ArrayUtils.contains(args, TETHERING_ARG)) {
             mTethering.dump(fd, pw, args);
             return;
+        } else if (ArrayUtils.contains(args, NETWORK_ARG)) {
+            dumpNetworks(pw);
+            return;
+        } else if (ArrayUtils.contains(args, REQUEST_ARG)) {
+            dumpNetworkRequests(pw);
+            return;
         }
 
         pw.print("NetworkFactories for:");
@@ -2029,36 +2038,15 @@
 
         pw.println("Current Networks:");
         pw.increaseIndent();
-        for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
-            pw.println(nai.toString());
-            pw.increaseIndent();
-            pw.println(String.format(
-                    "Requests: REQUEST:%d LISTEN:%d BACKGROUND_REQUEST:%d total:%d",
-                    nai.numForegroundNetworkRequests(),
-                    nai.numNetworkRequests() - nai.numRequestNetworkRequests(),
-                    nai.numBackgroundNetworkRequests(),
-                    nai.numNetworkRequests()));
-            pw.increaseIndent();
-            for (int i = 0; i < nai.numNetworkRequests(); i++) {
-                pw.println(nai.requestAt(i).toString());
-            }
-            pw.decreaseIndent();
-            pw.println("Lingered:");
-            pw.increaseIndent();
-            nai.dumpLingerTimers(pw);
-            pw.decreaseIndent();
-            pw.decreaseIndent();
-        }
+        dumpNetworks(pw);
         pw.decreaseIndent();
         pw.println();
 
         pw.println("Network Requests:");
         pw.increaseIndent();
-        for (NetworkRequestInfo nri : mNetworkRequests.values()) {
-            pw.println(nri.toString());
-        }
-        pw.println();
+        dumpNetworkRequests(pw);
         pw.decreaseIndent();
+        pw.println();
 
         mLegacyTypeTracker.dump(pw);
 
@@ -2126,6 +2114,55 @@
         }
     }
 
+    private void dumpNetworks(IndentingPrintWriter pw) {
+        for (NetworkAgentInfo nai : networksSortedById()) {
+            pw.println(nai.toString());
+            pw.increaseIndent();
+            pw.println(String.format(
+                    "Requests: REQUEST:%d LISTEN:%d BACKGROUND_REQUEST:%d total:%d",
+                    nai.numForegroundNetworkRequests(),
+                    nai.numNetworkRequests() - nai.numRequestNetworkRequests(),
+                    nai.numBackgroundNetworkRequests(),
+                    nai.numNetworkRequests()));
+            pw.increaseIndent();
+            for (int i = 0; i < nai.numNetworkRequests(); i++) {
+                pw.println(nai.requestAt(i).toString());
+            }
+            pw.decreaseIndent();
+            pw.println("Lingered:");
+            pw.increaseIndent();
+            nai.dumpLingerTimers(pw);
+            pw.decreaseIndent();
+            pw.decreaseIndent();
+        }
+    }
+
+    private void dumpNetworkRequests(IndentingPrintWriter pw) {
+        for (NetworkRequestInfo nri : requestsSortedById()) {
+            pw.println(nri.toString());
+        }
+    }
+
+    /**
+     * Return an array of all current NetworkAgentInfos sorted by network id.
+     */
+    private NetworkAgentInfo[] networksSortedById() {
+        NetworkAgentInfo[] networks = new NetworkAgentInfo[0];
+        networks = mNetworkAgentInfos.values().toArray(networks);
+        Arrays.sort(networks, Comparator.comparingInt(nai -> nai.network.netId));
+        return networks;
+    }
+
+    /**
+     * Return an array of all current NetworkRequest sorted by request id.
+     */
+    private NetworkRequestInfo[] requestsSortedById() {
+        NetworkRequestInfo[] requests = new NetworkRequestInfo[0];
+        requests = mNetworkRequests.values().toArray(requests);
+        Arrays.sort(requests, Comparator.comparingInt(nri -> nri.request.requestId));
+        return requests;
+    }
+
     private boolean isLiveNetworkAgent(NetworkAgentInfo nai, int what) {
         if (nai.network == null) return false;
         final NetworkAgentInfo officialNai = getNetworkAgentInfoForNetwork(nai.network);
@@ -2916,7 +2953,7 @@
         pw.println("User setting:      " + description);
         pw.println("Network overrides:");
         pw.increaseIndent();
-        for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
+        for (NetworkAgentInfo nai : networksSortedById()) {
             if (nai.avoidUnvalidated) {
                 pw.println(nai.name());
             }
diff --git a/services/core/java/com/android/server/HardwarePropertiesManagerService.java b/services/core/java/com/android/server/HardwarePropertiesManagerService.java
index 4016d29..e21a3d7 100644
--- a/services/core/java/com/android/server/HardwarePropertiesManagerService.java
+++ b/services/core/java/com/android/server/HardwarePropertiesManagerService.java
@@ -26,7 +26,6 @@
 import static android.os.HardwarePropertiesManager.TEMPERATURE_THROTTLING_BELOW_VR_MIN;
 
 import android.Manifest;
-import android.app.ActivityManager;
 import android.app.AppOpsManager;
 import android.app.admin.DevicePolicyManager;
 import android.content.Context;
@@ -34,8 +33,8 @@
 import android.os.Binder;
 import android.os.CpuUsageInfo;
 import android.os.IHardwarePropertiesManager;
-import android.os.Process;
 import android.os.UserHandle;
+
 import com.android.internal.util.DumpUtils;
 import com.android.server.vr.VrManagerInternal;
 
@@ -166,11 +165,11 @@
         final VrManagerInternal vrService = LocalServices.getService(VrManagerInternal.class);
         final DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class);
         if (!dpm.isDeviceOwnerApp(callingPackage)
-                && !vrService.isCurrentVrListener(callingPackage, userId)
                 && mContext.checkCallingOrSelfPermission(Manifest.permission.DEVICE_POWER)
-                        != PackageManager.PERMISSION_GRANTED) {
-            throw new SecurityException("The caller is not a device owner, bound VrListenerService"
-                + ", or holding the DEVICE_POWER permission.");
+                        != PackageManager.PERMISSION_GRANTED
+                && (vrService == null || !vrService.isCurrentVrListener(callingPackage, userId))) {
+            throw new SecurityException("The caller is neither a device owner"
+                + ", nor holding the DEVICE_POWER permission, nor the current VrListener.");
         }
     }
 }
diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java
index 744ed25..380f6a7 100644
--- a/services/core/java/com/android/server/IpSecService.java
+++ b/services/core/java/com/android/server/IpSecService.java
@@ -27,7 +27,6 @@
 import android.annotation.NonNull;
 import android.app.AppOpsManager;
 import android.content.Context;
-import android.net.ConnectivityManager;
 import android.net.IIpSecService;
 import android.net.INetd;
 import android.net.IpSecAlgorithm;
@@ -44,7 +43,6 @@
 import android.net.TrafficStats;
 import android.net.util.NetdService;
 import android.os.Binder;
-import android.os.DeadSystemException;
 import android.os.IBinder;
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
@@ -89,9 +87,8 @@
     private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
 
     private static final String NETD_SERVICE_NAME = "netd";
-    private static final int[] DIRECTIONS =
-            new int[] {IpSecManager.DIRECTION_OUT, IpSecManager.DIRECTION_IN};
-    private static final String[] WILDCARD_ADDRESSES = new String[]{"0.0.0.0", "::"};
+    private static final int[] ADDRESS_FAMILIES =
+            new int[] {OsConstants.AF_INET, OsConstants.AF_INET6};
 
     private static final int NETD_FETCH_TIMEOUT_MS = 5000; // ms
     private static final int MAX_PORT_BIND_ATTEMPTS = 10;
@@ -615,7 +612,7 @@
                 mSrvConfig
                         .getNetdInstance()
                         .ipSecDeleteSecurityAssociation(
-                                mResourceId,
+                                uid,
                                 mConfig.getSourceAddress(),
                                 mConfig.getDestinationAddress(),
                                 spi,
@@ -682,7 +679,7 @@
                     mSrvConfig
                             .getNetdInstance()
                             .ipSecDeleteSecurityAssociation(
-                                    mResourceId, mSourceAddress, mDestinationAddress, mSpi, 0, 0);
+                                    uid, mSourceAddress, mDestinationAddress, mSpi, 0, 0);
                 }
             } catch (ServiceSpecificException | RemoteException e) {
                 Log.e(TAG, "Failed to delete SPI reservation with ID: " + mResourceId, e);
@@ -819,16 +816,22 @@
             //       Teardown VTI
             //       Delete global policies
             try {
-                mSrvConfig.getNetdInstance().removeVirtualTunnelInterface(mInterfaceName);
+                final INetd netd = mSrvConfig.getNetdInstance();
+                netd.removeVirtualTunnelInterface(mInterfaceName);
 
-                for(String wildcardAddr : WILDCARD_ADDRESSES) {
-                    for (int direction : DIRECTIONS) {
-                        int mark = (direction == IpSecManager.DIRECTION_IN) ? mIkey : mOkey;
-                        mSrvConfig
-                                .getNetdInstance()
-                                .ipSecDeleteSecurityPolicy(
-                                        0, direction, wildcardAddr, wildcardAddr, mark, 0xffffffff);
-                    }
+                for (int selAddrFamily : ADDRESS_FAMILIES) {
+                    netd.ipSecDeleteSecurityPolicy(
+                            uid,
+                            selAddrFamily,
+                            IpSecManager.DIRECTION_OUT,
+                            mOkey,
+                            0xffffffff);
+                    netd.ipSecDeleteSecurityPolicy(
+                            uid,
+                            selAddrFamily,
+                            IpSecManager.DIRECTION_IN,
+                            mIkey,
+                            0xffffffff);
                 }
             } catch (ServiceSpecificException | RemoteException e) {
                 Log.e(
@@ -1080,7 +1083,8 @@
         }
         checkNotNull(binder, "Null Binder passed to allocateSecurityParameterIndex");
 
-        UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid());
+        int callingUid = Binder.getCallingUid();
+        UserRecord userRecord = mUserResourceTracker.getUserRecord(callingUid);
         final int resourceId = mNextResourceId++;
 
         int spi = IpSecManager.INVALID_SECURITY_PARAMETER_INDEX;
@@ -1093,7 +1097,7 @@
             spi =
                     mSrvConfig
                             .getNetdInstance()
-                            .ipSecAllocateSpi(resourceId, "", destinationAddress, requestedSpi);
+                            .ipSecAllocateSpi(callingUid, "", destinationAddress, requestedSpi);
             Log.d(TAG, "Allocated SPI " + spi);
             userRecord.mSpiRecords.put(
                     resourceId,
@@ -1261,7 +1265,8 @@
         // TODO: Check that underlying network exists, and IP addresses not assigned to a different
         //       network (b/72316676).
 
-        UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid());
+        int callerUid = Binder.getCallingUid();
+        UserRecord userRecord = mUserResourceTracker.getUserRecord(callerUid);
         if (!userRecord.mTunnelQuotaTracker.isAvailable()) {
             return new IpSecTunnelInterfaceResponse(IpSecManager.Status.RESOURCE_UNAVAILABLE);
         }
@@ -1276,25 +1281,29 @@
             //       Create VTI
             //       Add inbound/outbound global policies
             //              (use reqid = 0)
-            mSrvConfig
-                    .getNetdInstance()
-                    .addVirtualTunnelInterface(intfName, localAddr, remoteAddr, ikey, okey);
+            final INetd netd = mSrvConfig.getNetdInstance();
+            netd.addVirtualTunnelInterface(intfName, localAddr, remoteAddr, ikey, okey);
 
-            for(String wildcardAddr : WILDCARD_ADDRESSES) {
-                for (int direction : DIRECTIONS) {
-                    int mark = (direction == IpSecManager.DIRECTION_OUT) ? okey : ikey;
-
-                    mSrvConfig
-                            .getNetdInstance()
-                            .ipSecAddSecurityPolicy(
-                                0, // Use 0 for reqId
-                                direction,
-                                wildcardAddr,
-                                wildcardAddr,
-                                0,
-                                mark,
-                                0xffffffff);
-                }
+            for (int selAddrFamily : ADDRESS_FAMILIES) {
+                // Always send down correct local/remote addresses for template.
+                netd.ipSecAddSecurityPolicy(
+                        callerUid,
+                        selAddrFamily,
+                        IpSecManager.DIRECTION_OUT,
+                        localAddr,
+                        remoteAddr,
+                        0,
+                        okey,
+                        0xffffffff);
+                netd.ipSecAddSecurityPolicy(
+                        callerUid,
+                        selAddrFamily,
+                        IpSecManager.DIRECTION_IN,
+                        remoteAddr,
+                        localAddr,
+                        0,
+                        ikey,
+                        0xffffffff);
             }
 
             userRecord.mTunnelInterfaceRecords.put(
@@ -1525,7 +1534,7 @@
         mSrvConfig
                 .getNetdInstance()
                 .ipSecAddSecurityAssociation(
-                        resourceId,
+                        Binder.getCallingUid(),
                         c.getMode(),
                         c.getSourceAddress(),
                         c.getDestinationAddress(),
@@ -1616,13 +1625,14 @@
     @Override
     public synchronized void applyTransportModeTransform(
             ParcelFileDescriptor socket, int direction, int resourceId) throws RemoteException {
-        UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid());
+        int callingUid = Binder.getCallingUid();
+        UserRecord userRecord = mUserResourceTracker.getUserRecord(callingUid);
         checkDirection(direction);
         // Get transform record; if no transform is found, will throw IllegalArgumentException
         TransformRecord info = userRecord.mTransformRecords.getResourceOrThrow(resourceId);
 
         // TODO: make this a function.
-        if (info.pid != getCallingPid() || info.uid != getCallingUid()) {
+        if (info.pid != getCallingPid() || info.uid != callingUid) {
             throw new SecurityException("Only the owner of an IpSec Transform may apply it!");
         }
 
@@ -1636,7 +1646,7 @@
                 .getNetdInstance()
                 .ipSecApplyTransportModeTransform(
                         socket.getFileDescriptor(),
-                        resourceId,
+                        callingUid,
                         direction,
                         c.getSourceAddress(),
                         c.getDestinationAddress(),
@@ -1668,7 +1678,8 @@
         enforceTunnelPermissions(callingPackage);
         checkDirection(direction);
 
-        UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid());
+        int callingUid = Binder.getCallingUid();
+        UserRecord userRecord = mUserResourceTracker.getUserRecord(callingUid);
 
         // Get transform record; if no transform is found, will throw IllegalArgumentException
         TransformRecord transformInfo =
@@ -1693,9 +1704,9 @@
         SpiRecord spiRecord = userRecord.mSpiRecords.getResourceOrThrow(c.getSpiResourceId());
 
         int mark =
-                (direction == IpSecManager.DIRECTION_IN)
-                        ? tunnelInterfaceInfo.getIkey()
-                        : tunnelInterfaceInfo.getOkey();
+                (direction == IpSecManager.DIRECTION_OUT)
+                        ? tunnelInterfaceInfo.getOkey()
+                        : tunnelInterfaceInfo.getIkey();
 
         try {
             c.setMarkValue(mark);
@@ -1706,14 +1717,15 @@
                 c.setNetwork(tunnelInterfaceInfo.getUnderlyingNetwork());
 
                 // If outbound, also add SPI to the policy.
-                for(String wildcardAddr : WILDCARD_ADDRESSES) {
+                for (int selAddrFamily : ADDRESS_FAMILIES) {
                     mSrvConfig
                             .getNetdInstance()
                             .ipSecUpdateSecurityPolicy(
-                                    0, // Use 0 for reqId
+                                    callingUid,
+                                    selAddrFamily,
                                     direction,
-                                    wildcardAddr,
-                                    wildcardAddr,
+                                    tunnelInterfaceInfo.getLocalAddress(),
+                                    tunnelInterfaceInfo.getRemoteAddress(),
                                     transformInfo.getSpiRecord().getSpi(),
                                     mark,
                                     0xffffffff);
diff --git a/services/core/java/com/android/server/LooperStatsService.java b/services/core/java/com/android/server/LooperStatsService.java
new file mode 100644
index 0000000..ab7bf28
--- /dev/null
+++ b/services/core/java/com/android/server/LooperStatsService.java
@@ -0,0 +1,206 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server;
+
+import android.content.Context;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Binder;
+import android.os.Looper;
+import android.os.ResultReceiver;
+import android.os.ShellCallback;
+import android.os.ShellCommand;
+import android.os.SystemProperties;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.util.KeyValueListParser;
+import android.util.Slog;
+
+import com.android.internal.os.BackgroundThread;
+import com.android.internal.os.CachedDeviceState;
+import com.android.internal.os.LooperStats;
+import com.android.internal.util.DumpUtils;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.List;
+
+/**
+ * @hide Only for use within the system server.
+ */
+public class LooperStatsService extends Binder {
+    private static final String TAG = "LooperStatsService";
+    private static final String LOOPER_STATS_SERVICE_NAME = "looper_stats";
+    private static final String SETTINGS_ENABLED_KEY = "enabled";
+    private static final String SETTINGS_SAMPLING_INTERVAL_KEY = "sampling_interval";
+    private static final String DEBUG_SYS_LOOPER_STATS_ENABLED =
+            "debug.sys.looper_stats_enabled";
+    private static final int DEFAULT_SAMPLING_INTERVAL = 100;
+    private static final int DEFAULT_ENTRIES_SIZE_CAP = 2000;
+    private static final boolean DEFAULT_ENABLED = false;
+
+    private final Context mContext;
+    private final LooperStats mStats;
+    private boolean mEnabled = false;
+
+    private LooperStatsService(Context context, LooperStats stats) {
+        this.mContext = context;
+        this.mStats = stats;
+    }
+
+    private void initFromSettings() {
+        final KeyValueListParser parser = new KeyValueListParser(',');
+
+        try {
+            parser.setString(Settings.Global.getString(mContext.getContentResolver(),
+                    Settings.Global.LOOPER_STATS));
+        } catch (IllegalArgumentException e) {
+            Slog.e(TAG, "Bad looper_stats settings", e);
+        }
+
+        setSamplingInterval(
+                parser.getInt(SETTINGS_SAMPLING_INTERVAL_KEY, DEFAULT_SAMPLING_INTERVAL));
+        // Manually specified value takes precedence over Settings.
+        setEnabled(SystemProperties.getBoolean(
+                DEBUG_SYS_LOOPER_STATS_ENABLED,
+                parser.getBoolean(SETTINGS_ENABLED_KEY, DEFAULT_ENABLED)));
+    }
+
+    @Override
+    public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
+            String[] args, ShellCallback callback, ResultReceiver resultReceiver) {
+        (new LooperShellCommand()).exec(this, in, out, err, args, callback, resultReceiver);
+    }
+
+    @Override
+    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
+        List<LooperStats.ExportedEntry> entries = mStats.getEntries();
+        entries.sort(Comparator
+                .comparing((LooperStats.ExportedEntry entry) -> entry.threadName)
+                .thenComparing(entry -> entry.handlerClassName)
+                .thenComparing(entry -> entry.messageName));
+        String header = String.join(",", Arrays.asList(
+                "thread_name",
+                "handler_class",
+                "message_name",
+                "is_interactive",
+                "message_count",
+                "recorded_message_count",
+                "total_latency_micros",
+                "max_latency_micros",
+                "total_cpu_micros",
+                "max_cpu_micros",
+                "exception_count"));
+        pw.println(header);
+        for (LooperStats.ExportedEntry entry : entries) {
+            pw.printf("%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s\n", entry.threadName,
+                    entry.handlerClassName, entry.messageName, entry.isInteractive,
+                    entry.messageCount, entry.recordedMessageCount, entry.totalLatencyMicros,
+                    entry.maxLatencyMicros, entry.cpuUsageMicros, entry.maxCpuUsageMicros,
+                    entry.exceptionCount);
+        }
+    }
+
+    private void setEnabled(boolean enabled) {
+        if (mEnabled != enabled) {
+            mEnabled = enabled;
+            mStats.reset();
+            Looper.setObserver(enabled ? mStats : null);
+        }
+    }
+
+    private void setSamplingInterval(int samplingInterval) {
+        mStats.setSamplingInterval(samplingInterval);
+    }
+
+    /**
+     * Manages the lifecycle of LooperStatsService within System Server.
+     */
+    public static class Lifecycle extends SystemService {
+        private final SettingsObserver mSettingsObserver;
+        private final LooperStatsService mService;
+        private final LooperStats mStats;
+
+        public Lifecycle(Context context) {
+            super(context);
+            mStats = new LooperStats(DEFAULT_SAMPLING_INTERVAL, DEFAULT_ENTRIES_SIZE_CAP);
+            mService = new LooperStatsService(getContext(), mStats);
+            mSettingsObserver = new SettingsObserver(mService);
+        }
+
+        @Override
+        public void onStart() {
+            publishLocalService(LooperStats.class, mStats);
+            publishBinderService(LOOPER_STATS_SERVICE_NAME, mService);
+        }
+
+        @Override
+        public void onBootPhase(int phase) {
+            if (SystemService.PHASE_SYSTEM_SERVICES_READY == phase) {
+                mService.initFromSettings();
+                Uri settingsUri = Settings.Global.getUriFor(Settings.Global.LOOPER_STATS);
+                getContext().getContentResolver().registerContentObserver(
+                        settingsUri, false, mSettingsObserver, UserHandle.USER_SYSTEM);
+                mStats.setDeviceState(getLocalService(CachedDeviceState.Readonly.class));
+            }
+        }
+    }
+
+    private static class SettingsObserver extends ContentObserver {
+        private final LooperStatsService mService;
+
+        SettingsObserver(LooperStatsService service) {
+            super(BackgroundThread.getHandler());
+            mService = service;
+        }
+
+        @Override
+        public void onChange(boolean selfChange, Uri uri, int userId) {
+            mService.initFromSettings();
+        }
+    }
+
+    private class LooperShellCommand extends ShellCommand {
+        @Override
+        public int onCommand(String cmd) {
+            if ("enable".equals(cmd)) {
+                setEnabled(true);
+                return 0;
+            } else if ("disable".equals(cmd)) {
+                setEnabled(false);
+                return 0;
+            } else if ("reset".equals(cmd)) {
+                mStats.reset();
+                return 0;
+            } else {
+                return handleDefaultCommands(cmd);
+            }
+        }
+
+        @Override
+        public void onHelp() {
+            final PrintWriter pw = getOutPrintWriter();
+            pw.println(LOOPER_STATS_SERVICE_NAME + " commands:");
+            pw.println("  enable: Enable collecting stats");
+            pw.println("  disable: Disable collecting stats");
+            pw.println("  reset: Reset stats");
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index d829602..1d163ee 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -316,7 +316,6 @@
     }
     private HashMap<String, IdleTimerParams> mActiveIdleTimers = Maps.newHashMap();
 
-    private volatile boolean mBandwidthControlEnabled;
     private volatile boolean mFirewallEnabled;
     private volatile boolean mStrictEnabled;
 
@@ -624,27 +623,11 @@
      */
     private void prepareNativeDaemon() {
 
-        mBandwidthControlEnabled = false;
-
-        // only enable bandwidth control when support exists
-        final boolean hasKernelSupport = new File("/proc/net/xt_qtaguid/ctrl").exists();
-
         // push any existing quota or UID rules
         synchronized (mQuotaLock) {
 
-            if (hasKernelSupport) {
-                Slog.d(TAG, "enabling bandwidth control");
-                try {
-                    mConnector.execute("bandwidth", "enable");
-                    mBandwidthControlEnabled = true;
-                } catch (NativeDaemonConnectorException e) {
-                    Log.wtf(TAG, "problem enabling bandwidth controls", e);
-                }
-            } else {
-                Slog.i(TAG, "not enabling bandwidth control");
-            }
-
-            SystemProperties.set(PROP_QTAGUID_ENABLED, mBandwidthControlEnabled ? "1" : "0");
+            // Netd unconditionally enable bandwidth control
+            SystemProperties.set(PROP_QTAGUID_ENABLED, "1");
 
             mStrictEnabled = true;
 
@@ -726,11 +709,10 @@
             }
         }
 
-        if (mBandwidthControlEnabled) {
-            try {
-                getBatteryStats().noteNetworkStatsEnabled();
-            } catch (RemoteException e) {
-            }
+
+        try {
+            getBatteryStats().noteNetworkStatsEnabled();
+        } catch (RemoteException e) {
         }
 
     }
@@ -1576,10 +1558,6 @@
     public void setInterfaceQuota(String iface, long quotaBytes) {
         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
 
-        // silently discard when control disabled
-        // TODO: eventually migrate to be always enabled
-        if (!mBandwidthControlEnabled) return;
-
         synchronized (mQuotaLock) {
             if (mActiveQuotas.containsKey(iface)) {
                 throw new IllegalStateException("iface " + iface + " already has quota");
@@ -1587,10 +1565,11 @@
 
             try {
                 // TODO: support quota shared across interfaces
-                mConnector.execute("bandwidth", "setiquota", iface, quotaBytes);
+                mNetdService.bandwidthSetInterfaceQuota(iface, quotaBytes);
+
                 mActiveQuotas.put(iface, quotaBytes);
-            } catch (NativeDaemonConnectorException e) {
-                throw e.rethrowAsParcelableException();
+            } catch (RemoteException | ServiceSpecificException e) {
+                throw new IllegalStateException(e);
             }
 
             synchronized (mTetheringStatsProviders) {
@@ -1610,10 +1589,6 @@
     public void removeInterfaceQuota(String iface) {
         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
 
-        // silently discard when control disabled
-        // TODO: eventually migrate to be always enabled
-        if (!mBandwidthControlEnabled) return;
-
         synchronized (mQuotaLock) {
             if (!mActiveQuotas.containsKey(iface)) {
                 // TODO: eventually consider throwing
@@ -1625,9 +1600,9 @@
 
             try {
                 // TODO: support quota shared across interfaces
-                mConnector.execute("bandwidth", "removeiquota", iface);
-            } catch (NativeDaemonConnectorException e) {
-                throw e.rethrowAsParcelableException();
+                mNetdService.bandwidthRemoveInterfaceQuota(iface);
+            } catch (RemoteException | ServiceSpecificException e) {
+                throw new IllegalStateException(e);
             }
 
             synchronized (mTetheringStatsProviders) {
@@ -1647,10 +1622,6 @@
     public void setInterfaceAlert(String iface, long alertBytes) {
         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
 
-        // silently discard when control disabled
-        // TODO: eventually migrate to be always enabled
-        if (!mBandwidthControlEnabled) return;
-
         // quick sanity check
         if (!mActiveQuotas.containsKey(iface)) {
             throw new IllegalStateException("setting alert requires existing quota on iface");
@@ -1663,10 +1634,10 @@
 
             try {
                 // TODO: support alert shared across interfaces
-                mConnector.execute("bandwidth", "setinterfacealert", iface, alertBytes);
+                mNetdService.bandwidthSetInterfaceAlert(iface, alertBytes);
                 mActiveAlerts.put(iface, alertBytes);
-            } catch (NativeDaemonConnectorException e) {
-                throw e.rethrowAsParcelableException();
+            } catch (RemoteException | ServiceSpecificException e) {
+                throw new IllegalStateException(e);
             }
         }
     }
@@ -1675,10 +1646,6 @@
     public void removeInterfaceAlert(String iface) {
         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
 
-        // silently discard when control disabled
-        // TODO: eventually migrate to be always enabled
-        if (!mBandwidthControlEnabled) return;
-
         synchronized (mQuotaLock) {
             if (!mActiveAlerts.containsKey(iface)) {
                 // TODO: eventually consider throwing
@@ -1687,10 +1654,10 @@
 
             try {
                 // TODO: support alert shared across interfaces
-                mConnector.execute("bandwidth", "removeinterfacealert", iface);
+                mNetdService.bandwidthRemoveInterfaceAlert(iface);
                 mActiveAlerts.remove(iface);
-            } catch (NativeDaemonConnectorException e) {
-                throw e.rethrowAsParcelableException();
+            } catch (RemoteException | ServiceSpecificException e) {
+                throw new IllegalStateException(e);
             }
         }
     }
@@ -1699,27 +1666,16 @@
     public void setGlobalAlert(long alertBytes) {
         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
 
-        // silently discard when control disabled
-        // TODO: eventually migrate to be always enabled
-        if (!mBandwidthControlEnabled) return;
-
         try {
-            mConnector.execute("bandwidth", "setglobalalert", alertBytes);
-        } catch (NativeDaemonConnectorException e) {
-            throw e.rethrowAsParcelableException();
+            mNetdService.bandwidthSetGlobalAlert(alertBytes);
+        } catch (RemoteException | ServiceSpecificException e) {
+            throw new IllegalStateException(e);
         }
     }
 
     private void setUidOnMeteredNetworkList(int uid, boolean blacklist, boolean enable) {
         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
 
-        // silently discard when control disabled
-        // TODO: eventually migrate to be always enabled
-        if (!mBandwidthControlEnabled) return;
-
-        final String chain = blacklist ? "naughtyapps" : "niceapps";
-        final String suffix = enable ? "add" : "remove";
-
         synchronized (mQuotaLock) {
             boolean oldEnable;
             SparseBooleanArray quotaList;
@@ -1734,7 +1690,19 @@
 
             Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "inetd bandwidth");
             try {
-                mConnector.execute("bandwidth", suffix + chain, uid);
+                if (blacklist) {
+                    if (enable) {
+                        mNetdService.bandwidthAddNaughtyApp(uid);
+                    } else {
+                        mNetdService.bandwidthRemoveNaughtyApp(uid);
+                    }
+                } else {
+                    if (enable) {
+                        mNetdService.bandwidthAddNiceApp(uid);
+                    } else {
+                        mNetdService.bandwidthRemoveNiceApp(uid);
+                    }
+                }
                 synchronized (mRulesLock) {
                     if (enable) {
                         quotaList.put(uid, true);
@@ -1742,8 +1710,8 @@
                         quotaList.delete(uid);
                     }
                 }
-            } catch (NativeDaemonConnectorException e) {
-                throw e.rethrowAsParcelableException();
+            } catch (RemoteException | ServiceSpecificException e) {
+                throw new IllegalStateException(e);
             } finally {
                 Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
             }
@@ -1868,7 +1836,7 @@
     @Override
     public boolean isBandwidthControlEnabled() {
         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
-        return mBandwidthControlEnabled;
+        return true;
     }
 
     @Override
@@ -2376,7 +2344,6 @@
         mConnector.dump(fd, pw, args);
         pw.println();
 
-        pw.print("Bandwidth control enabled: "); pw.println(mBandwidthControlEnabled);
         pw.print("mMobileActivityFromRadio="); pw.print(mMobileActivityFromRadio);
                 pw.print(" mLastPowerStateFromRadio="); pw.println(mLastPowerStateFromRadio);
         pw.print("mNetworkActive="); pw.println(mNetworkActive);
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 566ce4f..98b88cb 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -50,6 +50,7 @@
 import android.telephony.VoLteServiceState;
 import android.util.LocalLog;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.app.IBatteryStats;
 import com.android.internal.telephony.IOnSubscriptionsChangedListener;
 import com.android.internal.telephony.IPhoneStateListener;
@@ -82,7 +83,8 @@
  * Eventually we may want to remove the notion of dummy value but for now this
  * looks like the best approach.
  */
-class TelephonyRegistry extends ITelephonyRegistry.Stub {
+@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+public class TelephonyRegistry extends ITelephonyRegistry.Stub {
     private static final String TAG = "TelephonyRegistry";
     private static final boolean DBG = false; // STOPSHIP if true
     private static final boolean DBG_LOC = false; // STOPSHIP if true
@@ -99,6 +101,7 @@
 
         IPhoneStateListener callback;
         IOnSubscriptionsChangedListener onSubscriptionsChangedListenerCallback;
+        IOnSubscriptionsChangedListener onOpportunisticSubscriptionsChangedListenerCallback;
 
         int callerUid;
         int callerPid;
@@ -117,6 +120,10 @@
             return (onSubscriptionsChangedListenerCallback != null);
         }
 
+        boolean matchOnOpportunisticSubscriptionsChangedListener() {
+            return (onOpportunisticSubscriptionsChangedListenerCallback != null);
+        }
+
         boolean canReadCallLog() {
             try {
                 return TelephonyPermissions.checkReadCallLog(
@@ -131,7 +138,9 @@
             return "{callingPackage=" + callingPackage + " binder=" + binder
                     + " callback=" + callback
                     + " onSubscriptionsChangedListenererCallback="
-                                            + onSubscriptionsChangedListenerCallback
+                    + onSubscriptionsChangedListenerCallback
+                    + " onOpportunisticSubscriptionsChangedListenererCallback="
+                    + onOpportunisticSubscriptionsChangedListenerCallback
                     + " callerUid=" + callerUid + " subId=" + subId + " phoneId=" + phoneId
                     + " events=" + Integer.toHexString(events) + "}";
         }
@@ -147,7 +156,9 @@
 
     private final AppOpsManager mAppOps;
 
-    private boolean hasNotifySubscriptionInfoChangedOccurred = false;
+    private boolean mHasNotifySubscriptionInfoChangedOccurred = false;
+
+    private boolean mHasNotifyOpportunisticSubscriptionInfoChangedOccurred = false;
 
     private int mNumPhones;
 
@@ -315,7 +326,8 @@
     // calls go through a oneway interface and local calls going through a
     // handler before they get to app code.
 
-    TelephonyRegistry(Context context) {
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+    public TelephonyRegistry(Context context) {
         CellLocation  location = CellLocation.getEmpty();
 
         mContext = context;
@@ -407,7 +419,7 @@
                 log("listen oscl:  Register r=" + r);
             }
             // Always notify when registration occurs if there has been a notification.
-            if (hasNotifySubscriptionInfoChangedOccurred) {
+            if (mHasNotifySubscriptionInfoChangedOccurred) {
                 try {
                     if (VDBG) log("listen oscl: send to r=" + r);
                     r.onSubscriptionsChangedListenerCallback.onSubscriptionsChanged();
@@ -417,7 +429,7 @@
                     remove(r.binder);
                 }
             } else {
-                log("listen oscl: hasNotifySubscriptionInfoChangedOccurred==false no callback");
+                log("listen oscl: mHasNotifySubscriptionInfoChangedOccurred==false no callback");
             }
         }
     }
@@ -429,15 +441,61 @@
         remove(callback.asBinder());
     }
 
+
+    @Override
+    public void addOnOpportunisticSubscriptionsChangedListener(String callingPackage,
+            IOnSubscriptionsChangedListener callback) {
+        int callerUserId = UserHandle.getCallingUserId();
+        mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
+        if (VDBG) {
+            log("listen ooscl: E pkg=" + callingPackage + " myUserId=" + UserHandle.myUserId()
+                    + " callerUserId="  + callerUserId + " callback=" + callback
+                    + " callback.asBinder=" + callback.asBinder());
+        }
+
+        synchronized (mRecords) {
+            // register
+            IBinder b = callback.asBinder();
+            Record r = add(b);
+
+            if (r == null) {
+                return;
+            }
+
+            r.context = mContext;
+            r.onOpportunisticSubscriptionsChangedListenerCallback = callback;
+            r.callingPackage = callingPackage;
+            r.callerUid = Binder.getCallingUid();
+            r.callerPid = Binder.getCallingPid();
+            r.events = 0;
+            if (DBG) {
+                log("listen ooscl:  Register r=" + r);
+            }
+            // Always notify when registration occurs if there has been a notification.
+            if (mHasNotifyOpportunisticSubscriptionInfoChangedOccurred) {
+                try {
+                    if (VDBG) log("listen ooscl: send to r=" + r);
+                    r.onOpportunisticSubscriptionsChangedListenerCallback.onSubscriptionsChanged();
+                    if (VDBG) log("listen ooscl: sent to r=" + r);
+                } catch (RemoteException e) {
+                    if (VDBG) log("listen ooscl: remote exception sending to r=" + r + " e=" + e);
+                    remove(r.binder);
+                }
+            } else {
+                log("listen ooscl: hasNotifyOpptSubInfoChangedOccurred==false no callback");
+            }
+        }
+    }
+
     @Override
     public void notifySubscriptionInfoChanged() {
         if (VDBG) log("notifySubscriptionInfoChanged:");
         synchronized (mRecords) {
-            if (!hasNotifySubscriptionInfoChangedOccurred) {
+            if (!mHasNotifySubscriptionInfoChangedOccurred) {
                 log("notifySubscriptionInfoChanged: first invocation mRecords.size="
                         + mRecords.size());
             }
-            hasNotifySubscriptionInfoChangedOccurred = true;
+            mHasNotifySubscriptionInfoChangedOccurred = true;
             mRemoveList.clear();
             for (Record r : mRecords) {
                 if (r.matchOnSubscriptionsChangedListener()) {
@@ -456,6 +514,33 @@
     }
 
     @Override
+    public void notifyOpportunisticSubscriptionInfoChanged() {
+        if (VDBG) log("notifyOpptSubscriptionInfoChanged:");
+        synchronized (mRecords) {
+            if (!mHasNotifyOpportunisticSubscriptionInfoChangedOccurred) {
+                log("notifyOpptSubscriptionInfoChanged: first invocation mRecords.size="
+                        + mRecords.size());
+            }
+            mHasNotifyOpportunisticSubscriptionInfoChangedOccurred = true;
+            mRemoveList.clear();
+            for (Record r : mRecords) {
+                if (r.matchOnOpportunisticSubscriptionsChangedListener()) {
+                    try {
+                        if (VDBG) log("notifyOpptSubChanged: call oosc to r=" + r);
+                        r.onOpportunisticSubscriptionsChangedListenerCallback
+                                .onSubscriptionsChanged();
+                        if (VDBG) log("notifyOpptSubChanged: done oosc to r=" + r);
+                    } catch (RemoteException ex) {
+                        if (VDBG) log("notifyOpptSubChanged: RemoteException r=" + r);
+                        mRemoveList.add(r.binder);
+                    }
+                }
+            }
+            handleRemoveListLocked();
+        }
+    }
+
+    @Override
     public void listen(String pkgForDebug, IPhoneStateListener callback, int events,
             boolean notifyNow) {
         listenForSubscriber(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, pkgForDebug, callback,
diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java
index ae3946a..b2be5e6 100644
--- a/services/core/java/com/android/server/VibratorService.java
+++ b/services/core/java/com/android/server/VibratorService.java
@@ -27,47 +27,46 @@
 import android.hardware.input.InputManager;
 import android.hardware.vibrator.V1_0.EffectStrength;
 import android.icu.text.DateFormat;
+import android.media.AudioAttributes;
 import android.media.AudioManager;
-import android.os.PowerManager.ServiceType;
-import android.os.PowerSaveState;
 import android.os.BatteryStats;
+import android.os.Binder;
 import android.os.Handler;
+import android.os.IBinder;
 import android.os.IVibratorService;
 import android.os.PowerManager;
+import android.os.PowerManager.ServiceType;
 import android.os.PowerManagerInternal;
+import android.os.PowerSaveState;
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.ResultReceiver;
-import android.os.IBinder;
-import android.os.Binder;
 import android.os.ServiceManager;
 import android.os.ShellCallback;
 import android.os.ShellCommand;
 import android.os.SystemClock;
 import android.os.Trace;
 import android.os.UserHandle;
-import android.os.Vibrator;
 import android.os.VibrationEffect;
+import android.os.Vibrator;
 import android.os.WorkSource;
 import android.provider.Settings;
 import android.provider.Settings.SettingNotFoundException;
 import android.util.DebugUtils;
 import android.util.Slog;
 import android.util.SparseArray;
+import android.util.StatsLog;
 import android.view.InputDevice;
-import android.media.AudioAttributes;
 
 import com.android.internal.annotations.GuardedBy;
-import com.android.internal.app.IAppOpsService;
 import com.android.internal.app.IBatteryStats;
 import com.android.internal.util.DumpUtils;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
-import java.util.LinkedList;
-import java.util.List;
 import java.util.Date;
+import java.util.LinkedList;
 
 public class VibratorService extends IVibratorService.Stub
         implements InputManager.InputDeviceListener {
@@ -1048,6 +1047,8 @@
     private void noteVibratorOnLocked(int uid, long millis) {
         try {
             mBatteryStatsService.noteVibratorOn(uid, millis);
+            StatsLog.write_non_chained(StatsLog.VIBRATOR_STATE_CHANGED, uid, null,
+                    StatsLog.VIBRATOR_STATE_CHANGED__STATE__ON, millis);
             mCurVibUid = uid;
         } catch (RemoteException e) {
         }
@@ -1057,6 +1058,8 @@
         if (mCurVibUid >= 0) {
             try {
                 mBatteryStatsService.noteVibratorOff(mCurVibUid);
+                StatsLog.write_non_chained(StatsLog.VIBRATOR_STATE_CHANGED, mCurVibUid, null,
+                        StatsLog.VIBRATOR_STATE_CHANGED__STATE__OFF, 0);
             } catch (RemoteException e) { }
             mCurVibUid = -1;
         }
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 426a0c15..a392b51 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -1185,8 +1185,8 @@
                         final long accountId = accountEntry.getKey();
                         final Account account = accountEntry.getValue();
                         if (obsoleteAuthType.contains(account.type)) {
-                            Slog.w(TAG, "deleting account " + account.name + " because type "
-                                    + account.type
+                            Slog.w(TAG, "deleting account " + account.toSafeString()
+                                    + " because type " + account.type
                                     + "'s registered authenticator no longer exist.");
                             Map<String, Integer> packagesToVisibility =
                                     getRequestingPackages(account, accounts);
@@ -1326,7 +1326,8 @@
         Preconditions.checkState(Thread.holdsLock(mUsers), "mUsers lock must be held");
         List<Account> accountsToRemove = accounts.accountsDb.findCeAccountsNotInDe();
         if (!accountsToRemove.isEmpty()) {
-            Slog.i(TAG, "Accounts " + accountsToRemove + " were previously deleted while user "
+            Slog.i(TAG, accountsToRemove.size()
+                    + " accounts were previously deleted while user "
                     + accounts.userId + " was locked. Removing accounts from CE tables");
             logRecord(accounts, AccountsDb.DEBUG_ACTION_SYNC_DE_CE_ACCOUNTS,
                     AccountsDb.TABLE_ACCOUNTS);
@@ -1641,7 +1642,7 @@
             return;
         }
 
-        Slog.d(TAG, "Copying account " + account.name
+        Slog.d(TAG, "Copying account " + account.toSafeString()
                 + " from user " + userFrom + " to user " + userTo);
         long identityToken = clearCallingIdentity();
         try {
@@ -1777,8 +1778,8 @@
             return false;
         }
         if (!isLocalUnlockedUser(accounts.userId)) {
-            Log.w(TAG, "Account " + account + " cannot be added - user " + accounts.userId
-                    + " is locked. callingUid=" + callingUid);
+            Log.w(TAG, "Account " + account.toSafeString() + " cannot be added - user "
+                    + accounts.userId + " is locked. callingUid=" + callingUid);
             return false;
         }
         synchronized (accounts.dbLock) {
@@ -1786,19 +1787,19 @@
                 accounts.accountsDb.beginTransaction();
                 try {
                     if (accounts.accountsDb.findCeAccountId(account) >= 0) {
-                        Log.w(TAG, "insertAccountIntoDatabase: " + account
+                        Log.w(TAG, "insertAccountIntoDatabase: " + account.toSafeString()
                                 + ", skipping since the account already exists");
                         return false;
                     }
                     long accountId = accounts.accountsDb.insertCeAccount(account, password);
                     if (accountId < 0) {
-                        Log.w(TAG, "insertAccountIntoDatabase: " + account
+                        Log.w(TAG, "insertAccountIntoDatabase: " + account.toSafeString()
                                 + ", skipping the DB insert failed");
                         return false;
                     }
                     // Insert into DE table
                     if (accounts.accountsDb.insertDeAccount(account, accountId) < 0) {
-                        Log.w(TAG, "insertAccountIntoDatabase: " + account
+                        Log.w(TAG, "insertAccountIntoDatabase: " + account.toSafeString()
                                 + ", skipping the DB insert failed");
                         return false;
                     }
@@ -1806,7 +1807,8 @@
                         for (String key : extras.keySet()) {
                             final String value = extras.getString(key);
                             if (accounts.accountsDb.insertExtra(accountId, key, value) < 0) {
-                                Log.w(TAG, "insertAccountIntoDatabase: " + account
+                                Log.w(TAG, "insertAccountIntoDatabase: "
+                                        + account.toSafeString()
                                         + ", skipping since insertExtra failed for key " + key);
                                 return false;
                             }
@@ -2282,7 +2284,8 @@
         boolean isChanged = false;
         boolean userUnlocked = isLocalUnlockedUser(accounts.userId);
         if (!userUnlocked) {
-            Slog.i(TAG, "Removing account " + account + " while user "+ accounts.userId
+            Slog.i(TAG, "Removing account " + account.toSafeString()
+                    + " while user " + accounts.userId
                     + " is still locked. CE data will be removed later");
         }
         synchronized (accounts.dbLock) {
@@ -2907,7 +2910,7 @@
                 protected String toDebugString(long now) {
                     if (loginOptions != null) loginOptions.keySet();
                     return super.toDebugString(now) + ", getAuthToken"
-                            + ", " + account
+                            + ", " + account.toSafeString()
                             + ", authTokenType " + authTokenType
                             + ", loginOptions " + loginOptions
                             + ", notifyOnAuthFailure " + notifyOnAuthFailure;
@@ -3669,7 +3672,7 @@
                 @Override
                 protected String toDebugString(long now) {
                     return super.toDebugString(now) + ", confirmCredentials"
-                            + ", " + account;
+                            + ", " + account.toSafeString();
                 }
             }.bind();
         } finally {
@@ -3707,7 +3710,7 @@
                 protected String toDebugString(long now) {
                     if (loginOptions != null) loginOptions.keySet();
                     return super.toDebugString(now) + ", updateCredentials"
-                            + ", " + account
+                            + ", " + account.toSafeString()
                             + ", authTokenType " + authTokenType
                             + ", loginOptions " + loginOptions;
                 }
@@ -3771,7 +3774,7 @@
                         loginOptions.keySet();
                     return super.toDebugString(now)
                             + ", startUpdateCredentialsSession"
-                            + ", " + account
+                            + ", " + account.toSafeString()
                             + ", authTokenType " + authTokenType
                             + ", loginOptions " + loginOptions;
                 }
@@ -3812,7 +3815,7 @@
                 @Override
                 protected String toDebugString(long now) {
                     return super.toDebugString(now) + ", isCredentialsUpdateSuggested"
-                            + ", " + account;
+                            + ", " + account.toSafeString();
                 }
 
                 @Override
@@ -4369,7 +4372,7 @@
         accounts.accountsDb.deleteSharedAccount(account);
         long accountId = accounts.accountsDb.insertSharedAccount(account);
         if (accountId < 0) {
-            Log.w(TAG, "insertAccountIntoDatabase: " + account
+            Log.w(TAG, "insertAccountIntoDatabase: " + account.toSafeString()
                     + ", skipping the DB insert failed");
             return false;
         }
@@ -5208,7 +5211,7 @@
                     Process.SYSTEM_UID, null /* packageName */, false);
             fout.println("Accounts: " + accounts.length);
             for (Account account : accounts) {
-                fout.println("  " + account);
+                fout.println("  " + account.toSafeString());
             }
 
             // Add debug information.
@@ -5296,7 +5299,9 @@
         try {
             INotificationManager notificationManager = mInjector.getNotificationManager();
             try {
-                notificationManager.enqueueNotificationWithTag(packageName, packageName,
+                // The calling uid must match either the package or op package, so use an op
+                // package that matches the cleared calling identity.
+                notificationManager.enqueueNotificationWithTag(packageName, "android",
                         id.mTag, id.mId, notification, userId);
             } catch (RemoteException e) {
                 /* ignore - local call */
@@ -5611,7 +5616,8 @@
                 if (!permissionGranted && ActivityManager.isRunningInTestHarness()) {
                     // TODO: Skip this check when running automated tests. Replace this
                     // with a more general solution.
-                    Log.d(TAG, "no credentials permission for usage of " + account + ", "
+                    Log.d(TAG, "no credentials permission for usage of "
+                            + account.toSafeString() + ", "
                             + authTokenType + " by uid " + callerUid
                             + " but ignoring since device is in test harness.");
                     return true;
diff --git a/services/core/java/com/android/server/am/ActivityDisplay.java b/services/core/java/com/android/server/am/ActivityDisplay.java
index 3568a47..1866420 100644
--- a/services/core/java/com/android/server/am/ActivityDisplay.java
+++ b/services/core/java/com/android/server/am/ActivityDisplay.java
@@ -39,10 +39,13 @@
 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.DEBUG_TASKS;
 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.FindTaskResult;
 import static com.android.server.am.ActivityStackSupervisor.TAG_STATES;
+import static com.android.server.am.ActivityStackSupervisor.TAG_TASKS;
 
 import android.annotation.Nullable;
 import android.app.ActivityOptions;
@@ -121,6 +124,8 @@
 
     private DisplayWindowController mWindowContainerController;
 
+    private final FindTaskResult mTmpFindTaskResult = new FindTaskResult();
+
     @VisibleForTesting
     ActivityDisplay(ActivityStackSupervisor supervisor, int displayId) {
         this(supervisor, supervisor.mDisplayManager.getDisplay(displayId));
@@ -138,6 +143,10 @@
         return new DisplayWindowController(mDisplay, this);
     }
 
+    DisplayWindowController getWindowContainerController() {
+        return mWindowContainerController;
+    }
+
     void updateBounds() {
         mDisplay.getSize(mTmpDisplaySize);
         setBounds(0, 0, mTmpDisplaySize.x, mTmpDisplaySize.y);
@@ -287,7 +296,13 @@
     <T extends ActivityStack> T getOrCreateStack(@Nullable ActivityRecord r,
             @Nullable ActivityOptions options, @Nullable TaskRecord candidateTask, int activityType,
             boolean onTop) {
-        final int windowingMode = resolveWindowingMode(r, options, candidateTask, activityType);
+        // First preference is the windowing mode in the activity options if set.
+        int windowingMode = (options != null)
+                ? options.getLaunchWindowingMode() : WINDOWING_MODE_UNDEFINED;
+        // Validate that our desired windowingMode will work under the current conditions.
+        // UNDEFINED windowing mode is a valid result and means that the new stack will inherit
+        // it's display's windowing mode.
+        windowingMode = validateWindowingMode(windowingMode, r, candidateTask, activityType);
         return getOrCreateStack(windowingMode, activityType, onTop);
     }
 
@@ -299,7 +314,7 @@
      * Creates a stack matching the input windowing mode and activity type on this display.
      * @param windowingMode The windowing mode the stack should be created in. If
      *                      {@link WindowConfiguration#WINDOWING_MODE_UNDEFINED} then the stack will
-     *                      be created in {@link WindowConfiguration#WINDOWING_MODE_FULLSCREEN}.
+     *                      inherit it's parent's windowing mode.
      * @param activityType The activityType the stack should be created in. If
      *                     {@link WindowConfiguration#ACTIVITY_TYPE_UNDEFINED} then the stack will
      *                     be created in {@link WindowConfiguration#ACTIVITY_TYPE_STANDARD}.
@@ -442,6 +457,41 @@
     }
 
     /**
+     * Find task for putting the Activity in.
+     */
+    void findTaskLocked(final ActivityRecord r, final boolean isPreferredDisplay,
+            FindTaskResult result) {
+        mTmpFindTaskResult.clear();
+        for (int stackNdx = getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+            final ActivityStack stack = getChildAt(stackNdx);
+            if (!r.hasCompatibleActivityType(stack)) {
+                if (DEBUG_TASKS) {
+                    Slog.d(TAG_TASKS, "Skipping stack: (mismatch activity/stack) " + stack);
+                }
+                continue;
+            }
+
+            stack.findTaskLocked(r, mTmpFindTaskResult);
+            // It is possible to have tasks in multiple stacks with the same root affinity, so
+            // we should keep looking after finding an affinity match to see if there is a
+            // better match in another stack. Also, task affinity isn't a good enough reason
+            // to target a display which isn't the source of the intent, so skip any affinity
+            // matches not on the specified display.
+            if (mTmpFindTaskResult.mRecord != null) {
+                if (mTmpFindTaskResult.mIdealMatch) {
+                    result.setTo(mTmpFindTaskResult);
+                    return;
+                } else if (isPreferredDisplay) {
+                    // Note: since the traversing through the stacks is top down, the floating
+                    // tasks should always have lower priority than any affinity-matching tasks
+                    // in the fullscreen stacks
+                    result.setTo(mTmpFindTaskResult);
+                }
+            }
+        }
+    }
+
+    /**
      * Removes stacks in the input windowing modes from the system if they are of activity type
      * ACTIVITY_TYPE_STANDARD or ACTIVITY_TYPE_UNDEFINED
      */
@@ -545,7 +595,7 @@
                 if (!otherStack.inSplitScreenSecondaryWindowingMode()) {
                     continue;
                 }
-                otherStack.setWindowingMode(WINDOWING_MODE_FULLSCREEN, false /* animate */,
+                otherStack.setWindowingMode(WINDOWING_MODE_UNDEFINED, false /* animate */,
                         false /* showRecents */, false /* enteringSplitScreenMode */,
                         true /* deferEnsuringVisibility */);
             }
@@ -606,10 +656,14 @@
             return false;
         }
 
+        final int displayWindowingMode = getWindowingMode();
         if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
                 || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) {
             return supportsSplitScreen
-                    && WindowConfiguration.supportSplitScreenWindowingMode(activityType);
+                    && WindowConfiguration.supportSplitScreenWindowingMode(activityType)
+                    // Freeform windows and split-screen windows don't mix well, so prevent
+                    // split windowing modes on freeform displays.
+                    && displayWindowingMode != WINDOWING_MODE_FREEFORM;
         }
 
         if (!supportsFreeform && windowingMode == WINDOWING_MODE_FREEFORM) {
@@ -622,6 +676,16 @@
         return true;
     }
 
+    /**
+     * Resolves the windowing mode that an {@link ActivityRecord} would be in if started on this
+     * display with the provided parameters.
+     *
+     * @param r The ActivityRecord in question.
+     * @param options Options to start with.
+     * @param task The task within-which the activity would start.
+     * @param activityType The type of activity to start.
+     * @return The resolved (not UNDEFINED) windowing-mode that the activity would be in.
+     */
     int resolveWindowingMode(@Nullable ActivityRecord r, @Nullable ActivityOptions options,
             @Nullable TaskRecord task, int activityType) {
 
@@ -643,7 +707,9 @@
                 windowingMode = getWindowingMode();
             }
         }
-        return validateWindowingMode(windowingMode, r, task, activityType);
+        windowingMode = validateWindowingMode(windowingMode, r, task, activityType);
+        return windowingMode != WINDOWING_MODE_UNDEFINED
+                ? windowingMode : WINDOWING_MODE_FULLSCREEN;
     }
 
     /**
@@ -680,23 +746,21 @@
         final boolean inSplitScreenMode = hasSplitScreenPrimaryStack();
         if (!inSplitScreenMode
                 && windowingMode == WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY) {
-            // Switch to fullscreen windowing mode if we are not in split-screen mode and we are
+            // Switch to the display's windowing mode if we are not in split-screen mode and we are
             // trying to launch in split-screen secondary.
-            windowingMode = WINDOWING_MODE_FULLSCREEN;
-        } else if (inSplitScreenMode && windowingMode == WINDOWING_MODE_FULLSCREEN
+            windowingMode = WINDOWING_MODE_UNDEFINED;
+        } else if (inSplitScreenMode && (windowingMode == WINDOWING_MODE_FULLSCREEN
+                        || windowingMode == WINDOWING_MODE_UNDEFINED)
                 && supportsSplitScreen) {
             windowingMode = WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
         }
 
         if (windowingMode != WINDOWING_MODE_UNDEFINED
                 && isWindowingModeSupported(windowingMode, supportsMultiWindow, supportsSplitScreen,
-                supportsFreeform, supportsPip, activityType)) {
+                        supportsFreeform, supportsPip, activityType)) {
             return windowingMode;
         }
-        // Try to use the display's windowing mode otherwise fallback to fullscreen.
-        windowingMode = getWindowingMode();
-        return windowingMode != WINDOWING_MODE_UNDEFINED
-                ? windowingMode : WINDOWING_MODE_FULLSCREEN;
+        return WINDOWING_MODE_UNDEFINED;
     }
 
     /**
@@ -837,7 +901,7 @@
         if (mStacks.isEmpty() && mRemoved) {
             mWindowContainerController.removeContainer();
             mWindowContainerController = null;
-            mSupervisor.releaseActivityDisplayLocked(mDisplayId);
+            mSupervisor.removeChild(this);
         }
     }
 
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index b91a449..b64e8b8 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -2382,7 +2382,7 @@
                 }
             }
             int logSampleRate = Settings.Global.getInt(mContext.getContentResolver(),
-                    Settings.Global.HIDDEN_API_ACCESS_LOG_SAMPLING_RATE, -1);
+                    Settings.Global.HIDDEN_API_ACCESS_LOG_SAMPLING_RATE, 0x200);
             if (logSampleRate < 0 || logSampleRate > 0x10000) {
                 logSampleRate = -1;
             }
@@ -4349,6 +4349,7 @@
     private final void handleAppDiedLocked(ProcessRecord app,
             boolean restarting, boolean allowRestart) {
         int pid = app.pid;
+        final boolean clearLaunchStartTime = !restarting && app.removed && app.foregroundActivities;
         boolean kept = cleanUpApplicationRecordLocked(app, restarting, allowRestart, -1,
                 false /*replacingPid*/);
         if (!kept && !restarting) {
@@ -4388,6 +4389,19 @@
         } finally {
             mWindowManager.continueSurfaceLayout();
         }
+
+        // TODO (b/67683350)
+        // When an app process is removed, activities from the process may be relaunched. In the
+        // case of forceStopPackageLocked the activities are finished before any window is drawn,
+        // and the launch time is not cleared. This will be incorrectly used to calculate launch
+        // time for the next launched activity launched in the same windowing mode.
+        if (clearLaunchStartTime) {
+            final LaunchTimeTracker.Entry entry = mStackSupervisor
+                    .getLaunchTimeTracker().getEntry(mStackSupervisor.getWindowingMode());
+            if (entry != null) {
+                entry.mLaunchStartTime = 0;
+            }
+        }
     }
 
     private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
@@ -11927,7 +11941,9 @@
                         printed = true;
                     }
                     pw.print("    "); UserHandle.formatUid(pw, reg.uid);
-                    pw.print(" "); pw.print(reg.pkg); pw.print(":");
+                    pw.print(" "); pw.print(reg.pkg);
+                    final IUidObserver observer = mUidObservers.getRegisteredCallbackItem(i);
+                    pw.print(" "); pw.print(observer.getClass().getTypeName()); pw.print(":");
                     if ((reg.which&ActivityManager.UID_OBSERVER_IDLE) != 0) {
                         pw.print(" IDLE");
                     }
@@ -17061,7 +17077,7 @@
             activeInstr.mUiAutomationConnection = uiAutomationConnection;
             activeInstr.mResultClass = className;
 
-            boolean disableHiddenApiChecks = ai.usesNonSdkApi
+            boolean disableHiddenApiChecks = ai.usesNonSdkApi()
                     || (flags & INSTRUMENTATION_FLAG_DISABLE_HIDDEN_API_CHECKS) != 0;
             if (disableHiddenApiChecks) {
                 enforceCallingPermission(android.Manifest.permission.DISABLE_HIDDEN_API_CHECKS,
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 9de6875..b24c36a 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -16,6 +16,7 @@
 
 package com.android.server.am;
 
+import static android.app.ActivityManagerInternal.ALLOW_FULL_ONLY;
 import static android.app.ActivityTaskManager.RESIZE_MODE_SYSTEM;
 import static android.app.ActivityTaskManager.RESIZE_MODE_USER;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
@@ -302,7 +303,9 @@
         mSamplingInterval = 0;
         mAutoStop = false;
         mStreaming = false;
-        mUserId = defUser;
+        mUserId = mInternal.mUserController.handleIncomingUser(Binder.getCallingPid(),
+            Binder.getCallingUid(), defUser, false, ALLOW_FULL_ONLY,
+            "ActivityManagerShellCommand", null);
         mDisplayId = INVALID_DISPLAY;
         mWindowingMode = WINDOWING_MODE_UNDEFINED;
         mActivityType = ACTIVITY_TYPE_UNDEFINED;
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 78fef65..aa4e68d 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -347,6 +347,9 @@
     /** The attached Display's unique identifier, or -1 if detached */
     int mDisplayId;
 
+    /** Stores the override windowing-mode from before a transient mode change (eg. split) */
+    private int mRestoreOverrideWindowingMode = WINDOWING_MODE_UNDEFINED;
+
     private final SparseArray<Rect> mTmpBounds = new SparseArray<>();
     private final SparseArray<Rect> mTmpInsetBounds = new SparseArray<>();
     private final Rect mTmpRect2 = new Rect();
@@ -531,16 +534,48 @@
                 false /* enteringSplitScreenMode */, false /* deferEnsuringVisibility */);
     }
 
+    /**
+     * A transient windowing mode is one which activities enter into temporarily. Examples of this
+     * are Split window modes and pip. Non-transient modes are modes that displays can adopt.
+     *
+     * @param windowingMode the windowingMode to test for transient-ness.
+     * @return {@code true} if the windowing mode is transient, {@code false} otherwise.
+     */
+    private static boolean isTransientWindowingMode(int windowingMode) {
+        // TODO(b/114842032): add PIP if/when it uses mode transitions instead of task reparenting
+        return windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
+                || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
+    }
+
+    /**
+     * Specialization of {@link #setWindowingMode(int)} for this subclass.
+     *
+     * @param preferredWindowingMode the preferred windowing mode. This may not be honored depending
+     *         on the state of things. For example, WINDOWING_MODE_UNDEFINED will resolve to the
+     *         previous non-transient mode if this stack is currently in a transient mode.
+     * @param animate Can be used to prevent animation.
+     * @param showRecents Controls whether recents is shown on the other side of a split while
+     *         entering split mode.
+     * @param enteringSplitScreenMode {@code true} if entering split mode.
+     * @param deferEnsuringVisibility Whether visibility updates are deferred. This is set when
+     *         many operations (which can effect visibility) are being performed in bulk.
+     */
     void setWindowingMode(int preferredWindowingMode, boolean animate, boolean showRecents,
             boolean enteringSplitScreenMode, boolean deferEnsuringVisibility) {
         final boolean creating = mWindowContainerController == null;
         final int currentMode = getWindowingMode();
+        final int currentOverrideMode = getOverrideWindowingMode();
         final ActivityDisplay display = getDisplay();
         final TaskRecord topTask = topTask();
         final ActivityStack splitScreenStack = display.getSplitScreenPrimaryStack();
-        mTmpOptions.setLaunchWindowingMode(preferredWindowingMode);
-
         int windowingMode = preferredWindowingMode;
+        if (preferredWindowingMode == WINDOWING_MODE_UNDEFINED
+                && isTransientWindowingMode(currentMode)) {
+            // Leaving a transient mode. Interpret UNDEFINED as "restore"
+            windowingMode = mRestoreOverrideWindowingMode;
+        }
+        mTmpOptions.setLaunchWindowingMode(windowingMode);
+
         // 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.
         if (!creating) {
@@ -550,8 +585,8 @@
         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;
+            // we want to leave split-screen mode.
+            windowingMode = mRestoreOverrideWindowingMode;
         }
 
         final boolean alreadyInSplitScreenMode = display.hasSplitScreenPrimaryStack();
@@ -570,21 +605,33 @@
                 // doesn't support split-screen mode, go ahead an dismiss split-screen and display a
                 // warning toast about it.
                 mService.getTaskChangeNotificationController().notifyActivityDismissingDockedStack();
-                display.getSplitScreenPrimaryStack().setWindowingMode(WINDOWING_MODE_FULLSCREEN,
+                display.getSplitScreenPrimaryStack().setWindowingMode(WINDOWING_MODE_UNDEFINED,
                         false /* animate */, false /* showRecents */,
                         false /* enteringSplitScreenMode */, true /* deferEnsuringVisibility */);
             }
         }
 
         if (currentMode == windowingMode) {
-            // You are already in the window mode silly...
+            // You are already in the window mode, so we can skip most of the work below. However,
+            // it's possible that we have inherited the current windowing mode from a parent. So,
+            // fulfill this method's contract by setting the override mode directly.
+            getOverrideConfiguration().windowConfiguration.setWindowingMode(windowingMode);
             return;
         }
 
         final WindowManagerService wm = mService.mWindowManager;
         final ActivityRecord topActivity = getTopActivity();
 
-        if (sendNonResizeableNotification && windowingMode != WINDOWING_MODE_FULLSCREEN
+        // For now, assume that the Stack's windowing mode is what will actually be used
+        // by it's activities. In the future, there may be situations where this doesn't
+        // happen; so at that point, this message will need to handle that.
+        int likelyResolvedMode = windowingMode;
+        if (windowingMode == WINDOWING_MODE_UNDEFINED) {
+            final ConfigurationContainer parent = getParent();
+            likelyResolvedMode = parent != null ? parent.getWindowingMode()
+                    : WINDOWING_MODE_FULLSCREEN;
+        }
+        if (sendNonResizeableNotification && likelyResolvedMode != WINDOWING_MODE_FULLSCREEN
                 && topActivity != null && topActivity.isNonResizableOrForcedResizable()
                 && !topActivity.noDisplay) {
             // Inform the user that they are starting an app that may not work correctly in
@@ -625,6 +672,9 @@
                         + " while there is already one isn't currently supported");
                 //return;
             }
+            if (isTransientWindowingMode(windowingMode) && !isTransientWindowingMode(currentMode)) {
+                mRestoreOverrideWindowingMode = currentOverrideMode;
+            }
 
             mTmpRect2.setEmpty();
             if (windowingMode != WINDOWING_MODE_FULLSCREEN) {
@@ -674,13 +724,6 @@
             // display, so they should be considered compatible.
             activityType = ACTIVITY_TYPE_STANDARD;
         }
-        final ActivityDisplay display = getDisplay();
-        if (display != null && activityType == ACTIVITY_TYPE_STANDARD
-                    && windowingMode == WINDOWING_MODE_UNDEFINED) {
-            // Standard activity types will mostly take on the windowing mode of the display if one
-            // isn't specified, so look-up a compatible stack based on the display's windowing mode.
-            windowingMode = display.getWindowingMode();
-        }
         return super.isCompatible(windowingMode, activityType);
     }
 
@@ -775,6 +818,11 @@
                 true /* includingParents */);
     }
 
+    void positionChildWindowContainerAtBottom(TaskRecord child) {
+        mWindowContainerController.positionChildAtBottom(child.getWindowContainerController(),
+                true /* includingParents */);
+    }
+
     /**
      * Returns whether to defer the scheduling of the multi-window mode.
      */
@@ -1080,7 +1128,7 @@
          * behind the home stack. Exit split screen in this case.
          */
         if (getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
-            setWindowingMode(WINDOWING_MODE_FULLSCREEN);
+            setWindowingMode(WINDOWING_MODE_UNDEFINED);
         }
 
         getDisplay().positionChildAtBottom(this);
@@ -1171,8 +1219,8 @@
                 //dump();
                 if (DEBUG_TASKS) Slog.d(TAG_TASKS,
                         "For Intent " + intent + " bringing to top: " + r.intent);
-                result.r = r;
-                result.matchedByRootAffinity = false;
+                result.mRecord = r;
+                result.mIdealMatch = true;
                 break;
             } else if (affinityIntent != null && affinityIntent.getComponent() != null &&
                     affinityIntent.getComponent().compareTo(cls) == 0 &&
@@ -1181,18 +1229,18 @@
                 //dump();
                 if (DEBUG_TASKS) Slog.d(TAG_TASKS,
                         "For Intent " + intent + " bringing to top: " + r.intent);
-                result.r = r;
-                result.matchedByRootAffinity = false;
+                result.mRecord = r;
+                result.mIdealMatch = true;
                 break;
             } else if (!isDocument && !taskIsDocument
-                    && result.r == null && task.rootAffinity != null) {
+                    && result.mRecord == null && task.rootAffinity != null) {
                 if (task.rootAffinity.equals(target.taskAffinity)) {
                     if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Found matching affinity candidate!");
                     // It is possible for multiple tasks to have the same root affinity especially
                     // if they are in separate stacks. We save off this candidate, but keep looking
                     // to see if there is a better candidate.
-                    result.r = r;
-                    result.matchedByRootAffinity = true;
+                    result.mRecord = r;
+                    result.mIdealMatch = false;
                 }
             } else if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Not a match: " + task);
         }
@@ -2859,8 +2907,7 @@
         final int position = getAdjustedPositionForTask(task, mTaskHistory.size(), starting);
         mTaskHistory.add(position, task);
         updateTaskMovement(task, true);
-        mWindowContainerController.positionChildAtTop(task.getWindowContainerController(),
-                true /* includingParents */);
+        positionChildWindowContainerAtTop(task);
     }
 
     private void insertTaskAtBottom(TaskRecord task) {
@@ -2869,8 +2916,7 @@
         final int position = getAdjustedPositionForTask(task, 0, null);
         mTaskHistory.add(position, task);
         updateTaskMovement(task, true);
-        mWindowContainerController.positionChildAtBottom(task.getWindowContainerController(),
-                true /* includingParents */);
+        positionChildWindowContainerAtBottom(task);
     }
 
     void startActivityLocked(ActivityRecord r, ActivityRecord focusedTopActivity,
@@ -3141,8 +3187,7 @@
                     p.reparent(targetTask, 0 /* position - bottom */, "resetTargetTaskIfNeeded");
                 }
 
-                mWindowContainerController.positionChildAtBottom(
-                        targetTask.getWindowContainerController(), false /* includingParents */);
+                positionChildWindowContainerAtBottom(targetTask);
                 replyChainEnd = -1;
             } else if (forceReset || finishOnTaskLaunch || clearWhenTaskReset) {
                 // If the activity should just be removed -- either
@@ -3277,8 +3322,7 @@
                         if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Pulling activity " + p
                                 + " from " + srcPos + " in to resetting task " + task);
                     }
-                    mWindowContainerController.positionChildAtTop(
-                            task.getWindowContainerController(), true /* includingParents */);
+                    positionChildWindowContainerAtTop(task);
 
                     // Now we've moved it in to place...  but what if this is
                     // a singleTop activity and we have put it on top of another
@@ -5239,8 +5283,7 @@
         addTask(task, toTop ? MAX_VALUE : 0, true /* schedulePictureInPictureModeChange */, reason);
         if (toTop) {
             // TODO: figure-out a way to remove this call.
-            mWindowContainerController.positionChildAtTop(task.getWindowContainerController(),
-                    true /* includingParents */);
+            positionChildWindowContainerAtTop(task);
         }
     }
 
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 4cfcbee..310898e 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -176,7 +176,10 @@
 import com.android.server.am.ActivityStack.ActivityState;
 import com.android.server.wm.ActivityTaskManagerInternal.SleepToken;
 import com.android.server.wm.ConfigurationContainer;
+import com.android.server.wm.DisplayWindowController;
 import com.android.server.wm.PinnedStackWindowController;
+import com.android.server.wm.RootWindowContainerController;
+import com.android.server.wm.RootWindowContainerListener;
 import com.android.server.wm.WindowManagerService;
 
 import java.io.FileDescriptor;
@@ -190,7 +193,7 @@
 import java.util.Set;
 
 public class ActivityStackSupervisor extends ConfigurationContainer implements DisplayListener,
-        RecentTasks.Callbacks {
+        RecentTasks.Callbacks, RootWindowContainerListener {
     private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStackSupervisor" : TAG_AM;
     private static final String TAG_FOCUS = TAG + POSTFIX_FOCUS;
     private static final String TAG_IDLE = TAG + POSTFIX_IDLE;
@@ -416,9 +419,14 @@
     /** Stack id of the front stack when user switched, indexed by userId. */
     SparseIntArray mUserStackInFront = new SparseIntArray(2);
 
-    // TODO: There should be an ActivityDisplayController coordinating am/wm interaction.
-    /** Mapping from displayId to display current state */
-    private final SparseArray<ActivityDisplay> mActivityDisplays = new SparseArray<>();
+    /** Reference to default display so we can quickly look it up. */
+    private ActivityDisplay mDefaultDisplay;
+
+    /**
+     * List of displays which contain activities, sorted by z-order.
+     * The last entry in the list is the topmost.
+     */
+    private final ArrayList<ActivityDisplay> mActivityDisplays = new ArrayList<>();
 
     private final SparseArray<IntArray> mDisplayAccessUIDs = new SparseArray<>();
 
@@ -453,7 +461,7 @@
 
     @Override
     protected ActivityDisplay getChildAt(int index) {
-        return mActivityDisplays.valueAt(index);
+        return mActivityDisplays.get(index);
     }
 
     @Override
@@ -525,17 +533,21 @@
     }
 
     static class FindTaskResult {
-        ActivityRecord r;
-        boolean matchedByRootAffinity;
-    }
-    private final FindTaskResult mTmpFindTaskResult = new FindTaskResult();
+        ActivityRecord mRecord;
+        boolean mIdealMatch;
 
-    /**
-     * Temp storage for display ids sorted in focus order.
-     * Maps position to id. Using {@link SparseIntArray} instead of {@link ArrayList} because
-     * it's more efficient, as the number of displays is usually small.
-     */
-    private SparseIntArray mTmpOrderedDisplayIds = new SparseIntArray();
+        void clear() {
+            mRecord = null;
+            mIdealMatch = false;
+        }
+
+        void setTo(FindTaskResult result) {
+            mRecord = result.mRecord;
+            mIdealMatch = result.mIdealMatch;
+        }
+    }
+
+    private final FindTaskResult mTmpFindTaskResult = new FindTaskResult();
 
     /**
      * Used to keep track whether app visibilities got changed since the last pause. Useful to
@@ -569,6 +581,8 @@
 
     private boolean mInitialized;
 
+    private RootWindowContainerController mWindowContainerController;
+
     /**
      * Description of a request to start a new activity, which has been held
      * due to app switches being disabled.
@@ -612,6 +626,11 @@
         mService = service;
     }
 
+    @VisibleForTesting
+    void setWindowContainerController(RootWindowContainerController controller) {
+        mWindowContainerController = controller;
+    }
+
     public void initialize() {
         if (mInitialized) {
             return;
@@ -664,38 +683,57 @@
     void setWindowManager(WindowManagerService wm) {
         mWindowManager = wm;
         getKeyguardController().setWindowManager(wm);
+        setWindowContainerController(new RootWindowContainerController(this));
 
-        mDisplayManager =
-                (DisplayManager) mService.mContext.getSystemService(Context.DISPLAY_SERVICE);
+        mDisplayManager = mService.mContext.getSystemService(DisplayManager.class);
         mDisplayManager.registerDisplayListener(this, null);
         mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
 
-        Display[] displays = mDisplayManager.getDisplays();
+        final Display[] displays = mDisplayManager.getDisplays();
         for (int displayNdx = displays.length - 1; displayNdx >= 0; --displayNdx) {
             final Display display = displays[displayNdx];
-            ActivityDisplay activityDisplay = new ActivityDisplay(this, display);
-            mActivityDisplays.put(display.getDisplayId(), activityDisplay);
+            final ActivityDisplay activityDisplay = new ActivityDisplay(this, display);
+            if (activityDisplay.mDisplayId == DEFAULT_DISPLAY) {
+                mDefaultDisplay = activityDisplay;
+            }
+            addChild(activityDisplay, ActivityDisplay.POSITION_TOP);
             calculateDefaultMinimalSizeOfResizeableTasks(activityDisplay);
         }
 
         final ActivityDisplay defaultDisplay = getDefaultDisplay();
         mHomeStack = mLastFocusedStack = defaultDisplay.getOrCreateStack(
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, ON_TOP);
+        positionChildAt(defaultDisplay, ActivityDisplay.POSITION_TOP);
+    }
+
+    /** Change the z-order of the given display. */
+    private void positionChildAt(ActivityDisplay display, int position) {
+        if (position >= mActivityDisplays.size()) {
+            position = mActivityDisplays.size() - 1;
+        } else if (position < 0) {
+            position = 0;
+        }
+
+        if (mActivityDisplays.isEmpty()) {
+            mActivityDisplays.add(display);
+        } else if (mActivityDisplays.get(position) != display) {
+            mActivityDisplays.remove(display);
+            mActivityDisplays.add(position, display);
+        }
+    }
+
+    @Override
+    public void onChildPositionChanged(DisplayWindowController childController, int position) {
+        // Assume AM lock is held from positionChildAt of controller in each hierarchy.
+        final ActivityDisplay display = getActivityDisplay(childController.getDisplayId());
+        if (display != null) {
+            positionChildAt(display, position);
+        }
     }
 
     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();
+        for (int i = mActivityDisplays.size() - 1; i >= 0; --i) {
+            final ActivityStack focusedStack = mActivityDisplays.get(i).getFocusedStack();
             if (focusedStack != null) {
                 return focusedStack;
             }
@@ -718,16 +756,8 @@
         }
         // 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;
-            }
+        for (int i = mActivityDisplays.size() - 1; i >= 0; --i) {
+            final ActivityDisplay display = mActivityDisplays.get(i);
             final ActivityRecord resumedActivityOnDisplay = display.getResumedActivity();
             if (resumedActivityOnDisplay != null) {
                 return resumedActivityOnDisplay;
@@ -848,7 +878,7 @@
 
         int numDisplays = mActivityDisplays.size();
         for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
-            final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+            final ActivityDisplay display = mActivityDisplays.get(displayNdx);
             for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
                 final ActivityStack stack = display.getChildAt(stackNdx);
                 final TaskRecord task = stack.taskForIdLocked(id);
@@ -905,7 +935,7 @@
     ActivityRecord isInAnyStackLocked(IBinder token) {
         int numDisplays = mActivityDisplays.size();
         for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
-            final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+            final ActivityDisplay display = mActivityDisplays.get(displayNdx);
             for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
                 final ActivityStack stack = display.getChildAt(stackNdx);
                 final ActivityRecord r = stack.isInStackLocked(token);
@@ -947,7 +977,7 @@
         mWindowManager.deferSurfaceLayout();
         try {
             for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
-                final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+                final ActivityDisplay display = mActivityDisplays.get(displayNdx);
                 for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
                     final ActivityStack stack = display.getChildAt(stackNdx);
                     final List<TaskRecord> tasks = stack.getAllTasks();
@@ -1011,7 +1041,7 @@
         final String processName = app.processName;
         boolean didSomething = false;
         for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
-            final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+            final ActivityDisplay display = mActivityDisplays.get(displayNdx);
             for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
                 final ActivityStack stack = display.getChildAt(stackNdx);
                 if (!isTopDisplayFocusedStack(stack)) {
@@ -1046,7 +1076,7 @@
 
     boolean allResumedActivitiesIdle() {
         for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
-            final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+            final ActivityDisplay display = mActivityDisplays.get(displayNdx);
             for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
                 final ActivityStack stack = display.getChildAt(stackNdx);
                 if (!isTopDisplayFocusedStack(stack) || stack.numActivities() == 0) {
@@ -1067,7 +1097,7 @@
 
     boolean allResumedActivitiesComplete() {
         for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
-            final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+            final ActivityDisplay display = mActivityDisplays.get(displayNdx);
             for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
                 final ActivityStack stack = display.getChildAt(stackNdx);
                 if (isTopDisplayFocusedStack(stack)) {
@@ -1090,7 +1120,7 @@
     private boolean allResumedActivitiesVisible() {
         boolean foundResumed = false;
         for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
-            final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+            final ActivityDisplay display = mActivityDisplays.get(displayNdx);
             for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
                 final ActivityStack stack = display.getChildAt(stackNdx);
                 final ActivityRecord r = stack.getResumedActivity();
@@ -1116,7 +1146,7 @@
     boolean pauseBackStacks(boolean userLeaving, ActivityRecord resuming, boolean dontWait) {
         boolean someActivityPaused = false;
         for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
-            someActivityPaused |= mActivityDisplays.valueAt(displayNdx)
+            someActivityPaused |= mActivityDisplays.get(displayNdx)
                     .pauseBackStacks(userLeaving, resuming, dontWait);
         }
         return someActivityPaused;
@@ -1125,7 +1155,7 @@
     boolean allPausedActivitiesComplete() {
         boolean pausing = true;
         for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
-            final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+            final ActivityDisplay display = mActivityDisplays.get(displayNdx);
             for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
                 final ActivityStack stack = display.getChildAt(stackNdx);
                 final ActivityRecord r = stack.mPausingActivity;
@@ -1145,7 +1175,7 @@
 
     void cancelInitializingActivities() {
         for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
-            final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+            final ActivityDisplay display = mActivityDisplays.get(displayNdx);
             for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
                 final ActivityStack stack = display.getChildAt(stackNdx);
                 stack.cancelInitializingActivities();
@@ -1266,17 +1296,8 @@
         }
 
         // Look in other non-focused and non-home stacks.
-        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;
-            }
+        for (int i = mActivityDisplays.size() - 1; i >= 0; --i) {
+            final ActivityDisplay display = mActivityDisplays.get(i);
 
             // TODO: We probably want to consider the top fullscreen stack as we could have a pinned
             // stack on top.
@@ -1757,7 +1778,7 @@
             boolean noResumedActivities = true;
             boolean allFocusedProcessesDiffer = true;
             for (int displayNdx = 0; displayNdx < mActivityDisplays.size(); ++displayNdx) {
-                final ActivityDisplay activityDisplay = mActivityDisplays.valueAt(displayNdx);
+                final ActivityDisplay activityDisplay = mActivityDisplays.get(displayNdx);
                 final ActivityRecord resumedActivity = activityDisplay.getResumedActivity();
                 final WindowProcessController resumedActivityProcess =
                     resumedActivity == null ? null : resumedActivity.app;
@@ -1927,7 +1948,7 @@
     void updateUIDsPresentOnDisplay() {
         mDisplayAccessUIDs.clear();
         for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
-            final ActivityDisplay activityDisplay = mActivityDisplays.valueAt(displayNdx);
+            final ActivityDisplay activityDisplay = mActivityDisplays.get(displayNdx);
             // Only bother calculating the whitelist for private displays
             if (activityDisplay.isPrivate()) {
                 mDisplayAccessUIDs.append(
@@ -2173,7 +2194,7 @@
     boolean handleAppDiedLocked(WindowProcessController app) {
         boolean hasVisibleActivities = false;
         for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
-            final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+            final ActivityDisplay display = mActivityDisplays.get(displayNdx);
             for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
                 final ActivityStack stack = display.getChildAt(stackNdx);
                 hasVisibleActivities |= stack.handleAppDiedLocked(app);
@@ -2184,7 +2205,7 @@
 
     void closeSystemDialogsLocked() {
         for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
-            final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+            final ActivityDisplay display = mActivityDisplays.get(displayNdx);
             for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
                 final ActivityStack stack = display.getChildAt(stackNdx);
                 stack.closeSystemDialogsLocked();
@@ -2213,7 +2234,7 @@
             boolean doit, boolean evenPersistent, int userId) {
         boolean didSomething = false;
         for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
-            final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+            final ActivityDisplay display = mActivityDisplays.get(displayNdx);
             for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
                 final ActivityStack stack = display.getChildAt(stackNdx);
                 if (stack.finishDisabledPackageActivitiesLocked(
@@ -2235,7 +2256,7 @@
         // hosted by the process that is actually still the foreground.
         WindowProcessController fgApp = null;
         for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
-            final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+            final ActivityDisplay display = mActivityDisplays.get(displayNdx);
             for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
                 final ActivityStack stack = display.getChildAt(stackNdx);
                 if (isTopDisplayFocusedStack(stack)) {
@@ -2277,7 +2298,7 @@
 
         // 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 ActivityDisplay display = mActivityDisplays.get(displayNdx);
             final ActivityStack focusedStack = display.getFocusedStack();
             if (focusedStack == null) {
                 continue;
@@ -2296,7 +2317,7 @@
 
     void updateActivityApplicationInfoLocked(ApplicationInfo aInfo) {
         for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
-            final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+            final ActivityDisplay display = mActivityDisplays.get(displayNdx);
             for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
                 final ActivityStack stack = display.getChildAt(stackNdx);
                 stack.updateActivityApplicationInfoLocked(aInfo);
@@ -2314,7 +2335,7 @@
         TaskRecord finishedTask = null;
         ActivityStack focusedStack = getTopDisplayFocusedStack();
         for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
-            final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+            final ActivityDisplay display = mActivityDisplays.get(displayNdx);
             // It is possible that request to finish activity might also remove its task and stack,
             // so we need to be careful with indexes in the loop and check child count every time.
             for (int stackNdx = 0; stackNdx < display.getChildCount(); ++stackNdx) {
@@ -2330,7 +2351,7 @@
 
     void finishVoiceTask(IVoiceInteractionSession session) {
         for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
-            final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+            final ActivityDisplay display = mActivityDisplays.get(displayNdx);
             final int numStacks = display.getChildCount();
             for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
                 final ActivityStack stack = display.getChildAt(stackNdx);
@@ -2417,7 +2438,7 @@
 
     protected <T extends ActivityStack> T getStack(int stackId) {
         for (int i = mActivityDisplays.size() - 1; i >= 0; --i) {
-            final T stack = mActivityDisplays.valueAt(i).getStack(stackId);
+            final T stack = mActivityDisplays.get(i).getStack(stackId);
             if (stack != null) {
                 return stack;
             }
@@ -2428,7 +2449,7 @@
     /** @see ActivityDisplay#getStack(int, int) */
     private <T extends ActivityStack> T getStack(int windowingMode, int activityType) {
         for (int i = mActivityDisplays.size() - 1; i >= 0; --i) {
-            final T stack = mActivityDisplays.valueAt(i).getStack(windowingMode, activityType);
+            final T stack = mActivityDisplays.get(i).getStack(windowingMode, activityType);
             if (stack != null) {
                 return stack;
             }
@@ -2642,19 +2663,12 @@
         }
 
         // 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) {
+        for (int i = mActivityDisplays.size() - 1; i >= 0; --i) {
+            final ActivityDisplay display = mActivityDisplays.get(i);
+            if (display == preferredDisplay) {
                 // 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;
-            }
             final ActivityStack nextFocusableStack = display.getNextFocusableStack(currentFocus,
                     ignoreCurrent);
             if (nextFocusableStack != null) {
@@ -2676,13 +2690,12 @@
      * @return Next valid {@link ActivityStack}, null if not found.
      */
     ActivityStack getNextValidLaunchStackLocked(@NonNull ActivityRecord r, int currentFocus) {
-        mWindowManager.getDisplaysInFocusOrder(mTmpOrderedDisplayIds);
-        for (int i = mTmpOrderedDisplayIds.size() - 1; i >= 0; --i) {
-            final int displayId = mTmpOrderedDisplayIds.get(i);
-            if (displayId == currentFocus) {
+        for (int i = mActivityDisplays.size() - 1; i >= 0; --i) {
+            final ActivityDisplay display = mActivityDisplays.get(i);
+            if (display.mDisplayId == currentFocus) {
                 continue;
             }
-            final ActivityStack stack = getValidLaunchStackOnDisplay(displayId, r,
+            final ActivityStack stack = getValidLaunchStackOnDisplay(display.mDisplayId, r,
                     null /* options */);
             if (stack != null) {
                 return stack;
@@ -2815,8 +2828,7 @@
                     if (!otherStack.inSplitScreenSecondaryWindowingMode()) {
                         continue;
                     }
-                    resizeStackLocked(otherStack, null, null, null, PRESERVE_WINDOWS,
-                            true /* allowResizeInDockedMode */, DEFER_RESUME);
+                    otherStack.setWindowingMode(WINDOWING_MODE_UNDEFINED);
                 }
 
                 // Also disable docked stack resizing since we have manually adjusted the
@@ -3081,13 +3093,13 @@
      */
     void removeStacksInWindowingModes(int... windowingModes) {
         for (int i = mActivityDisplays.size() - 1; i >= 0; --i) {
-            mActivityDisplays.valueAt(i).removeStacksInWindowingModes(windowingModes);
+            mActivityDisplays.get(i).removeStacksInWindowingModes(windowingModes);
         }
     }
 
     void removeStacksWithActivityTypes(int... activityTypes) {
         for (int i = mActivityDisplays.size() - 1; i >= 0; --i) {
-            mActivityDisplays.valueAt(i).removeStacksWithActivityTypes(activityTypes);
+            mActivityDisplays.get(i).removeStacksWithActivityTypes(activityTypes);
         }
     }
 
@@ -3457,50 +3469,39 @@
         return true;
     }
 
-    ActivityRecord findTaskLocked(ActivityRecord r, int displayId) {
-        mTmpFindTaskResult.r = null;
-        mTmpFindTaskResult.matchedByRootAffinity = false;
-        ActivityRecord affinityMatch = null;
+    ActivityRecord findTaskLocked(ActivityRecord r, int preferredDisplayId) {
         if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Looking for task of " + r);
-        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 (!r.hasCompatibleActivityType(stack)) {
-                    if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping stack: (mismatch activity/stack) "
-                            + stack);
-                    continue;
-                }
-                stack.findTaskLocked(r, mTmpFindTaskResult);
-                // It is possible to have tasks in multiple stacks with the same root affinity, so
-                // we should keep looking after finding an affinity match to see if there is a
-                // better match in another stack. Also, task affinity isn't a good enough reason
-                // to target a display which isn't the source of the intent, so skip any affinity
-                // matches not on the specified display.
-                if (mTmpFindTaskResult.r != null) {
-                    if (!mTmpFindTaskResult.matchedByRootAffinity) {
-                        return mTmpFindTaskResult.r;
-                    } else if (mTmpFindTaskResult.r.getDisplayId() == displayId) {
-                        // Note: since the traversing through the stacks is top down, the floating
-                        // tasks should always have lower priority than any affinity-matching tasks
-                        // in the fullscreen stacks
-                        affinityMatch = mTmpFindTaskResult.r;
-                    } else if (DEBUG_TASKS && mTmpFindTaskResult.matchedByRootAffinity) {
-                        Slog.d(TAG_TASKS, "Skipping match on different display "
-                                + mTmpFindTaskResult.r.getDisplayId() + " " + displayId);
-                    }
-                }
+        mTmpFindTaskResult.clear();
+
+        // Looking up task on preferred display first
+        final ActivityDisplay preferredDisplay = getActivityDisplay(preferredDisplayId);
+        if (preferredDisplay != null) {
+            preferredDisplay.findTaskLocked(r, true /* isPreferredDisplay */, mTmpFindTaskResult);
+            if (mTmpFindTaskResult.mIdealMatch) {
+                return mTmpFindTaskResult.mRecord;
             }
         }
 
-        if (DEBUG_TASKS && affinityMatch == null) Slog.d(TAG_TASKS, "No task found");
-        return affinityMatch;
+        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+            final ActivityDisplay display = mActivityDisplays.get(displayNdx);
+            if (display.mDisplayId == preferredDisplayId) {
+                continue;
+            }
+
+            display.findTaskLocked(r, false /* isPreferredDisplay */, mTmpFindTaskResult);
+            if (mTmpFindTaskResult.mIdealMatch) {
+                return mTmpFindTaskResult.mRecord;
+            }
+        }
+
+        if (DEBUG_TASKS && mTmpFindTaskResult.mRecord == null) Slog.d(TAG_TASKS, "No task found");
+        return mTmpFindTaskResult.mRecord;
     }
 
     ActivityRecord findActivityLocked(Intent intent, ActivityInfo info,
             boolean compareIntentFilters) {
         for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
-            final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+            final ActivityDisplay display = mActivityDisplays.get(displayNdx);
             for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
                 final ActivityStack stack = display.getChildAt(stackNdx);
                 final ActivityRecord ar = stack.findActivityLocked(
@@ -3515,7 +3516,7 @@
 
     boolean hasAwakeDisplay() {
         for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
-            final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+            final ActivityDisplay display = mActivityDisplays.get(displayNdx);
             if (!display.shouldSleep()) {
                 return true;
             }
@@ -3543,7 +3544,7 @@
 
     void prepareForShutdownLocked() {
         for (int i = 0; i < mActivityDisplays.size(); i++) {
-            createSleepTokenLocked("shutdown", mActivityDisplays.keyAt(i));
+            createSleepTokenLocked("shutdown", mActivityDisplays.get(i).mDisplayId);
         }
     }
 
@@ -3586,7 +3587,7 @@
     void applySleepTokensLocked(boolean applyToStacks) {
         for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
             // Set the sleeping state of the display.
-            final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+            final ActivityDisplay display = mActivityDisplays.get(displayNdx);
             final boolean displayShouldSleep = display.shouldSleep();
             if (displayShouldSleep == display.isSleeping()) {
                 continue;
@@ -3666,7 +3667,7 @@
     private boolean putStacksToSleepLocked(boolean allowDelay, boolean shuttingDown) {
         boolean allSleep = true;
         for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
-            final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+            final ActivityDisplay display = mActivityDisplays.get(displayNdx);
             for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
                 final ActivityStack stack = display.getChildAt(stackNdx);
                 if (allowDelay) {
@@ -3697,7 +3698,7 @@
 
     void handleAppCrashLocked(WindowProcessController app) {
         for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
-            final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+            final ActivityDisplay display = mActivityDisplays.get(displayNdx);
             for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
                 final ActivityStack stack = display.getChildAt(stackNdx);
                 stack.handleAppCrashLocked(app);
@@ -3746,7 +3747,7 @@
         try {
             // First the front stacks. In case any are not fullscreen and are in front of home.
             for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
-                final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+                final ActivityDisplay display = mActivityDisplays.get(displayNdx);
                 for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
                     final ActivityStack stack = display.getChildAt(stackNdx);
                     stack.ensureActivitiesVisibleLocked(starting, configChanges, preserveWindows,
@@ -3760,7 +3761,7 @@
 
     void addStartingWindowsForVisibleActivities(boolean taskSwitch) {
         for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
-            final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+            final ActivityDisplay display = mActivityDisplays.get(displayNdx);
             for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
                 final ActivityStack stack = display.getChildAt(stackNdx);
                 stack.addStartingWindowsForVisibleActivities(taskSwitch);
@@ -3778,7 +3779,7 @@
         }
         mTaskLayersChanged = false;
         for (int displayNdx = 0; displayNdx < mActivityDisplays.size(); displayNdx++) {
-            final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+            final ActivityDisplay display = mActivityDisplays.get(displayNdx);
             int baseLayer = 0;
             for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
                 final ActivityStack stack = display.getChildAt(stackNdx);
@@ -3789,7 +3790,7 @@
 
     void clearOtherAppTimeTrackers(AppTimeTracker except) {
         for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
-            final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+            final ActivityDisplay display = mActivityDisplays.get(displayNdx);
             for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
                 final ActivityStack stack = display.getChildAt(stackNdx);
                 stack.clearOtherAppTimeTrackers(except);
@@ -3799,7 +3800,7 @@
 
     void scheduleDestroyAllActivities(WindowProcessController app, String reason) {
         for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
-            final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+            final ActivityDisplay display = mActivityDisplays.get(displayNdx);
             for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
                 final ActivityStack stack = display.getChildAt(stackNdx);
                 stack.scheduleDestroyActivities(app, reason);
@@ -3818,7 +3819,7 @@
         // let's iterate through the tasks and release the oldest one.
         final int numDisplays = mActivityDisplays.size();
         for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
-            final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+            final ActivityDisplay display = mActivityDisplays.get(displayNdx);
             final int stackCount = display.getChildCount();
             // Step through all stacks starting from behind, to hit the oldest things first.
             for (int stackNdx = 0; stackNdx < stackCount; stackNdx++) {
@@ -3849,7 +3850,7 @@
 
         mStartingUsers.add(uss);
         for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
-            final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+            final ActivityDisplay display = mActivityDisplays.get(displayNdx);
             for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
                 final ActivityStack stack = display.getChildAt(stackNdx);
                 stack.switchUserLocked(userId);
@@ -3953,7 +3954,7 @@
 
     void validateTopActivitiesLocked() {
         for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
-            final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+            final ActivityDisplay display = mActivityDisplays.get(displayNdx);
             for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
                 final ActivityStack stack = display.getChildAt(stackNdx);
                 final ActivityRecord r = stack.topRunningActivityLocked();
@@ -3984,7 +3985,7 @@
 
     public void dumpDisplays(PrintWriter pw) {
         for (int i = mActivityDisplays.size() - 1; i >= 0; --i) {
-            final ActivityDisplay display = mActivityDisplays.valueAt(i);
+            final ActivityDisplay display = mActivityDisplays.get(i);
             pw.print("[id:" + display.mDisplayId + " stacks:");
             display.dumpStacks(pw);
             pw.print("]");
@@ -3998,7 +3999,7 @@
         pw.println("mCurTaskIdForUser=" + mCurTaskIdForUser);
         pw.print(prefix); pw.println("mUserStackInFront=" + mUserStackInFront);
         for (int i = mActivityDisplays.size() - 1; i >= 0; --i) {
-            final ActivityDisplay display = mActivityDisplays.valueAt(i);
+            final ActivityDisplay display = mActivityDisplays.get(i);
             display.dump(pw, prefix);
         }
         if (!mWaitingForActivityVisible.isEmpty()) {
@@ -4018,7 +4019,7 @@
         final long token = proto.start(fieldId);
         super.writeToProto(proto, CONFIGURATION_CONTAINER, false /* trim */);
         for (int displayNdx = 0; displayNdx < mActivityDisplays.size(); ++displayNdx) {
-            final ActivityDisplay activityDisplay = mActivityDisplays.valueAt(displayNdx);
+            final ActivityDisplay activityDisplay = mActivityDisplays.get(displayNdx);
             activityDisplay.writeToProto(proto, DISPLAYS);
         }
         getKeyguardController().writeToProto(proto, KEYGUARD_CONTROLLER);
@@ -4047,7 +4048,7 @@
         pw.print(prefix); pw.println("Display override configurations:");
         final int displayCount = mActivityDisplays.size();
         for (int i = 0; i < displayCount; i++) {
-            final ActivityDisplay activityDisplay = mActivityDisplays.valueAt(i);
+            final ActivityDisplay activityDisplay = mActivityDisplays.get(i);
             pw.print(prefix); pw.print("  "); pw.print(activityDisplay.mDisplayId); pw.print(": ");
                     pw.println(activityDisplay.getOverrideConfiguration());
         }
@@ -4065,7 +4066,7 @@
             ArrayList<ActivityRecord> activities = new ArrayList<>();
             int numDisplays = mActivityDisplays.size();
             for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
-                final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+                final ActivityDisplay display = mActivityDisplays.get(displayNdx);
                 for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
                     final ActivityStack stack = display.getChildAt(stackNdx);
                     if (!dumpVisibleStacksOnly || stack.shouldBeVisible(null)) {
@@ -4096,11 +4097,11 @@
             boolean dumpClient, String dumpPackage) {
         boolean printed = false;
         boolean needSep = false;
-        for (int displayNdx = 0; displayNdx < mActivityDisplays.size(); ++displayNdx) {
-            ActivityDisplay activityDisplay = mActivityDisplays.valueAt(displayNdx);
+        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+            ActivityDisplay activityDisplay = mActivityDisplays.get(displayNdx);
             pw.print("Display #"); pw.print(activityDisplay.mDisplayId);
                     pw.println(" (activities from top to bottom):");
-            final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+            final ActivityDisplay display = mActivityDisplays.get(displayNdx);
             for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
                 final ActivityStack stack = display.getChildAt(stackNdx);
                 pw.println();
@@ -4299,12 +4300,18 @@
 
     // TODO: Look into consolidating with getActivityDisplayOrCreateLocked()
     ActivityDisplay getActivityDisplay(int displayId) {
-        return mActivityDisplays.get(displayId);
+        for (int i = mActivityDisplays.size() - 1; i >= 0; --i) {
+            final ActivityDisplay activityDisplay = mActivityDisplays.get(i);
+            if (activityDisplay.mDisplayId == displayId) {
+                return activityDisplay;
+            }
+        }
+        return null;
     }
 
     // TODO(multi-display): Look at all callpoints to make sure they make sense in multi-display.
     ActivityDisplay getDefaultDisplay() {
-        return mActivityDisplays.get(DEFAULT_DISPLAY);
+        return mDefaultDisplay;
     }
 
     /**
@@ -4313,7 +4320,7 @@
      */
     // TODO: Look into consolidating with getActivityDisplay()
     ActivityDisplay getActivityDisplayOrCreateLocked(int displayId) {
-        ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
+        ActivityDisplay activityDisplay = getActivityDisplay(displayId);
         if (activityDisplay != null) {
             return activityDisplay;
         }
@@ -4328,15 +4335,23 @@
         }
         // The display hasn't been added to ActivityManager yet, create a new record now.
         activityDisplay = new ActivityDisplay(this, display);
-        attachDisplay(activityDisplay);
+        addChild(activityDisplay, ActivityDisplay.POSITION_BOTTOM);
         calculateDefaultMinimalSizeOfResizeableTasks(activityDisplay);
         mWindowManager.onDisplayAdded(displayId);
         return activityDisplay;
     }
 
     @VisibleForTesting
-    void attachDisplay(ActivityDisplay display) {
-        mActivityDisplays.put(display.mDisplayId, display);
+    void addChild(ActivityDisplay activityDisplay, int position) {
+        positionChildAt(activityDisplay, position);
+        mWindowContainerController.positionChildAt(
+                activityDisplay.getWindowContainerController(), position);
+    }
+
+    void removeChild(ActivityDisplay activityDisplay) {
+        // The caller must tell the controller of {@link ActivityDisplay} to release its container
+        // {@link DisplayContent}. That is done in {@link ActivityDisplay#releaseSelfIfNeeded}).
+        mActivityDisplays.remove(activityDisplay);
     }
 
     private void calculateDefaultMinimalSizeOfResizeableTasks(ActivityDisplay display) {
@@ -4351,7 +4366,7 @@
         }
 
         synchronized (mService.mGlobalLock) {
-            final ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
+            final ActivityDisplay activityDisplay = getActivityDisplay(displayId);
             if (activityDisplay == null) {
                 return;
             }
@@ -4362,14 +4377,9 @@
         }
     }
 
-    void releaseActivityDisplayLocked(int displayId) {
-        mActivityDisplays.remove(displayId);
-    }
-
-
     private void handleDisplayChanged(int displayId) {
         synchronized (mService.mGlobalLock) {
-            ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
+            ActivityDisplay activityDisplay = getActivityDisplay(displayId);
             // TODO: The following code block should be moved into {@link ActivityDisplay}.
             if (activityDisplay != null) {
                 // The window policy is responsible for stopping activities on the default display
@@ -4392,7 +4402,7 @@
     }
 
     SleepToken createSleepTokenLocked(String tag, int displayId) {
-        ActivityDisplay display = mActivityDisplays.get(displayId);
+        final ActivityDisplay display = getActivityDisplay(displayId);
         if (display == null) {
             throw new IllegalArgumentException("Invalid display: " + displayId);
         }
@@ -4406,7 +4416,7 @@
     private void removeSleepTokenLocked(SleepTokenImpl token) {
         mSleepTokens.remove(token);
 
-        ActivityDisplay display = mActivityDisplays.get(token.mDisplayId);
+        final ActivityDisplay display = getActivityDisplay(token.mDisplayId);
         if (display != null) {
             display.mAllSleepTokens.remove(token);
             if (display.mAllSleepTokens.isEmpty()) {
@@ -4429,7 +4439,7 @@
 
     private StackInfo getStackInfo(ActivityStack stack) {
         final int displayId = stack.mDisplayId;
-        final ActivityDisplay display = mActivityDisplays.get(displayId);
+        final ActivityDisplay display = getActivityDisplay(displayId);
         StackInfo info = new StackInfo();
         stack.getWindowContainerBounds(info.bounds);
         info.displayId = displayId;
@@ -4483,7 +4493,7 @@
     ArrayList<StackInfo> getAllStackInfosLocked() {
         ArrayList<StackInfo> list = new ArrayList<>();
         for (int displayNdx = 0; displayNdx < mActivityDisplays.size(); ++displayNdx) {
-            final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+            final ActivityDisplay display = mActivityDisplays.get(displayNdx);
             for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
                 final ActivityStack stack = display.getChildAt(stackNdx);
                 list.add(getStackInfo(stack));
@@ -4765,14 +4775,12 @@
     }
 
     ActivityStack findStackBehind(ActivityStack stack) {
-        // TODO(multi-display): We are only looking for stacks on the default display.
-        final ActivityDisplay display = mActivityDisplays.get(DEFAULT_DISPLAY);
-        if (display == null) {
-            return null;
-        }
-        for (int i = display.getChildCount() - 1; i >= 0; i--) {
-            if (display.getChildAt(i) == stack && i > 0) {
-                return display.getChildAt(i - 1);
+        final ActivityDisplay display = getActivityDisplay(stack.mDisplayId);
+        if (display != null) {
+            for (int i = display.getChildCount() - 1; i >= 0; i--) {
+                if (display.getChildAt(i) == stack && i > 0) {
+                    return display.getChildAt(i - 1);
+                }
             }
         }
         throw new IllegalStateException("Failed to find a stack behind stack=" + stack
@@ -4904,7 +4912,7 @@
         final ActivityStack topFocusedStack = getTopDisplayFocusedStack();
         // Traverse all displays.
         for (int i = mActivityDisplays.size() - 1; i >= 0; i--) {
-            final ActivityDisplay display = mActivityDisplays.valueAt(i);
+            final ActivityDisplay display = mActivityDisplays.get(i);
             // Traverse all stacks on a display.
             for (int j = display.getChildCount() - 1; j >= 0; --j) {
                 final ActivityStack stack = display.getChildAt(j);
diff --git a/services/core/java/com/android/server/am/ActivityTaskManagerService.java b/services/core/java/com/android/server/am/ActivityTaskManagerService.java
index 11f8bb1..212844a 100644
--- a/services/core/java/com/android/server/am/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityTaskManagerService.java
@@ -27,17 +27,7 @@
 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.ActivityManagerInternal.ALLOW_FULL_ONLY;
 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;
@@ -51,15 +41,19 @@
 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
 import static android.content.pm.PackageManager.FEATURE_ACTIVITIES_ON_SECONDARY_DISPLAYS;
 import static android.content.pm.PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEMENT;
+import static android.content.pm.PackageManager.FEATURE_PC;
 import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE;
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 import static android.content.res.Configuration.UI_MODE_TYPE_TELEVISION;
 import static android.os.Build.VERSION_CODES.N;
 import static android.os.Process.SYSTEM_UID;
+import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
 import static android.provider.Settings.Global.ALWAYS_FINISH_ACTIVITIES;
 import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT;
 import static android.provider.Settings.Global.DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES;
 import static android.provider.Settings.Global.DEVELOPMENT_FORCE_RTL;
+import static android.provider.Settings.Global.HIDE_ERROR_DIALOGS;
+import static android.provider.Settings.System.FONT_SCALE;
 import static android.service.voice.VoiceInteractionSession.SHOW_SOURCE_APPLICATION;
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.Display.INVALID_DISPLAY;
@@ -68,6 +62,7 @@
 import static android.view.WindowManager.TRANSIT_TASK_IN_PLACE;
 import static android.view.WindowManager.TRANSIT_TASK_OPEN;
 import static android.view.WindowManager.TRANSIT_TASK_TO_FRONT;
+
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ALL;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONFIGURATION;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_FOCUS;
@@ -86,13 +81,13 @@
 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 android.app.ActivityManagerInternal.ALLOW_FULL_ONLY;
 import static com.android.server.am.ActivityManagerService.ANIMATE;
 import static com.android.server.am.ActivityManagerService.MY_PID;
 import static com.android.server.am.ActivityManagerService.SEND_LOCALE_TO_MOUNT_DAEMON_MSG;
 import static com.android.server.am.ActivityManagerService.STOCK_PM_FLAGS;
 import static com.android.server.am.ActivityManagerService.UPDATE_CONFIGURATION_MSG;
 import static com.android.server.am.ActivityManagerService.checkComponentPermission;
+import static com.android.server.am.ActivityManagerService.dumpStackTraces;
 import static com.android.server.am.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
 import static com.android.server.am.ActivityStackSupervisor.DEFER_RESUME;
 import static com.android.server.am.ActivityStackSupervisor.MATCH_TASK_IN_STACKS_ONLY;
@@ -100,10 +95,16 @@
 import static com.android.server.am.ActivityStackSupervisor.ON_TOP;
 import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
 import static com.android.server.am.ActivityStackSupervisor.REMOVE_FROM_RECENTS;
+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.am.TaskRecord.INVALID_TASK_ID;
 import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_DONT_LOCK;
 import static com.android.server.am.TaskRecord.REPARENT_KEEP_STACK_AT_FRONT;
 import static com.android.server.am.TaskRecord.REPARENT_LEAVE_STACK_IN_PLACE;
+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 com.android.server.wm.RecentsAnimationController.REORDER_KEEP_IN_PLACE;
 import static com.android.server.wm.RecentsAnimationController.REORDER_MOVE_TO_ORIGINAL_POSITION;
 
@@ -118,26 +119,8 @@
 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.Dialog;
 import android.app.IActivityController;
 import android.app.IActivityTaskManager;
 import android.app.IApplicationThread;
@@ -157,15 +140,19 @@
 import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Context;
+import android.content.DialogInterface;
 import android.content.IIntentSender;
 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.PackageManagerInternal;
 import android.content.pm.ParceledListSlice;
 import android.content.pm.ResolveInfo;
 import android.content.res.Configuration;
 import android.content.res.Resources;
+import android.database.ContentObserver;
 import android.graphics.Bitmap;
 import android.graphics.Point;
 import android.graphics.Rect;
@@ -177,16 +164,22 @@
 import android.os.FileUtils;
 import android.os.Handler;
 import android.os.IBinder;
+import android.os.IUserManager;
 import android.os.LocaleList;
 import android.os.Looper;
 import android.os.Message;
 import android.os.PersistableBundle;
+import android.os.PowerManager;
 import android.os.RemoteException;
+import android.os.ServiceManager;
 import android.os.StrictMode;
 import android.os.SystemClock;
 import android.os.SystemProperties;
+import android.os.Trace;
 import android.os.UpdateLock;
 import android.os.UserHandle;
+import android.os.UserManager;
+import android.os.WorkSource;
 import android.provider.Settings;
 import android.service.voice.IVoiceInteractionSession;
 import android.service.voice.VoiceInteractionManagerInternal;
@@ -197,7 +190,6 @@
 import android.util.EventLog;
 import android.util.Log;
 import android.util.Slog;
-
 import android.util.SparseArray;
 import android.util.SparseIntArray;
 import android.util.StatsLog;
@@ -206,22 +198,30 @@
 import android.view.IRecentsAnimationRunner;
 import android.view.RemoteAnimationAdapter;
 import android.view.RemoteAnimationDefinition;
+import android.view.WindowManager;
 
+import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.app.AssistUtils;
+import com.android.internal.app.IAppOpsService;
 import com.android.internal.app.IVoiceInteractor;
 import com.android.internal.app.ProcessMap;
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.os.logging.MetricsLoggerWrapper;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.internal.os.logging.MetricsLoggerWrapper;
 import com.android.internal.policy.IKeyguardDismissCallback;
 import com.android.internal.policy.KeyguardDismissCallback;
 import com.android.internal.util.Preconditions;
+import com.android.server.AppOpsService;
 import com.android.server.AttributeCache;
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
+import com.android.server.SystemServiceManager;
 import com.android.server.Watchdog;
+import com.android.server.pm.UserManagerService;
+import com.android.server.uri.UriGrantsManagerInternal;
 import com.android.server.vr.VrManagerInternal;
+import com.android.server.wm.ActivityTaskManagerInternal;
 import com.android.server.wm.PinnedStackWindowController;
 import com.android.server.wm.WindowManagerService;
 
@@ -3338,7 +3338,7 @@
                     }
                 }
 
-                stack.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
+                stack.setWindowingMode(WINDOWING_MODE_UNDEFINED);
             }
         } finally {
             Binder.restoreCallingIdentity(ident);
diff --git a/services/core/java/com/android/server/am/BaseErrorDialog.java b/services/core/java/com/android/server/am/BaseErrorDialog.java
index 347a357..cd4d6a3 100644
--- a/services/core/java/com/android/server/am/BaseErrorDialog.java
+++ b/services/core/java/com/android/server/am/BaseErrorDialog.java
@@ -33,7 +33,7 @@
     private boolean mConsuming = true;
 
     public BaseErrorDialog(Context context) {
-        super(context, com.android.internal.R.style.Theme_Dialog_AppError);
+        super(context, com.android.internal.R.style.Theme_DeviceDefault_Dialog_AppError);
         context.assertRuntimeOverlayThemable();
 
         getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index bc23316..0a7e127 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -414,7 +414,11 @@
         if (state == BroadcastRecord.IDLE) {
             Slog.w(TAG, "finishReceiver [" + mQueueName + "] called but state is IDLE");
         }
-        r.duration[r.nextReceiver - 1] = finishTime - r.receiverTime;
+        // If we're abandoning this broadcast before any receivers were actually spun up,
+        // nextReceiver is zero; in which case time-to-process bookkeeping doesn't apply.
+        if (r.nextReceiver > 0) {
+            r.duration[r.nextReceiver - 1] = finishTime - r.receiverTime;
+        }
         r.receiver = null;
         r.intent.setComponent(null);
         if (r.curApp != null && r.curApp.curReceivers.contains(r)) {
diff --git a/services/core/java/com/android/server/am/OWNERS b/services/core/java/com/android/server/am/OWNERS
index f60c5c3..79c98e5 100644
--- a/services/core/java/com/android/server/am/OWNERS
+++ b/services/core/java/com/android/server/am/OWNERS
@@ -4,7 +4,6 @@
 jsharkey@google.com
 hackbod@google.com
 omakoto@google.com
-fkupolov@google.com
 ctate@google.com
 huiyu@google.com
 mwachens@google.com
@@ -28,7 +27,4 @@
 michaelwr@google.com
 narayan@google.com
 
-per-file GlobalSettingsToPropertiesMapper.java=fkupolov@google.com
-per-file GlobalSettingsToPropertiesMapper.java=omakoto@google.com
-per-file GlobalSettingsToPropertiesMapper.java=svetoslavganov@google.com
-per-file GlobalSettingsToPropertiesMapper.java=yamasani@google.com
+per-file GlobalSettingsToPropertiesMapper.java = omakoto@google.com, svetoslavganov@google.com, yamasani@google.com
diff --git a/services/core/java/com/android/server/am/RunningTasks.java b/services/core/java/com/android/server/am/RunningTasks.java
index 7008cee..d878f51 100644
--- a/services/core/java/com/android/server/am/RunningTasks.java
+++ b/services/core/java/com/android/server/am/RunningTasks.java
@@ -16,13 +16,9 @@
 
 package com.android.server.am;
 
-import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
-import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
-
 import android.app.ActivityManager.RunningTaskInfo;
 import android.app.WindowConfiguration.ActivityType;
 import android.app.WindowConfiguration.WindowingMode;
-import android.util.SparseArray;
 
 import java.util.ArrayList;
 import java.util.Comparator;
@@ -45,7 +41,7 @@
     private final ArrayList<TaskRecord> mTmpStackTasks = new ArrayList<>();
 
     void getTasks(int maxNum, List<RunningTaskInfo> list, @ActivityType int ignoreActivityType,
-            @WindowingMode int ignoreWindowingMode, SparseArray<ActivityDisplay> activityDisplays,
+            @WindowingMode int ignoreWindowingMode, ArrayList<ActivityDisplay> activityDisplays,
             int callingUid, boolean allowed) {
         // Return early if there are no tasks to fetch
         if (maxNum <= 0) {
@@ -56,7 +52,7 @@
         mTmpSortedSet.clear();
         final int numDisplays = activityDisplays.size();
         for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
-            final ActivityDisplay display = activityDisplays.valueAt(displayNdx);
+            final ActivityDisplay display = activityDisplays.get(displayNdx);
             for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
                 final ActivityStack stack = display.getChildAt(stackNdx);
                 mTmpStackTasks.clear();
diff --git a/services/core/java/com/android/server/am/TEST_MAPPING b/services/core/java/com/android/server/am/TEST_MAPPING
index 4ca96a1..b817669 100644
--- a/services/core/java/com/android/server/am/TEST_MAPPING
+++ b/services/core/java/com/android/server/am/TEST_MAPPING
@@ -49,6 +49,20 @@
           "exclude-annotation": "androidx.test.filters.FlakyTest"
         }
       ]
+    },
+    {
+      "name": "WmTests",
+      "options": [
+        {
+          "include-filter": "com.android.server.am."
+        },
+        {
+          "include-annotation": "android.platform.test.annotations.Presubmit"
+        },
+        {
+          "exclude-annotation": "androidx.test.filters.FlakyTest"
+        }
+      ]
     }
   ],
   "postsubmit": [
@@ -65,6 +79,14 @@
           "include-filter": "com.android.server.am."
         }
       ]
+    },
+    {
+      "name": "WmTests",
+      "options": [
+        {
+          "include-filter": "com.android.server.am."
+        }
+      ]
     }
   ]
 }
diff --git a/services/core/java/com/android/server/biometrics/AuthenticationClient.java b/services/core/java/com/android/server/biometrics/AuthenticationClient.java
index 06462a2..36e7cba 100644
--- a/services/core/java/com/android/server/biometrics/AuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/AuthenticationClient.java
@@ -21,7 +21,6 @@
 import android.hardware.biometrics.BiometricConstants;
 import android.hardware.biometrics.BiometricPrompt;
 import android.hardware.biometrics.IBiometricPromptReceiver;
-import android.hardware.fingerprint.FingerprintManager;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
@@ -45,17 +44,16 @@
     public static final int LOCKOUT_TIMED = 1;
     public static final int LOCKOUT_PERMANENT = 2;
 
+    private final BiometricAuthenticator mAuthenticator;
     // Callback mechanism received from the client
-    // (BiometricPrompt -> FingerprintManager -> FingerprintService -> AuthenticationClient)
+    // (BiometricPrompt -> BiometricPromptService -> <Biometric>Service -> AuthenticationClient)
     private IBiometricPromptReceiver mDialogReceiverFromClient;
     private Bundle mBundle;
     private IStatusBarService mStatusBarService;
     private boolean mInLockout;
-    // TODO: BiometricManager, after other biometric modalities are introduced.
-    private final FingerprintManager mFingerprintManager;
     protected boolean mDialogDismissed;
 
-    // Receives events from SystemUI and handles them before forwarding them to FingerprintDialog
+    // Receives events from SystemUI and handles them before forwarding them to BiometricDialog
     protected IBiometricPromptReceiver mDialogReceiver = new IBiometricPromptReceiver.Stub() {
         @Override // binder call
         public void onDialogDismissed(int reason) {
@@ -81,7 +79,7 @@
     public abstract void onStart();
 
     /**
-     * This method is called when a fingerprint is authenticated or authentication is stopped
+     * This method is called when a biometric is authenticated or authentication is stopped
      * (cancelled by the user, or an error such as lockout has occurred).
      */
     public abstract void onStop();
@@ -90,15 +88,15 @@
             BiometricService.DaemonWrapper daemon, long halDeviceId, IBinder token,
             BiometricService.ServiceListener listener, int targetUserId, int groupId, long opId,
             boolean restricted, String owner, Bundle bundle,
-            IBiometricPromptReceiver dialogReceiver, IStatusBarService statusBarService) {
+            IBiometricPromptReceiver dialogReceiver, IStatusBarService statusBarService,
+            BiometricAuthenticator authenticator) {
         super(context, metrics, daemon, halDeviceId, token, listener, targetUserId, groupId,
                 restricted, owner);
         mOpId = opId;
         mBundle = bundle;
         mDialogReceiverFromClient = dialogReceiver;
         mStatusBarService = statusBarService;
-        mFingerprintManager = (FingerprintManager) getContext()
-                .getSystemService(Context.FINGERPRINT_SERVICE);
+        mAuthenticator = authenticator;
         mHandler = new Handler(Looper.getMainLooper());
     }
 
@@ -118,7 +116,7 @@
             try {
                 if (acquiredInfo != BiometricConstants.BIOMETRIC_ACQUIRED_GOOD) {
                     mStatusBarService.onBiometricHelp(
-                            mFingerprintManager.getAcquiredString(acquiredInfo, vendorCode));
+                            mAuthenticator.getAcquiredString(acquiredInfo, vendorCode));
                 }
                 return false; // acquisition continues
             } catch (RemoteException e) {
@@ -139,15 +137,15 @@
     public boolean onError(long deviceId, int error, int vendorCode) {
         if (mDialogDismissed) {
             // If user cancels authentication, the application has already received the
-            // FingerprintManager.FINGERPRINT_ERROR_USER_CANCELED message from onDialogDismissed()
-            // and stopped the fingerprint hardware, so there is no need to send a
-            // FingerprintManager.FINGERPRINT_ERROR_CANCELED message.
+            // ERROR_USER_CANCELED message from onDialogDismissed()
+            // and stopped the biometric hardware, so there is no need to send a
+            // ERROR_CANCELED message.
             return true;
         }
         if (mBundle != null) {
             try {
                 mStatusBarService.onBiometricError(
-                        mFingerprintManager.getErrorString(error, vendorCode));
+                        mAuthenticator.getErrorString(error, vendorCode));
             } catch (RemoteException e) {
                 Slog.e(getLogTag(), "Remote exception when sending error", e);
             }
@@ -160,15 +158,14 @@
             boolean authenticated) {
         boolean result = false;
 
-        // If the fingerprint dialog is showing, notify authentication succeeded
-        // TODO: this goes to BiometricPrompt, split between biometric modalities
+        // If the biometric dialog is showing, notify authentication succeeded
         if (mBundle != null) {
             try {
                 if (authenticated) {
                     mStatusBarService.onBiometricAuthenticated();
                 } else {
                     mStatusBarService.onBiometricHelp(getContext().getResources().getString(
-                            com.android.internal.R.string.fingerprint_not_recognized));
+                            com.android.internal.R.string.biometric_not_recognized));
                 }
             } catch (RemoteException e) {
                 Slog.e(getLogTag(), "Failed to notify Authenticated:", e);
@@ -223,7 +220,7 @@
                     // Send the lockout message to the system dialog
                     if (mBundle != null) {
                         mStatusBarService.onBiometricError(
-                                mFingerprintManager.getErrorString(errorCode, 0 /* vendorCode */));
+                                mAuthenticator.getErrorString(errorCode, 0 /* vendorCode */));
                         mHandler.postDelayed(() -> {
                             try {
                                 listener.onError(getHalDeviceId(), errorCode, 0 /* vendorCode */);
@@ -243,7 +240,7 @@
             if (listener != null) {
                 vibrateSuccess();
             }
-            result |= true; // we have a valid fingerprint, done
+            result |= true; // we have a valid biometric, done
             resetFailedAttempts();
             onStop();
         }
@@ -270,9 +267,10 @@
             // If authenticating with system dialog, show the dialog
             if (mBundle != null) {
                 try {
-                    mStatusBarService.showBiometricDialog(mBundle, mDialogReceiver);
+                    mStatusBarService.showBiometricDialog(mBundle, mDialogReceiver,
+                            mAuthenticator.getType());
                 } catch (RemoteException e) {
-                    Slog.e(getLogTag(), "Unable to show fingerprint dialog", e);
+                    Slog.e(getLogTag(), "Unable to show biometric dialog", e);
                 }
             }
         } catch (RemoteException e) {
@@ -297,7 +295,8 @@
                 Slog.w(getLogTag(), "stopAuthentication failed, result=" + result);
                 return result;
             }
-            if (DEBUG) Slog.w(getLogTag(), "client " + getOwnerString() + " is no longer authenticating");
+            if (DEBUG) Slog.w(getLogTag(), "client " + getOwnerString() +
+                    " is no longer authenticating");
         } catch (RemoteException e) {
             Slog.e(getLogTag(), "stopAuthentication failed", e);
             return ERROR_ESRCH;
@@ -310,7 +309,7 @@
                 try {
                     mStatusBarService.hideBiometricDialog();
                 } catch (RemoteException e) {
-                    Slog.e(getLogTag(), "Unable to hide fingerprint dialog", e);
+                    Slog.e(getLogTag(), "Unable to hide biometric dialog", e);
                 }
             }
         }
diff --git a/services/core/java/com/android/server/biometrics/BiometricPromptService.java b/services/core/java/com/android/server/biometrics/BiometricPromptService.java
index 29eda8b..d1371d1 100644
--- a/services/core/java/com/android/server/biometrics/BiometricPromptService.java
+++ b/services/core/java/com/android/server/biometrics/BiometricPromptService.java
@@ -41,7 +41,6 @@
 import android.util.Slog;
 
 import com.android.internal.R;
-import com.android.internal.os.SomeArgs;
 import com.android.server.SystemService;
 
 import java.util.ArrayList;
@@ -133,6 +132,12 @@
             // AppOps and foreground check.
             checkPermission();
 
+            if (token == null || receiver == null || opPackageName == null || bundle == null
+                    || dialogReceiver == null) {
+                Slog.e(TAG, "Unable to authenticate, one or more null arguments");
+                return;
+            }
+
             final int callingUid = Binder.getCallingUid();
             final int callingPid = Binder.getCallingPid();
             final int callingUserId = UserHandle.getCallingUserId();
@@ -166,6 +171,11 @@
                 throws RemoteException {
             checkPermission();
 
+            if (token == null || opPackageName == null) {
+                Slog.e(TAG, "Unable to cancel, one or more null arguments");
+                return;
+            }
+
             final int callingUid = Binder.getCallingUid();
             final int callingPid = Binder.getCallingPid();
             final int callingUserId = UserHandle.getCallingUserId();
diff --git a/services/core/java/com/android/server/biometrics/BiometricService.java b/services/core/java/com/android/server/biometrics/BiometricService.java
index cc2e81f..a181b61 100644
--- a/services/core/java/com/android/server/biometrics/BiometricService.java
+++ b/services/core/java/com/android/server/biometrics/BiometricService.java
@@ -47,6 +47,7 @@
 import android.os.IRemoteCallback;
 import android.os.PowerManager;
 import android.os.RemoteException;
+import android.os.ServiceManager;
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.os.UserManager;
@@ -96,6 +97,7 @@
     private final LockoutReceiver mLockoutReceiver = new LockoutReceiver();
     private final ArrayList<LockoutResetMonitor> mLockoutMonitors = new ArrayList<>();
 
+    protected final IStatusBarService mStatusBarService;
     protected final Map<Integer, Long> mAuthenticatorIds =
             Collections.synchronizedMap(new HashMap<>());
     protected final ResetFailedAttemptsForUserRunnable mResetFailedAttemptsForCurrentUserRunnable =
@@ -221,10 +223,10 @@
                 IBinder token, ServiceListener listener, int targetUserId, int groupId, long opId,
                 boolean restricted, String owner, Bundle bundle,
                 IBiometricPromptReceiver dialogReceiver,
-                IStatusBarService statusBarService) {
+                IStatusBarService statusBarService, BiometricAuthenticator authenticator) {
             super(context, getMetrics(), daemon, halDeviceId, token, listener,
                     targetUserId, groupId, opId, restricted, owner, bundle, dialogReceiver,
-                    statusBarService);
+                    statusBarService, authenticator);
         }
 
         @Override
@@ -524,6 +526,8 @@
     public BiometricService(Context context) {
         super(context);
         mContext = context;
+        mStatusBarService = IStatusBarService.Stub.asInterface(
+                ServiceManager.getService(Context.STATUS_BAR_SERVICE));
         mKeyguardPackage = ComponentName.unflattenFromString(context.getResources().getString(
                 com.android.internal.R.string.config_keyguardComponent)).getPackageName();
         mAppOps = context.getSystemService(AppOpsManager.class);
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 2e76406..8afac97 100644
--- a/services/core/java/com/android/server/biometrics/face/FaceService.java
+++ b/services/core/java/com/android/server/biometrics/face/FaceService.java
@@ -42,7 +42,6 @@
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.SELinux;
-import android.os.ServiceManager;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.util.Slog;
@@ -50,7 +49,6 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.statusbar.IStatusBarService;
 import com.android.internal.util.DumpUtils;
 import com.android.server.SystemServerInitThreadPool;
 import com.android.server.biometrics.BiometricService;
@@ -133,7 +131,7 @@
             final AuthenticationClientImpl client = new AuthenticationClientImpl(getContext(),
                     mDaemonWrapper, mHalDeviceId, token, new ServiceListenerImpl(receiver),
                     mCurrentUserId, 0 /* groupId */, opId, restricted, opPackageName,
-                    null /* bundle */, null /* dialogReceiver */, mStatusBarService);
+                    null /* bundle */, null /* dialogReceiver */, mStatusBarService, mFaceManager);
 
             authenticateInternal(client, opId, opPackageName);
         }
@@ -149,7 +147,7 @@
                     mDaemonWrapper, mHalDeviceId, token,
                     new BiometricPromptServiceListenerImpl(receiver),
                     mCurrentUserId, 0 /* groupId */, opId, restricted, opPackageName,
-                    bundle, dialogReceiver, mStatusBarService);
+                    bundle, dialogReceiver, mStatusBarService, mFaceManager);
             authenticateInternal(client, opId, opPackageName, callingUid, callingPid,
                     callingUserId);
         }
@@ -326,13 +324,10 @@
      */
     private class BiometricPromptServiceListenerImpl implements ServiceListener {
 
-        // Use FaceManager to get strings, so BiometricPrompt interface is cleaner
-        private FaceManager mFaceManager;
         private IBiometricPromptServiceReceiver mBiometricPromptServiceReceiver;
 
         public BiometricPromptServiceListenerImpl(IBiometricPromptServiceReceiver receiver) {
             mBiometricPromptServiceReceiver = receiver;
-            mFaceManager = (FaceManager) getContext().getSystemService(Context.FACE_SERVICE);
         }
 
         @Override
@@ -451,9 +446,9 @@
 
     @GuardedBy("this")
     private IBiometricsFace mDaemon;
-
     private long mHalDeviceId;
-    private IStatusBarService mStatusBarService;
+    // Use FaceManager to get strings, so BiometricPrompt interface is cleaner
+    private FaceManager mFaceManager;
 
     /**
      * Receives callbacks from the HAL.
@@ -579,22 +574,22 @@
             for (int i = 0; i < cryptoToken.length; i++) {
                 token.add(cryptoToken[i]);
             }
-            return daemon.enroll(token, timeout);
+            // TODO: plumb requireAttention down from framework
+            return daemon.enroll(token, timeout, true /* requireAttention */);
         }
     };
 
 
     public FaceService(Context context) {
         super(context);
-        // TODO: can this be retrieved from AuthenticationClient, or BiometricService?
-        mStatusBarService = IStatusBarService.Stub.asInterface(
-                ServiceManager.getService(Context.STATUS_BAR_SERVICE));
     }
 
     @Override
     public void onStart() {
+        super.onStart();
         publishBinderService(Context.FACE_SERVICE, new FaceServiceWrapper());
         SystemServerInitThreadPool.get().submit(this::getFaceDaemon, TAG + ".onStart");
+        mFaceManager = (FaceManager) getContext().getSystemService(Context.FACE_SERVICE);
     }
 
     @Override
@@ -763,7 +758,7 @@
             return 0;
         }
         try {
-            return daemon.preEnroll().value;
+            return daemon.generateChallenge().value;
         } catch (RemoteException e) {
             Slog.e(TAG, "startPreEnroll failed", e);
         }
@@ -777,7 +772,7 @@
             return 0;
         }
         try {
-            return daemon.postEnroll();
+            return daemon.revokeChallenge();
         } catch (RemoteException e) {
             Slog.e(TAG, "startPostEnroll failed", e);
         }
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 a25b4b4..95fb9e3 100644
--- a/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java
@@ -47,7 +47,6 @@
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.SELinux;
-import android.os.ServiceManager;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.util.Slog;
@@ -55,7 +54,6 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.statusbar.IStatusBarService;
 import com.android.internal.util.DumpUtils;
 import com.android.server.SystemServerInitThreadPool;
 import com.android.server.biometrics.BiometricService;
@@ -154,7 +152,7 @@
             final AuthenticationClientImpl client = new AuthenticationClientImpl(getContext(),
                     mDaemonWrapper, mHalDeviceId, token, new ServiceListenerImpl(receiver),
                     mCurrentUserId, groupId, opId, restricted, opPackageName, null /* bundle */,
-                    null /* dialogReceiver */, mStatusBarService);
+                    null /* dialogReceiver */, mStatusBarService, mFingerprintManager);
 
             authenticateInternal(client, opId, opPackageName);
         }
@@ -170,7 +168,7 @@
                     mDaemonWrapper, mHalDeviceId, token,
                     new BiometricPromptServiceListenerImpl(receiver),
                     mCurrentUserId, groupId, opId, restricted, opPackageName, bundle,
-                    dialogReceiver, mStatusBarService);
+                    dialogReceiver, mStatusBarService, mFingerprintManager);
             authenticateInternal(client, opId, opPackageName, callingUid, callingPid,
                     callingUserId);
         }
@@ -362,14 +360,10 @@
      */
     private class BiometricPromptServiceListenerImpl implements ServiceListener {
 
-        // Use FingerprintManager to get strings, so BiometricPrompt interface is cleaner
-        private FingerprintManager mFingerprintManager;
         private IBiometricPromptServiceReceiver mBiometricPromptServiceReceiver;
 
         public BiometricPromptServiceListenerImpl(IBiometricPromptServiceReceiver receiver) {
             mBiometricPromptServiceReceiver = receiver;
-            mFingerprintManager = (FingerprintManager)
-                    getContext().getSystemService(Context.FINGERPRINT_SERVICE);
         }
 
         @Override
@@ -571,9 +565,10 @@
     private IBiometricsFingerprint mDaemon;
 
     private long mHalDeviceId;
-    private IStatusBarService mStatusBarService;
     private IBinder mToken = new Binder(); // used for internal FingerprintService enumeration
     private ArrayList<UserFingerprint> mUnknownFingerprints = new ArrayList<>(); // hw fingerprints
+    // Use FingerprintManager to get strings, so BiometricPrompt interface is cleaner.
+    private FingerprintManager mFingerprintManager;
 
     /**
      * Receives callbacks from the HAL.
@@ -715,9 +710,6 @@
 
     public FingerprintService(Context context) {
         super(context);
-        // TODO: can this be retrieved from AuthenticationClient, or BiometricService?
-        mStatusBarService = IStatusBarService.Stub.asInterface(
-                ServiceManager.getService(Context.STATUS_BAR_SERVICE));
     }
 
     @Override
@@ -725,6 +717,8 @@
         super.onStart();
         publishBinderService(Context.FINGERPRINT_SERVICE, new FingerprintServiceWrapper());
         SystemServerInitThreadPool.get().submit(this::getFingerprintDaemon, TAG + ".onStart");
+        mFingerprintManager = (FingerprintManager)
+                getContext().getSystemService(Context.FINGERPRINT_SERVICE);
     }
 
     @Override
diff --git a/services/core/java/com/android/server/clipboard/ClipboardService.java b/services/core/java/com/android/server/clipboard/ClipboardService.java
index c80c0f1..c028a43 100644
--- a/services/core/java/com/android/server/clipboard/ClipboardService.java
+++ b/services/core/java/com/android/server/clipboard/ClipboardService.java
@@ -26,6 +26,7 @@
 import android.app.UriGrantsManager;
 import android.content.ClipData;
 import android.content.ClipDescription;
+import android.content.ComponentName;
 import android.content.ContentProvider;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -48,6 +49,7 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.Settings;
+import android.text.TextUtils;
 import android.util.Slog;
 import android.util.SparseArray;
 
@@ -630,8 +632,11 @@
         // 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;
+        if (!TextUtils.isEmpty(defaultIme)) {
+            final String imePkg = ComponentName.unflattenFromString(defaultIme).getPackageName();
+            if (imePkg.equals(callingPackage)) {
+                return true;
+            }
         }
 
         // Otherwise only focused applications can access the clipboard.
diff --git a/services/core/java/com/android/server/connectivity/PermissionMonitor.java b/services/core/java/com/android/server/connectivity/PermissionMonitor.java
index e471c7d..7b8571c 100644
--- a/services/core/java/com/android/server/connectivity/PermissionMonitor.java
+++ b/services/core/java/com/android/server/connectivity/PermissionMonitor.java
@@ -24,6 +24,7 @@
 import static android.content.pm.ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
 import static android.content.pm.PackageManager.GET_PERMISSIONS;
 
+import android.annotation.NonNull;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -34,6 +35,7 @@
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.UserInfo;
 import android.net.Uri;
+import android.os.Build;
 import android.os.INetworkManagementService;
 import android.os.RemoteException;
 import android.os.UserHandle;
@@ -155,9 +157,8 @@
     }
 
     @VisibleForTesting
-    boolean isPreinstalledSystemApp(PackageInfo app) {
-        int flags = app.applicationInfo != null ? app.applicationInfo.flags : 0;
-        return (flags & (FLAG_SYSTEM | FLAG_UPDATED_SYSTEM_APP)) != 0;
+    static boolean isVendorApp(@NonNull ApplicationInfo appInfo) {
+        return appInfo.isVendor() || appInfo.isOem() || appInfo.isProduct();
     }
 
     @VisibleForTesting
@@ -177,7 +178,13 @@
     }
 
     private boolean hasRestrictedNetworkPermission(PackageInfo app) {
-        if (isPreinstalledSystemApp(app)) return true;
+        // TODO : remove this check in the future(b/31479477). All apps should just
+        // request the appropriate permission for their use case since android Q.
+        if (app.applicationInfo != null
+                && app.applicationInfo.targetSdkVersion < Build.VERSION_CODES.Q
+                && isVendorApp(app.applicationInfo)) {
+            return true;
+        }
         return hasPermission(app, CONNECTIVITY_INTERNAL)
                 || hasPermission(app, CONNECTIVITY_USE_RESTRICTED_NETWORKS);
     }
@@ -186,13 +193,8 @@
         // This function defines what it means to hold the permission to use
         // background networks.
         return hasPermission(app, CHANGE_NETWORK_STATE)
-                || hasPermission(app, CONNECTIVITY_USE_RESTRICTED_NETWORKS)
-                || hasPermission(app, CONNECTIVITY_INTERNAL)
                 || hasPermission(app, NETWORK_STACK)
-                // TODO : remove this check (b/31479477). Not all preinstalled apps should
-                // have access to background networks, they should just request the appropriate
-                // permission for their use case from the list above.
-                || isPreinstalledSystemApp(app);
+                || hasRestrictedNetworkPermission(app);
     }
 
     public boolean hasUseBackgroundNetworksPermission(int uid) {
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index d16c277..a8f7259 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -68,6 +68,7 @@
 import android.hardware.usb.UsbManager;
 import android.net.INetworkPolicyManager;
 import android.net.INetworkStatsService;
+import android.net.ip.IpServer;
 import android.net.IpPrefix;
 import android.net.LinkAddress;
 import android.net.LinkProperties;
@@ -112,10 +113,8 @@
 import com.android.internal.util.State;
 import com.android.internal.util.StateMachine;
 import com.android.server.LocalServices;
-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.TetherInterfaceStateMachine;
 import com.android.server.connectivity.tethering.TetheringConfiguration;
 import com.android.server.connectivity.tethering.TetheringDependencies;
 import com.android.server.connectivity.tethering.TetheringInterfaceUtils;
@@ -149,7 +148,7 @@
     protected static final String DISABLE_PROVISIONING_SYSPROP_KEY = "net.tethering.noprovisioning";
 
     private static final Class[] messageClasses = {
-            Tethering.class, TetherMasterSM.class, TetherInterfaceStateMachine.class
+            Tethering.class, TetherMasterSM.class, IpServer.class
     };
     private static final SparseArray<String> sMagicDecoderRing =
             MessageUtils.findMessageNames(messageClasses);
@@ -159,21 +158,21 @@
             .getSystem().getString(com.android.internal.R.string.config_wifi_tether_enable));
 
     private static class TetherState {
-        public final TetherInterfaceStateMachine stateMachine;
+        public final IpServer ipServer;
         public int lastState;
         public int lastError;
 
-        public TetherState(TetherInterfaceStateMachine sm) {
-            stateMachine = sm;
+        public TetherState(IpServer ipServer) {
+            this.ipServer = ipServer;
             // Assume all state machines start out available and with no errors.
-            lastState = IControlsTethering.STATE_AVAILABLE;
+            lastState = IpServer.STATE_AVAILABLE;
             lastError = TETHER_ERROR_NO_ERROR;
         }
 
         public boolean isCurrentlyServing() {
             switch (lastState) {
-                case IControlsTethering.STATE_TETHERED:
-                case IControlsTethering.STATE_LOCAL_ONLY:
+                case IpServer.STATE_TETHERED:
+                case IpServer.STATE_LOCAL_ONLY:
                     return true;
                 default:
                     return false;
@@ -198,7 +197,7 @@
     private final UpstreamNetworkMonitor mUpstreamNetworkMonitor;
     // TODO: Figure out how to merge this and other downstream-tracking objects
     // into a single coherent structure.
-    private final HashSet<TetherInterfaceStateMachine> mForwardedDownstreams;
+    private final HashSet<IpServer> mForwardedDownstreams;
     private final VersionedBroadcastListener mCarrierConfigChange;
     private final TetheringDependencies mDeps;
 
@@ -604,7 +603,7 @@
     }
 
     public int tether(String iface) {
-        return tether(iface, IControlsTethering.STATE_TETHERED);
+        return tether(iface, IpServer.STATE_TETHERED);
     }
 
     private int tether(String iface, int requestedState) {
@@ -617,7 +616,7 @@
             }
             // Ignore the error status of the interface.  If the interface is available,
             // the errors are referring to past tethering attempts anyway.
-            if (tetherState.lastState != IControlsTethering.STATE_AVAILABLE) {
+            if (tetherState.lastState != IpServer.STATE_AVAILABLE) {
                 Log.e(TAG, "Tried to Tether an unavailable iface: " + iface + ", ignoring");
                 return TETHER_ERROR_UNAVAIL_IFACE;
             }
@@ -626,8 +625,7 @@
             // return an error.
             //
             // TODO: reexamine the threading and messaging model.
-            tetherState.stateMachine.sendMessage(
-                    TetherInterfaceStateMachine.CMD_TETHER_REQUESTED, requestedState);
+            tetherState.ipServer.sendMessage(IpServer.CMD_TETHER_REQUESTED, requestedState);
             return TETHER_ERROR_NO_ERROR;
         }
     }
@@ -644,8 +642,7 @@
                 Log.e(TAG, "Tried to untether an inactive iface :" + iface + ", ignoring");
                 return TETHER_ERROR_UNAVAIL_IFACE;
             }
-            tetherState.stateMachine.sendMessage(
-                    TetherInterfaceStateMachine.CMD_TETHER_UNREQUESTED);
+            tetherState.ipServer.sendMessage(IpServer.CMD_TETHER_UNREQUESTED);
             return TETHER_ERROR_NO_ERROR;
         }
     }
@@ -689,11 +686,11 @@
                 String iface = mTetherStates.keyAt(i);
                 if (tetherState.lastError != TETHER_ERROR_NO_ERROR) {
                     erroredList.add(iface);
-                } else if (tetherState.lastState == IControlsTethering.STATE_AVAILABLE) {
+                } else if (tetherState.lastState == IpServer.STATE_AVAILABLE) {
                     availableList.add(iface);
-                } else if (tetherState.lastState == IControlsTethering.STATE_LOCAL_ONLY) {
+                } else if (tetherState.lastState == IpServer.STATE_LOCAL_ONLY) {
                     localOnlyList.add(iface);
-                } else if (tetherState.lastState == IControlsTethering.STATE_TETHERED) {
+                } else if (tetherState.lastState == IpServer.STATE_TETHERED) {
                     if (cfg.isUsb(iface)) {
                         usbTethered = true;
                     } else if (cfg.isWifi(iface)) {
@@ -882,10 +879,10 @@
             synchronized (Tethering.this.mPublicSync) {
                 if (!usbConnected && mRndisEnabled) {
                     // Turn off tethering if it was enabled and there is a disconnect.
-                    tetherMatchingInterfaces(IControlsTethering.STATE_AVAILABLE, TETHERING_USB);
+                    tetherMatchingInterfaces(IpServer.STATE_AVAILABLE, TETHERING_USB);
                 } else if (usbConfigured && rndisEnabled) {
                     // Tether if rndis is enabled and usb is configured.
-                    tetherMatchingInterfaces(IControlsTethering.STATE_TETHERED, TETHERING_USB);
+                    tetherMatchingInterfaces(IpServer.STATE_TETHERED, TETHERING_USB);
                 }
                 mRndisEnabled = usbConfigured && rndisEnabled;
             }
@@ -959,15 +956,15 @@
         if (!TextUtils.isEmpty(ifname)) {
             final TetherState ts = mTetherStates.get(ifname);
             if (ts != null) {
-                ts.stateMachine.unwanted();
+                ts.ipServer.unwanted();
                 return;
             }
         }
 
         for (int i = 0; i < mTetherStates.size(); i++) {
-            TetherInterfaceStateMachine tism = mTetherStates.valueAt(i).stateMachine;
-            if (tism.interfaceType() == TETHERING_WIFI) {
-                tism.unwanted();
+            final IpServer ipServer = mTetherStates.valueAt(i).ipServer;
+            if (ipServer.interfaceType() == TETHERING_WIFI) {
+                ipServer.unwanted();
                 return;
             }
         }
@@ -978,15 +975,15 @@
     }
 
     private void enableWifiIpServingLocked(String ifname, int wifiIpMode) {
-        // Map wifiIpMode values to IControlsTethering serving states, inferring
+        // Map wifiIpMode values to IpServer.Callback serving states, inferring
         // from mWifiTetherRequested as a final "best guess".
         final int ipServingMode;
         switch (wifiIpMode) {
             case IFACE_IP_MODE_TETHERED:
-                ipServingMode = IControlsTethering.STATE_TETHERED;
+                ipServingMode = IpServer.STATE_TETHERED;
                 break;
             case IFACE_IP_MODE_LOCAL_ONLY:
-                ipServingMode = IControlsTethering.STATE_LOCAL_ONLY;
+                ipServingMode = IpServer.STATE_LOCAL_ONLY;
                 break;
             default:
                 mLog.e("Cannot enable IP serving in unknown WiFi mode: " + wifiIpMode);
@@ -1041,12 +1038,12 @@
     private void changeInterfaceState(String ifname, int requestedState) {
         final int result;
         switch (requestedState) {
-            case IControlsTethering.STATE_UNAVAILABLE:
-            case IControlsTethering.STATE_AVAILABLE:
+            case IpServer.STATE_UNAVAILABLE:
+            case IpServer.STATE_AVAILABLE:
                 result = untether(ifname);
                 break;
-            case IControlsTethering.STATE_TETHERED:
-            case IControlsTethering.STATE_LOCAL_ONLY:
+            case IpServer.STATE_TETHERED:
+            case IpServer.STATE_LOCAL_ONLY:
                 result = tether(ifname, requestedState);
                 break;
             default:
@@ -1104,7 +1101,7 @@
         synchronized (mPublicSync) {
             for (int i = 0; i < mTetherStates.size(); i++) {
                 TetherState tetherState = mTetherStates.valueAt(i);
-                if (tetherState.lastState == IControlsTethering.STATE_TETHERED) {
+                if (tetherState.lastState == IpServer.STATE_TETHERED) {
                     list.add(mTetherStates.keyAt(i));
                 }
             }
@@ -1117,7 +1114,7 @@
         synchronized (mPublicSync) {
             for (int i = 0; i < mTetherStates.size(); i++) {
                 TetherState tetherState = mTetherStates.valueAt(i);
-                if (tetherState.lastState == IControlsTethering.STATE_AVAILABLE) {
+                if (tetherState.lastState == IpServer.STATE_AVAILABLE) {
                     list.add(mTetherStates.keyAt(i));
                 }
             }
@@ -1177,7 +1174,7 @@
         synchronized (mPublicSync) {
             for (int i = 0; i < mTetherStates.size(); i++) {
                 TetherState tetherState = mTetherStates.valueAt(i);
-                if (tetherState.lastState != IControlsTethering.STATE_TETHERED) {
+                if (tetherState.lastState != IpServer.STATE_TETHERED) {
                     continue;  // Skip interfaces that aren't tethered.
                 }
                 String iface = mTetherStates.keyAt(i);
@@ -1231,7 +1228,7 @@
         // Because we excise interfaces immediately from mTetherStates, we must maintain mNotifyList
         // so that the garbage collector does not clean up the state machine before it has a chance
         // to tear itself down.
-        private final ArrayList<TetherInterfaceStateMachine> mNotifyList;
+        private final ArrayList<IpServer> mNotifyList;
         private final IPv6TetheringCoordinator mIPv6TetheringCoordinator;
         private final OffloadWrapper mOffload;
 
@@ -1268,17 +1265,19 @@
             public boolean processMessage(Message message) {
                 logMessage(this, message.what);
                 switch (message.what) {
-                    case EVENT_IFACE_SERVING_STATE_ACTIVE:
-                        TetherInterfaceStateMachine who = (TetherInterfaceStateMachine) message.obj;
+                    case EVENT_IFACE_SERVING_STATE_ACTIVE: {
+                        final IpServer who = (IpServer) message.obj;
                         if (VDBG) Log.d(TAG, "Tether Mode requested by " + who);
                         handleInterfaceServingStateActive(message.arg1, who);
                         transitionTo(mTetherModeAliveState);
                         break;
-                    case EVENT_IFACE_SERVING_STATE_INACTIVE:
-                        who = (TetherInterfaceStateMachine) message.obj;
+                    }
+                    case EVENT_IFACE_SERVING_STATE_INACTIVE: {
+                        final IpServer who = (IpServer) message.obj;
                         if (VDBG) Log.d(TAG, "Tether Mode unrequested by " + who);
                         handleInterfaceServingStateInactive(who);
                         break;
+                    }
                     case EVENT_IFACE_UPDATE_LINKPROPERTIES:
                         // Silently ignore these for now.
                         break;
@@ -1410,8 +1409,8 @@
 
         protected void notifyDownstreamsOfNewUpstreamIface(InterfaceSet ifaces) {
             mCurrentUpstreamIfaceSet = ifaces;
-            for (TetherInterfaceStateMachine sm : mNotifyList) {
-                sm.sendMessage(TetherInterfaceStateMachine.CMD_TETHER_CONNECTION_CHANGED, ifaces);
+            for (IpServer ipServer : mNotifyList) {
+                ipServer.sendMessage(IpServer.CMD_TETHER_CONNECTION_CHANGED, ifaces);
             }
         }
 
@@ -1420,13 +1419,13 @@
             mOffload.updateUpstreamNetworkState(ns);
         }
 
-        private void handleInterfaceServingStateActive(int mode, TetherInterfaceStateMachine who) {
+        private void handleInterfaceServingStateActive(int mode, IpServer who) {
             if (mNotifyList.indexOf(who) < 0) {
                 mNotifyList.add(who);
                 mIPv6TetheringCoordinator.addActiveDownstream(who, mode);
             }
 
-            if (mode == IControlsTethering.STATE_TETHERED) {
+            if (mode == IpServer.STATE_TETHERED) {
                 // No need to notify OffloadController just yet as there are no
                 // "offload-able" prefixes to pass along. This will handled
                 // when the TISM informs Tethering of its LinkProperties.
@@ -1441,10 +1440,10 @@
                 final WifiManager mgr = getWifiManager();
                 final String iface = who.interfaceName();
                 switch (mode) {
-                    case IControlsTethering.STATE_TETHERED:
+                    case IpServer.STATE_TETHERED:
                         mgr.updateInterfaceIpState(iface, IFACE_IP_MODE_TETHERED);
                         break;
-                    case IControlsTethering.STATE_LOCAL_ONLY:
+                    case IpServer.STATE_LOCAL_ONLY:
                         mgr.updateInterfaceIpState(iface, IFACE_IP_MODE_LOCAL_ONLY);
                         break;
                     default:
@@ -1454,7 +1453,7 @@
             }
         }
 
-        private void handleInterfaceServingStateInactive(TetherInterfaceStateMachine who) {
+        private void handleInterfaceServingStateInactive(IpServer who) {
             mNotifyList.remove(who);
             mIPv6TetheringCoordinator.removeActiveDownstream(who);
             mOffload.excludeDownstreamInterface(who.interfaceName());
@@ -1563,10 +1562,10 @@
                 boolean retValue = true;
                 switch (message.what) {
                     case EVENT_IFACE_SERVING_STATE_ACTIVE: {
-                        TetherInterfaceStateMachine who = (TetherInterfaceStateMachine) message.obj;
+                        IpServer who = (IpServer) message.obj;
                         if (VDBG) Log.d(TAG, "Tether Mode requested by " + who);
                         handleInterfaceServingStateActive(message.arg1, who);
-                        who.sendMessage(TetherInterfaceStateMachine.CMD_TETHER_CONNECTION_CHANGED,
+                        who.sendMessage(IpServer.CMD_TETHER_CONNECTION_CHANGED,
                                 mCurrentUpstreamIfaceSet);
                         // If there has been a change and an upstream is now
                         // desired, kick off the selection process.
@@ -1577,7 +1576,7 @@
                         break;
                     }
                     case EVENT_IFACE_SERVING_STATE_INACTIVE: {
-                        TetherInterfaceStateMachine who = (TetherInterfaceStateMachine) message.obj;
+                        IpServer who = (IpServer) message.obj;
                         if (VDBG) Log.d(TAG, "Tether Mode unrequested by " + who);
                         handleInterfaceServingStateInactive(who);
 
@@ -1591,7 +1590,7 @@
                         if (DBG) {
                             Log.d(TAG, "TetherModeAlive still has " + mNotifyList.size() +
                                     " live requests:");
-                            for (TetherInterfaceStateMachine o : mNotifyList) {
+                            for (IpServer o : mNotifyList) {
                                 Log.d(TAG, "  " + o);
                             }
                         }
@@ -1605,7 +1604,7 @@
                     }
                     case EVENT_IFACE_UPDATE_LINKPROPERTIES: {
                         final LinkProperties newLp = (LinkProperties) message.obj;
-                        if (message.arg1 == IControlsTethering.STATE_TETHERED) {
+                        if (message.arg1 == IpServer.STATE_TETHERED) {
                             mOffload.updateDownstreamLinkProperties(newLp);
                         } else {
                             mOffload.excludeDownstreamInterface(newLp.getInterfaceName());
@@ -1650,7 +1649,7 @@
                 boolean retValue = true;
                 switch (message.what) {
                     case EVENT_IFACE_SERVING_STATE_ACTIVE:
-                        TetherInterfaceStateMachine who = (TetherInterfaceStateMachine) message.obj;
+                        IpServer who = (IpServer) message.obj;
                         who.sendMessage(mErrorNotification);
                         break;
                     case CMD_CLEAR_ERROR:
@@ -1665,8 +1664,8 @@
 
             void notify(int msgType) {
                 mErrorNotification = msgType;
-                for (TetherInterfaceStateMachine sm : mNotifyList) {
-                    sm.sendMessage(msgType);
+                for (IpServer ipServer : mNotifyList) {
+                    ipServer.sendMessage(msgType);
                 }
             }
 
@@ -1676,7 +1675,7 @@
             @Override
             public void enter() {
                 Log.e(TAG, "Error in setIpForwardingEnabled");
-                notify(TetherInterfaceStateMachine.CMD_IP_FORWARDING_ENABLE_ERROR);
+                notify(IpServer.CMD_IP_FORWARDING_ENABLE_ERROR);
             }
         }
 
@@ -1684,7 +1683,7 @@
             @Override
             public void enter() {
                 Log.e(TAG, "Error in setIpForwardingDisabled");
-                notify(TetherInterfaceStateMachine.CMD_IP_FORWARDING_DISABLE_ERROR);
+                notify(IpServer.CMD_IP_FORWARDING_DISABLE_ERROR);
             }
         }
 
@@ -1692,7 +1691,7 @@
             @Override
             public void enter() {
                 Log.e(TAG, "Error in startTethering");
-                notify(TetherInterfaceStateMachine.CMD_START_TETHERING_ERROR);
+                notify(IpServer.CMD_START_TETHERING_ERROR);
                 try {
                     mNMService.setIpForwardingEnabled(false);
                 } catch (Exception e) {}
@@ -1703,7 +1702,7 @@
             @Override
             public void enter() {
                 Log.e(TAG, "Error in stopTethering");
-                notify(TetherInterfaceStateMachine.CMD_STOP_TETHERING_ERROR);
+                notify(IpServer.CMD_STOP_TETHERING_ERROR);
                 try {
                     mNMService.setIpForwardingEnabled(false);
                 } catch (Exception e) {}
@@ -1714,7 +1713,7 @@
             @Override
             public void enter() {
                 Log.e(TAG, "Error in setDnsForwarders");
-                notify(TetherInterfaceStateMachine.CMD_SET_DNS_FORWARDERS_ERROR);
+                notify(IpServer.CMD_SET_DNS_FORWARDERS_ERROR);
                 try {
                     mNMService.stopTethering();
                 } catch (Exception e) {}
@@ -1771,15 +1770,15 @@
 
                 // Maybe add prefixes or addresses for downstreams, depending on
                 // the IP serving mode of each.
-                for (TetherInterfaceStateMachine tism : mNotifyList) {
-                    final LinkProperties lp = tism.linkProperties();
+                for (IpServer ipServer : mNotifyList) {
+                    final LinkProperties lp = ipServer.linkProperties();
 
-                    switch (tism.servingMode()) {
-                        case IControlsTethering.STATE_UNAVAILABLE:
-                        case IControlsTethering.STATE_AVAILABLE:
+                    switch (ipServer.servingMode()) {
+                        case IpServer.STATE_UNAVAILABLE:
+                        case IpServer.STATE_AVAILABLE:
                             // No usable LinkProperties in these states.
                             continue;
-                        case IControlsTethering.STATE_TETHERED:
+                        case IpServer.STATE_TETHERED:
                             // Only add IPv4 /32 and IPv6 /128 prefixes. The
                             // directly-connected prefixes will be sent as
                             // downstream "offload-able" prefixes.
@@ -1789,7 +1788,7 @@
                                 localPrefixes.add(PrefixUtils.ipAddressAsPrefix(ip));
                             }
                             break;
-                        case IControlsTethering.STATE_LOCAL_ONLY:
+                        case IpServer.STATE_LOCAL_ONLY:
                             // Add prefixes covering all local IPs.
                             localPrefixes.addAll(PrefixUtils.localPrefixesFrom(lp));
                             break;
@@ -1826,16 +1825,16 @@
                 pw.print(iface + " - ");
 
                 switch (tetherState.lastState) {
-                    case IControlsTethering.STATE_UNAVAILABLE:
+                    case IpServer.STATE_UNAVAILABLE:
                         pw.print("UnavailableState");
                         break;
-                    case IControlsTethering.STATE_AVAILABLE:
+                    case IpServer.STATE_AVAILABLE:
                         pw.print("AvailableState");
                         break;
-                    case IControlsTethering.STATE_TETHERED:
+                    case IpServer.STATE_TETHERED:
                         pw.print("TetheredState");
                         break;
-                    case IControlsTethering.STATE_LOCAL_ONLY:
+                    case IpServer.STATE_LOCAL_ONLY:
                         pw.print("LocalHotspotState");
                         break;
                     default:
@@ -1873,28 +1872,26 @@
         return false;
     }
 
-    private IControlsTethering makeControlCallback(String ifname) {
-        return new IControlsTethering() {
+    private IpServer.Callback makeControlCallback() {
+        return new IpServer.Callback() {
             @Override
-            public void updateInterfaceState(
-                    TetherInterfaceStateMachine who, int state, int lastError) {
-                notifyInterfaceStateChange(ifname, who, state, lastError);
+            public void updateInterfaceState(IpServer who, int state, int lastError) {
+                notifyInterfaceStateChange(who, state, lastError);
             }
 
             @Override
-            public void updateLinkProperties(
-                    TetherInterfaceStateMachine who, LinkProperties newLp) {
-                notifyLinkPropertiesChanged(ifname, who, newLp);
+            public void updateLinkProperties(IpServer who, LinkProperties newLp) {
+                notifyLinkPropertiesChanged(who, newLp);
             }
         };
     }
 
     // TODO: Move into TetherMasterSM.
-    private void notifyInterfaceStateChange(
-            String iface, TetherInterfaceStateMachine who, int state, int error) {
+    private void notifyInterfaceStateChange(IpServer who, int state, int error) {
+        final String iface = who.interfaceName();
         synchronized (mPublicSync) {
             final TetherState tetherState = mTetherStates.get(iface);
-            if (tetherState != null && tetherState.stateMachine.equals(who)) {
+            if (tetherState != null && tetherState.ipServer.equals(who)) {
                 tetherState.lastState = state;
                 tetherState.lastError = error;
             } else {
@@ -1908,7 +1905,7 @@
             // Notify that we're tethering (or not) this interface.
             // This is how data saver for instance knows if the user explicitly
             // turned on tethering (thus keeping us from being in data saver mode).
-            mPolicyManager.onTetheringChanged(iface, state == IControlsTethering.STATE_TETHERED);
+            mPolicyManager.onTetheringChanged(iface, state == IpServer.STATE_TETHERED);
         } catch (RemoteException e) {
             // Not really very much we can do here.
         }
@@ -1921,12 +1918,12 @@
         }
         int which;
         switch (state) {
-            case IControlsTethering.STATE_UNAVAILABLE:
-            case IControlsTethering.STATE_AVAILABLE:
+            case IpServer.STATE_UNAVAILABLE:
+            case IpServer.STATE_AVAILABLE:
                 which = TetherMasterSM.EVENT_IFACE_SERVING_STATE_INACTIVE;
                 break;
-            case IControlsTethering.STATE_TETHERED:
-            case IControlsTethering.STATE_LOCAL_ONLY:
+            case IpServer.STATE_TETHERED:
+            case IpServer.STATE_LOCAL_ONLY:
                 which = TetherMasterSM.EVENT_IFACE_SERVING_STATE_ACTIVE;
                 break;
             default:
@@ -1937,12 +1934,12 @@
         sendTetherStateChangedBroadcast();
     }
 
-    private void notifyLinkPropertiesChanged(String iface, TetherInterfaceStateMachine who,
-                                             LinkProperties newLp) {
+    private void notifyLinkPropertiesChanged(IpServer who, LinkProperties newLp) {
+        final String iface = who.interfaceName();
         final int state;
         synchronized (mPublicSync) {
             final TetherState tetherState = mTetherStates.get(iface);
-            if (tetherState != null && tetherState.stateMachine.equals(who)) {
+            if (tetherState != null && tetherState.ipServer.equals(who)) {
                 state = tetherState.lastState;
             } else {
                 mLog.log("got notification from stale iface " + iface);
@@ -1952,7 +1949,7 @@
 
         mLog.log(String.format(
                 "OBSERVED LinkProperties update iface=%s state=%s lp=%s",
-                iface, IControlsTethering.getStateString(state), newLp));
+                iface, IpServer.getStateString(state), newLp));
         final int which = TetherMasterSM.EVENT_IFACE_UPDATE_LINKPROPERTIES;
         mTetherMasterSM.sendMessage(which, state, 0, newLp);
     }
@@ -1976,11 +1973,11 @@
 
         mLog.log("adding TetheringInterfaceStateMachine for: " + iface);
         final TetherState tetherState = new TetherState(
-                new TetherInterfaceStateMachine(
-                    iface, mLooper, interfaceType, mLog, mNMService, mStatsService,
-                    makeControlCallback(iface), mConfig.enableLegacyDhcpServer, mDeps));
+                new IpServer(iface, mLooper, interfaceType, mLog, mNMService, mStatsService,
+                             makeControlCallback(), mConfig.enableLegacyDhcpServer,
+                             mDeps.getIpServerDependencies()));
         mTetherStates.put(iface, tetherState);
-        tetherState.stateMachine.start();
+        tetherState.ipServer.start();
     }
 
     private void stopTrackingInterfaceLocked(final String iface) {
@@ -1989,36 +1986,11 @@
             mLog.log("attempting to remove unknown iface (" + iface + "), ignoring");
             return;
         }
-        tetherState.stateMachine.stop();
+        tetherState.ipServer.stop();
         mLog.log("removing TetheringInterfaceStateMachine for: " + iface);
         mTetherStates.remove(iface);
     }
 
-    private static String getIPv4DefaultRouteInterface(NetworkState ns) {
-        if (ns == null) return null;
-        return getInterfaceForDestination(ns.linkProperties, Inet4Address.ANY);
-    }
-
-    private static String getIPv6DefaultRouteInterface(NetworkState ns) {
-        if (ns == null) return null;
-        // An upstream network's IPv6 capability is currently only useful if it
-        // can be 64share'd downstream (RFC 7278). For now, that means mobile
-        // upstream networks only.
-        if (ns.networkCapabilities == null ||
-                !ns.networkCapabilities.hasTransport(TRANSPORT_CELLULAR)) {
-            return null;
-        }
-
-        return getInterfaceForDestination(ns.linkProperties, Inet6Address.ANY);
-    }
-
-    private static String getInterfaceForDestination(LinkProperties lp, InetAddress dst) {
-        final RouteInfo ri = (lp != null)
-                ? RouteInfo.selectBestRoute(lp.getAllRoutes(), dst)
-                : null;
-        return (ri != null) ? ri.getInterface() : null;
-    }
-
     private static String[] copy(String[] strarray) {
         return Arrays.copyOf(strarray, strarray.length);
     }
diff --git a/services/core/java/com/android/server/connectivity/tethering/IControlsTethering.java b/services/core/java/com/android/server/connectivity/tethering/IControlsTethering.java
deleted file mode 100644
index 2b81347..0000000
--- a/services/core/java/com/android/server/connectivity/tethering/IControlsTethering.java
+++ /dev/null
@@ -1,66 +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.server.connectivity.tethering;
-
-import android.net.LinkProperties;
-
-/**
- * @hide
- *
- * Interface with methods necessary to notify that a given interface is ready for tethering.
- *
- * Rename to something more representative, e.g. IpServingControlCallback.
- *
- * All methods MUST be called on the TetherMasterSM main Looper's thread.
- */
-public class IControlsTethering {
-    public static final int STATE_UNAVAILABLE = 0;
-    public static final int STATE_AVAILABLE   = 1;
-    public static final int STATE_TETHERED    = 2;
-    public static final int STATE_LOCAL_ONLY  = 3;
-
-    public static String getStateString(int state) {
-        switch (state) {
-            case STATE_UNAVAILABLE: return "UNAVAILABLE";
-            case STATE_AVAILABLE:   return "AVAILABLE";
-            case STATE_TETHERED:    return "TETHERED";
-            case STATE_LOCAL_ONLY:  return "LOCAL_ONLY";
-        }
-        return "UNKNOWN: " + state;
-    }
-
-    /**
-     * Notify that |who| has changed its tethering state.
-     *
-     * TODO: Remove the need for the |who| argument.
-     *
-     * @param who corresponding instance of a TetherInterfaceStateMachine
-     * @param state one of IControlsTethering.STATE_*
-     * @param lastError one of ConnectivityManager.TETHER_ERROR_*
-     */
-    public void updateInterfaceState(TetherInterfaceStateMachine who, int state, int lastError) {}
-
-    /**
-     * Notify that |who| has new LinkProperties.
-     *
-     * TODO: Remove the need for the |who| argument.
-     *
-     * @param who corresponding instance of a TetherInterfaceStateMachine
-     * @param newLp the new LinkProperties to report
-     */
-    public void updateLinkProperties(TetherInterfaceStateMachine who, LinkProperties newLp) {}
-}
diff --git a/services/core/java/com/android/server/connectivity/tethering/IPv6TetheringCoordinator.java b/services/core/java/com/android/server/connectivity/tethering/IPv6TetheringCoordinator.java
index ba67c94..1000148 100644
--- a/services/core/java/com/android/server/connectivity/tethering/IPv6TetheringCoordinator.java
+++ b/services/core/java/com/android/server/connectivity/tethering/IPv6TetheringCoordinator.java
@@ -17,6 +17,7 @@
 package com.android.server.connectivity.tethering;
 
 import android.net.ConnectivityManager;
+import android.net.ip.IpServer;
 import android.net.IpPrefix;
 import android.net.LinkAddress;
 import android.net.LinkProperties;
@@ -50,19 +51,19 @@
     private static final boolean VDBG = false;
 
     private static class Downstream {
-        public final TetherInterfaceStateMachine tism;
-        public final int mode;  // IControlsTethering.STATE_*
+        public final IpServer ipServer;
+        public final int mode;  // IpServer.STATE_*
         // Used to append to a ULA /48, constructing a ULA /64 for local use.
         public final short subnetId;
 
-        Downstream(TetherInterfaceStateMachine tism, int mode, short subnetId) {
-            this.tism = tism;
+        Downstream(IpServer ipServer, int mode, short subnetId) {
+            this.ipServer = ipServer;
             this.mode = mode;
             this.subnetId = subnetId;
         }
     }
 
-    private final ArrayList<TetherInterfaceStateMachine> mNotifyList;
+    private final ArrayList<IpServer> mNotifyList;
     private final SharedLog mLog;
     // NOTE: mActiveDownstreams is a list and not a hash data structure because
     // we keep active downstreams in arrival order.  This is done so /64s can
@@ -74,8 +75,7 @@
     private short mNextSubnetId;
     private NetworkState mUpstreamNetworkState;
 
-    public IPv6TetheringCoordinator(ArrayList<TetherInterfaceStateMachine> notifyList,
-                                    SharedLog log) {
+    public IPv6TetheringCoordinator(ArrayList<IpServer> notifyList, SharedLog log) {
         mNotifyList = notifyList;
         mLog = log.forSubComponent(TAG);
         mActiveDownstreams = new LinkedList<>();
@@ -83,7 +83,7 @@
         mNextSubnetId = 0;
     }
 
-    public void addActiveDownstream(TetherInterfaceStateMachine downstream, int mode) {
+    public void addActiveDownstream(IpServer downstream, int mode) {
         if (findDownstream(downstream) == null) {
             // Adding a new downstream appends it to the list. Adding a
             // downstream a second time without first removing it has no effect.
@@ -98,7 +98,7 @@
         }
     }
 
-    public void removeActiveDownstream(TetherInterfaceStateMachine downstream) {
+    public void removeActiveDownstream(IpServer downstream) {
         stopIPv6TetheringOn(downstream);
         if (mActiveDownstreams.remove(findDownstream(downstream))) {
             updateIPv6TetheringInterfaces();
@@ -133,8 +133,8 @@
     }
 
     private void stopIPv6TetheringOnAllInterfaces() {
-        for (TetherInterfaceStateMachine sm : mNotifyList) {
-            stopIPv6TetheringOn(sm);
+        for (IpServer ipServer : mNotifyList) {
+            stopIPv6TetheringOn(ipServer);
         }
     }
 
@@ -156,28 +156,28 @@
     }
 
     private void updateIPv6TetheringInterfaces() {
-        for (TetherInterfaceStateMachine sm : mNotifyList) {
-            final LinkProperties lp = getInterfaceIPv6LinkProperties(sm);
-            sm.sendMessage(TetherInterfaceStateMachine.CMD_IPV6_TETHER_UPDATE, 0, 0, lp);
+        for (IpServer ipServer : mNotifyList) {
+            final LinkProperties lp = getInterfaceIPv6LinkProperties(ipServer);
+            ipServer.sendMessage(IpServer.CMD_IPV6_TETHER_UPDATE, 0, 0, lp);
             break;
         }
     }
 
-    private LinkProperties getInterfaceIPv6LinkProperties(TetherInterfaceStateMachine sm) {
-        if (sm.interfaceType() == ConnectivityManager.TETHERING_BLUETOOTH) {
+    private LinkProperties getInterfaceIPv6LinkProperties(IpServer ipServer) {
+        if (ipServer.interfaceType() == ConnectivityManager.TETHERING_BLUETOOTH) {
             // TODO: Figure out IPv6 support on PAN interfaces.
             return null;
         }
 
-        final Downstream ds = findDownstream(sm);
+        final Downstream ds = findDownstream(ipServer);
         if (ds == null) return null;
 
-        if (ds.mode == IControlsTethering.STATE_LOCAL_ONLY) {
+        if (ds.mode == IpServer.STATE_LOCAL_ONLY) {
             // Build a Unique Locally-assigned Prefix configuration.
             return getUniqueLocalConfig(mUniqueLocalPrefix, ds.subnetId);
         }
 
-        // This downstream is in IControlsTethering.STATE_TETHERED mode.
+        // This downstream is in IpServer.STATE_TETHERED mode.
         if (mUpstreamNetworkState == null || mUpstreamNetworkState.linkProperties == null) {
             return null;
         }
@@ -188,7 +188,7 @@
         // IPv6 toward the oldest (first requested) active downstream.
 
         final Downstream currentActive = mActiveDownstreams.peek();
-        if (currentActive != null && currentActive.tism == sm) {
+        if (currentActive != null && currentActive.ipServer == ipServer) {
             final LinkProperties lp = getIPv6OnlyLinkProperties(
                     mUpstreamNetworkState.linkProperties);
             if (lp.hasIPv6DefaultRoute() && lp.hasGlobalIPv6Address()) {
@@ -199,9 +199,9 @@
         return null;
     }
 
-    Downstream findDownstream(TetherInterfaceStateMachine tism) {
+    Downstream findDownstream(IpServer ipServer) {
         for (Downstream ds : mActiveDownstreams) {
-            if (ds.tism == tism) return ds;
+            if (ds.ipServer == ipServer) return ds;
         }
         return null;
     }
@@ -304,7 +304,7 @@
                 ns.linkProperties);
     }
 
-    private static void stopIPv6TetheringOn(TetherInterfaceStateMachine sm) {
-        sm.sendMessage(TetherInterfaceStateMachine.CMD_IPV6_TETHER_UPDATE, 0, 0, null);
+    private static void stopIPv6TetheringOn(IpServer ipServer) {
+        ipServer.sendMessage(IpServer.CMD_IPV6_TETHER_UPDATE, 0, 0, null);
     }
 }
diff --git a/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java b/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java
index 6699444..2b1d919 100644
--- a/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java
+++ b/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java
@@ -162,6 +162,9 @@
         dumpStringArray(pw, "provisioningApp", provisioningApp);
         pw.print("provisioningAppNoUi: ");
         pw.println(provisioningAppNoUi);
+
+        pw.print("enableLegacyDhcpServer: ");
+        pw.println(enableLegacyDhcpServer);
     }
 
     public String toString() {
@@ -176,6 +179,7 @@
                 makeString(preferredUpstreamNames(preferredUpstreamIfaceTypes))));
         sj.add(String.format("provisioningApp:%s", makeString(provisioningApp)));
         sj.add(String.format("provisioningAppNoUi:%s", provisioningAppNoUi));
+        sj.add(String.format("enableLegacyDhcpServer:%s", enableLegacyDhcpServer));
         return String.format("TetheringConfiguration{%s}", sj.toString());
     }
 
diff --git a/services/core/java/com/android/server/connectivity/tethering/TetheringDependencies.java b/services/core/java/com/android/server/connectivity/tethering/TetheringDependencies.java
index caa867c..8b40069 100644
--- a/services/core/java/com/android/server/connectivity/tethering/TetheringDependencies.java
+++ b/services/core/java/com/android/server/connectivity/tethering/TetheringDependencies.java
@@ -21,6 +21,7 @@
 import android.net.NetworkRequest;
 import android.net.dhcp.DhcpServer;
 import android.net.dhcp.DhcpServingParams;
+import android.net.ip.IpServer;
 import android.net.ip.RouterAdvertisementDaemon;
 import android.net.util.InterfaceParams;
 import android.net.util.NetdService;
@@ -49,20 +50,12 @@
     }
 
     public IPv6TetheringCoordinator getIPv6TetheringCoordinator(
-            ArrayList<TetherInterfaceStateMachine> notifyList, SharedLog log) {
+            ArrayList<IpServer> notifyList, SharedLog log) {
         return new IPv6TetheringCoordinator(notifyList, log);
     }
 
-    public RouterAdvertisementDaemon getRouterAdvertisementDaemon(InterfaceParams ifParams) {
-        return new RouterAdvertisementDaemon(ifParams);
-    }
-
-    public InterfaceParams getInterfaceParams(String ifName) {
-        return InterfaceParams.getByName(ifName);
-    }
-
-    public INetd getNetdService() {
-        return NetdService.getInstance();
+    public IpServer.Dependencies getIpServerDependencies() {
+        return new IpServer.Dependencies();
     }
 
     public boolean isTetheringSupported() {
@@ -72,9 +65,4 @@
     public NetworkRequest getDefaultNetworkRequest() {
         return null;
     }
-
-    public DhcpServer makeDhcpServer(Looper looper, InterfaceParams iface, DhcpServingParams params,
-            SharedLog log) {
-        return new DhcpServer(looper, iface, params, log);
-    }
 }
diff --git a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
index 1b688a6..76c191d 100644
--- a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
+++ b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
@@ -26,8 +26,8 @@
 import android.util.Slog;
 import android.util.Spline;
 
-import com.android.internal.util.Preconditions;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.Preconditions;
 import com.android.server.display.utils.Plog;
 
 import java.io.PrintWriter;
@@ -77,8 +77,8 @@
                 Slog.w(TAG, "Screen brightness mapping does not cover whole range of available " +
                         "backlight values, autobrightness functionality may be impaired.");
             }
-            BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder();
-            builder.setCurve(luxLevels, brightnessLevelsNits);
+            BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder(
+                    luxLevels, brightnessLevelsNits);
             return new PhysicalMappingStrategy(builder.build(), nitsRange, backlightRange,
                     autoBrightnessAdjustmentMaxGamma);
         } else if (isValidMapping(luxLevels, brightnessLevelsBacklight)) {
diff --git a/services/core/java/com/android/server/display/BrightnessTracker.java b/services/core/java/com/android/server/display/BrightnessTracker.java
index c473ef2..019d726 100644
--- a/services/core/java/com/android/server/display/BrightnessTracker.java
+++ b/services/core/java/com/android/server/display/BrightnessTracker.java
@@ -51,6 +51,7 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.app.ColorDisplayController;
 import com.android.internal.os.BackgroundThread;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.RingBuffer;
@@ -72,7 +73,6 @@
 import java.text.SimpleDateFormat;
 import java.util.ArrayDeque;
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.Date;
 import java.util.Deque;
 import java.util.HashMap;
@@ -363,12 +363,9 @@
             return;
         }
 
-        builder.setNightMode(mInjector.getSecureIntForUser(mContentResolver,
-                Settings.Secure.NIGHT_DISPLAY_ACTIVATED, 0, UserHandle.USER_CURRENT)
-                == 1);
-        builder.setColorTemperature(mInjector.getSecureIntForUser(mContentResolver,
-                Settings.Secure.NIGHT_DISPLAY_COLOR_TEMPERATURE,
-                0, UserHandle.USER_CURRENT));
+        builder.setNightMode(mInjector.isNightModeActive(mContext, UserHandle.USER_CURRENT));
+        builder.setColorTemperature(mInjector.getColorTemperature(mContext,
+                UserHandle.USER_CURRENT));
 
         BrightnessChangeEvent event = builder.build();
         if (DEBUG) {
@@ -952,5 +949,13 @@
         public boolean isInteractive(Context context) {
             return context.getSystemService(PowerManager.class).isInteractive();
         }
+
+        public int getColorTemperature(Context context, int userId) {
+            return new ColorDisplayController(context, userId).getColorTemperature();
+        }
+
+        public boolean isNightModeActive(Context context, int userId) {
+            return new ColorDisplayController(context, userId).isActivated();
+        }
     }
 }
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 9df9ba6..a050aa9 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -16,26 +16,10 @@
 
 package com.android.server.input;
 
+import static android.hardware.display.DisplayViewport.VIEWPORT_INTERNAL;
+import static android.hardware.display.DisplayViewport.VIEWPORT_EXTERNAL;
+
 import android.annotation.NonNull;
-import android.os.LocaleList;
-import android.os.ShellCallback;
-import android.util.Log;
-import android.view.Display;
-import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
-import com.android.internal.notification.SystemNotificationChannels;
-import com.android.internal.os.SomeArgs;
-import com.android.internal.R;
-import com.android.internal.util.DumpUtils;
-import com.android.internal.util.Preconditions;
-import com.android.internal.util.XmlUtils;
-import com.android.server.DisplayThread;
-import com.android.server.LocalServices;
-import com.android.server.Watchdog;
-import com.android.server.policy.WindowManagerPolicy;
-
-import org.xmlpull.v1.XmlPullParser;
-
-import android.Manifest;
 import android.app.IInputForwarder;
 import android.app.Notification;
 import android.app.NotificationManager;
@@ -50,8 +34,8 @@
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
 import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ResolveInfo;
 import android.content.res.Resources;
 import android.content.res.Resources.NotFoundException;
 import android.content.res.TypedArray;
@@ -61,10 +45,10 @@
 import android.hardware.display.DisplayViewport;
 import android.hardware.input.IInputDevicesChangedListener;
 import android.hardware.input.IInputManager;
+import android.hardware.input.ITabletModeChangedListener;
 import android.hardware.input.InputDeviceIdentifier;
 import android.hardware.input.InputManager;
 import android.hardware.input.InputManagerInternal;
-import android.hardware.input.ITabletModeChangedListener;
 import android.hardware.input.KeyboardLayout;
 import android.hardware.input.TouchCalibration;
 import android.os.Binder;
@@ -72,6 +56,7 @@
 import android.os.Environment;
 import android.os.Handler;
 import android.os.IBinder;
+import android.os.LocaleList;
 import android.os.Looper;
 import android.os.Message;
 import android.os.MessageQueue;
@@ -81,6 +66,7 @@
 import android.provider.Settings;
 import android.provider.Settings.SettingNotFoundException;
 import android.text.TextUtils;
+import android.util.Log;
 import android.util.Slog;
 import android.util.SparseArray;
 import android.util.Xml;
@@ -97,6 +83,23 @@
 import android.view.ViewConfiguration;
 import android.widget.Toast;
 
+import com.android.internal.R;
+import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
+import com.android.internal.notification.SystemNotificationChannels;
+import com.android.internal.os.SomeArgs;
+import com.android.internal.util.DumpUtils;
+import com.android.internal.util.Preconditions;
+import com.android.internal.util.XmlUtils;
+import com.android.server.DisplayThread;
+import com.android.server.LocalServices;
+import com.android.server.Watchdog;
+import com.android.server.policy.WindowManagerPolicy;
+
+import libcore.io.IoUtils;
+import libcore.io.Streams;
+
+import org.xmlpull.v1.XmlPullParser;
+
 import java.io.File;
 import java.io.FileDescriptor;
 import java.io.FileNotFoundException;
@@ -113,9 +116,6 @@
 import java.util.Locale;
 import java.util.Objects;
 
-import libcore.io.IoUtils;
-import libcore.io.Streams;
-
 /*
  * Wraps the C++ InputManager and provides its callbacks.
  */
@@ -212,7 +212,8 @@
             int injectorPid, int injectorUid, int syncMode, int timeoutMillis,
             int policyFlags);
     private static native void nativeToggleCapsLock(long ptr, int deviceId);
-    private static native void nativeSetInputWindows(long ptr, InputWindowHandle[] windowHandles);
+    private static native void nativeSetInputWindows(long ptr, InputWindowHandle[] windowHandles,
+            int displayId);
     private static native void nativeSetInputDispatchMode(long ptr, boolean enabled, boolean frozen);
     private static native void nativeSetSystemUiVisibility(long ptr, int visibility);
     private static native void nativeSetFocusedApplication(long ptr,
@@ -292,11 +293,6 @@
     /** Switch code: Camera lens cover. When set the lens is covered. */
     public static final int SW_CAMERA_LENS_COVER = 0x09;
 
-    // Viewport constants defined in InputReader.h.
-    public static final int VIEWPORT_DEFAULT = 1;
-    public static final int VIEWPORT_EXTERNAL = 2;
-    public static final int VIEWPORT_VIRTUAL = 3;
-
     public static final int SW_LID_BIT = 1 << SW_LID;
     public static final int SW_TABLET_MODE_BIT = 1 << SW_TABLET_MODE;
     public static final int SW_KEYPAD_SLIDE_BIT = 1 << SW_KEYPAD_SLIDE;
@@ -362,7 +358,7 @@
         updateAccessibilityLargePointerFromSettings();
     }
 
-    // TODO(BT) Pass in paramter for bluetooth system
+    // TODO(BT) Pass in parameter for bluetooth system
     public void systemRunning() {
         if (DEBUG) {
             Slog.d(TAG, "System ready.");
@@ -417,7 +413,7 @@
             DisplayViewport externalTouchViewport,
             List<DisplayViewport> virtualTouchViewports) {
         if (defaultViewport.valid) {
-            setDisplayViewport(VIEWPORT_DEFAULT, defaultViewport);
+            setDisplayViewport(VIEWPORT_INTERNAL, defaultViewport);
         }
 
         if (externalTouchViewport.valid) {
@@ -1467,7 +1463,7 @@
     }
 
     public void setInputWindows(InputWindowHandle[] windowHandles,
-            InputWindowHandle focusedWindowHandle) {
+            InputWindowHandle focusedWindowHandle, int displayId) {
         final IWindow newFocusedWindow =
             focusedWindowHandle != null ? focusedWindowHandle.clientWindow : null;
         if (mFocusedWindow != newFocusedWindow) {
@@ -1476,7 +1472,7 @@
                 setPointerCapture(false);
             }
         }
-        nativeSetInputWindows(mPtr, windowHandles);
+        nativeSetInputWindows(mPtr, windowHandles, displayId);
     }
 
     public void setFocusedApplication(InputApplicationHandle application) {
diff --git a/services/core/java/com/android/server/input/InputWindowHandle.java b/services/core/java/com/android/server/input/InputWindowHandle.java
index 720eaaa5..bb29bf8 100644
--- a/services/core/java/com/android/server/input/InputWindowHandle.java
+++ b/services/core/java/com/android/server/input/InputWindowHandle.java
@@ -17,8 +17,8 @@
 package com.android.server.input;
 
 import android.graphics.Region;
-import android.view.InputChannel;
 import android.view.IWindow;
+import android.view.InputChannel;
 
 /**
  * Functions as a handle for a window that can receive input.
@@ -106,7 +106,7 @@
 
     @Override
     public String toString() {
-        return new StringBuilder(name)
+        return new StringBuilder(name != null ? name : "")
                 .append(", layer=").append(layer)
                 .append(", frame=[").append(frameLeft).append(",").append(frameTop).append(",")
                         .append(frameRight).append(",").append(frameBottom).append("]")
diff --git a/services/core/java/com/android/server/InputContentUriTokenHandler.java b/services/core/java/com/android/server/inputmethod/InputContentUriTokenHandler.java
similarity index 97%
rename from services/core/java/com/android/server/InputContentUriTokenHandler.java
rename to services/core/java/com/android/server/inputmethod/InputContentUriTokenHandler.java
index 6338b2f..845fca1 100644
--- a/services/core/java/com/android/server/InputContentUriTokenHandler.java
+++ b/services/core/java/com/android/server/inputmethod/InputContentUriTokenHandler.java
@@ -14,11 +14,10 @@
 ** limitations under the License.
 */
 
-package com.android.server;
+package com.android.server.inputmethod;
 
 import android.annotation.NonNull;
 import android.annotation.UserIdInt;
-import android.app.ActivityManager;
 import android.app.UriGrantsManager;
 import android.content.Intent;
 import android.net.Uri;
@@ -28,6 +27,7 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.inputmethod.IInputContentUriToken;
+import com.android.server.LocalServices;
 import com.android.server.uri.UriGrantsManagerInternal;
 
 final class InputContentUriTokenHandler extends IInputContentUriToken.Stub {
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java
index b57356f..b5a9f74 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java
@@ -28,6 +28,10 @@
     /**
      * Called by the window manager service when a client process is being attached to the window
      * manager service.
+     *
+     * <p>The caller must not have WindowManagerService lock.  This method internally acquires
+     * InputMethodManagerService lock.</p>
+     *
      * @param client {@link android.os.Binder} proxy that is associated with the singleton instance
      *               of {@link android.view.inputmethod.InputMethodManager} that runs on the client
      *               process
@@ -42,6 +46,10 @@
     /**
      * Called by the window manager service when a client process is being attached to the window
      * manager service.
+     *
+     * <p>The caller must not have WindowManagerService lock.  This method internally acquires
+     * InputMethodManagerService lock.</p>
+     *
      * @param client {@link android.os.Binder} proxy that is associated with the singleton instance
      *               of {@link android.view.inputmethod.InputMethodManager} that runs on the client
      *               process
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
similarity index 95%
rename from services/core/java/com/android/server/InputMethodManagerService.java
rename to services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 4e4e208..44fb9ea 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -13,9 +13,10 @@
  * the License.
  */
 
-package com.android.server;
+package com.android.server.inputmethod;
 
 import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.Display.INVALID_DISPLAY;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
@@ -27,6 +28,7 @@
 import android.annotation.AnyThread;
 import android.annotation.BinderThread;
 import android.annotation.ColorInt;
+import android.annotation.DrawableRes;
 import android.annotation.IntDef;
 import android.annotation.MainThread;
 import android.annotation.NonNull;
@@ -127,6 +129,7 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.content.PackageMonitor;
 import com.android.internal.inputmethod.IInputContentUriToken;
+import com.android.internal.inputmethod.IInputMethodPrivilegedOperations;
 import com.android.internal.inputmethod.InputMethodSubtypeSwitchingController;
 import com.android.internal.inputmethod.InputMethodSubtypeSwitchingController.ImeSubtypeListItem;
 import com.android.internal.inputmethod.InputMethodUtils;
@@ -147,7 +150,9 @@
 import com.android.internal.view.IInputSessionCallback;
 import com.android.internal.view.InputBindResult;
 import com.android.internal.view.InputMethodClient;
-import com.android.server.inputmethod.InputMethodManagerInternal;
+import com.android.server.EventLogTags;
+import com.android.server.LocalServices;
+import com.android.server.SystemService;
 import com.android.server.statusbar.StatusBarManagerService;
 import com.android.server.wm.WindowManagerInternal;
 
@@ -198,19 +203,16 @@
     static final int MSG_SHOW_SOFT_INPUT = 1020;
     static final int MSG_HIDE_SOFT_INPUT = 1030;
     static final int MSG_HIDE_CURRENT_INPUT_METHOD = 1035;
-    static final int MSG_ATTACH_TOKEN = 1040;
+    static final int MSG_INITIALIZE_IME = 1040;
     static final int MSG_CREATE_SESSION = 1050;
 
     static final int MSG_START_INPUT = 2000;
     static final int MSG_START_VR_INPUT = 2010;
 
-    static final int MSG_ADD_CLIENT = 2980;
-    static final int MSG_REMOVE_CLIENT = 2990;
     static final int MSG_UNBIND_CLIENT = 3000;
     static final int MSG_BIND_CLIENT = 3010;
     static final int MSG_SET_ACTIVE = 3020;
     static final int MSG_SET_INTERACTIVE = 3030;
-    static final int MSG_SET_USER_ACTION_NOTIFICATION_SEQUENCE_NUMBER = 3040;
     static final int MSG_REPORT_FULLSCREEN_MODE = 3045;
 
     static final int MSG_HARD_KEYBOARD_SWITCH_CHANGED = 4000;
@@ -254,7 +256,7 @@
      * the notification.
      */
     private static final String ACTION_SHOW_INPUT_METHOD_PICKER =
-            "com.android.server.InputMethodManagerService.SHOW_INPUT_METHOD_PICKER";
+            "com.android.server.inputmethod.InputMethodManagerService.SHOW_INPUT_METHOD_PICKER";
 
     /**
      * Debug flag for overriding runtime {@link SystemProperties}.
@@ -571,6 +573,11 @@
     IBinder mCurToken;
 
     /**
+     * The displayId of current active input method.
+     */
+    int mCurTokenDisplayId = INVALID_DISPLAY;
+
+    /**
      * If non-null, this is the input method service we are currently connected
      * to.
      */
@@ -598,8 +605,6 @@
      */
     boolean mIsInteractive = true;
 
-    int mCurUserActionNotificationSequenceNumber = 0;
-
     int mBackDisposition = InputMethodService.BACK_DISPOSITION_DEFAULT;
 
     /**
@@ -1302,7 +1307,7 @@
         @Override
         public void onStart() {
             LocalServices.addService(InputMethodManagerInternal.class,
-                    new LocalServiceImpl(mService.mHandler));
+                    new LocalServiceImpl(mService));
             publishBinderService(Context.INPUT_METHOD_SERVICE, mService);
         }
 
@@ -1561,7 +1566,6 @@
                 final String defaultImiId = mSettings.getSelectedInputMethod();
                 final boolean imeSelectedOnBoot = !TextUtils.isEmpty(defaultImiId);
                 buildInputMethodListLocked(!imeSelectedOnBoot /* resetDefaultEnabledIme */);
-                resetDefaultImeLocked(mContext);
                 updateFromSettingsLocked(true);
                 InputMethodUtils.setNonSelectedSystemImesDisabledUntilUsed(mIPackageManager,
                         mSettings.getEnabledInputMethodListLocked(), currentUserId,
@@ -1823,7 +1827,7 @@
         }
         return new InputBindResult(InputBindResult.ResultCode.SUCCESS_WITH_IME_SESSION,
                 session.session, (session.channel != null ? session.channel.dup() : null),
-                mCurId, mCurSeq, mCurUserActionNotificationSequenceNumber);
+                mCurId, mCurSeq);
     }
 
     @GuardedBy("mMethodMap")
@@ -1868,7 +1872,9 @@
         mCurAttribute = attribute;
 
         // Check if the input method is changing.
-        if (mCurId != null && mCurId.equals(mCurMethodId)) {
+        final int displayId = mWindowManagerInternal.getDisplayIdForWindow(
+                mCurFocusedWindow);
+        if (mCurId != null && mCurId.equals(mCurMethodId) && displayId == mCurTokenDisplayId) {
             if (cs.curSession != null) {
                 // Fast case: if we are already connected to the input method,
                 // then just return it.
@@ -1882,8 +1888,7 @@
                     requestClientSessionLocked(cs);
                     return new InputBindResult(
                             InputBindResult.ResultCode.SUCCESS_WAITING_IME_SESSION,
-                            null, null, mCurId, mCurSeq,
-                            mCurUserActionNotificationSequenceNumber);
+                            null, null, mCurId, mCurSeq);
                 } else if (SystemClock.uptimeMillis()
                         < (mLastBindTime+TIME_TO_RECONNECT)) {
                     // In this case we have connected to the service, but
@@ -1895,8 +1900,7 @@
                     // to see if we can get back in touch with the service.
                     return new InputBindResult(
                             InputBindResult.ResultCode.SUCCESS_WAITING_IME_BINDING,
-                            null, null, mCurId, mCurSeq,
-                            mCurUserActionNotificationSequenceNumber);
+                            null, null, mCurId, mCurSeq);
                 } else {
                     EventLog.writeEvent(EventLogTags.IMF_FORCE_RECONNECT_IME,
                             mCurMethodId, SystemClock.uptimeMillis()-mLastBindTime, 0);
@@ -1918,8 +1922,7 @@
             // party code.
             return new InputBindResult(
                     InputBindResult.ResultCode.ERROR_SYSTEM_NOT_READY,
-                    null, null, mCurMethodId, mCurSeq,
-                    mCurUserActionNotificationSequenceNumber);
+                    null, null, mCurMethodId, mCurSeq);
         }
 
         InputMethodInfo info = mMethodMap.get(mCurMethodId);
@@ -1935,20 +1938,25 @@
                 com.android.internal.R.string.input_method_binding_label);
         mCurIntent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity(
                 mContext, 0, new Intent(Settings.ACTION_INPUT_METHOD_SETTINGS), 0));
+        final int displayId = mWindowManagerInternal.getDisplayIdForWindow(mCurFocusedWindow);
+        mCurTokenDisplayId = (displayId != INVALID_DISPLAY) ? displayId : DEFAULT_DISPLAY;
+
         if (bindCurrentInputMethodServiceLocked(mCurIntent, this, IME_CONNECTION_BIND_FLAGS)) {
             mLastBindTime = SystemClock.uptimeMillis();
             mHaveConnection = true;
             mCurId = info.getId();
             mCurToken = new Binder();
             try {
-                if (DEBUG) Slog.v(TAG, "Adding window token: " + mCurToken);
-                mIWindowManager.addWindowToken(mCurToken, TYPE_INPUT_METHOD, DEFAULT_DISPLAY);
+                if (DEBUG) {
+                    Slog.v(TAG, "Adding window token: " + mCurToken + " for display: "
+                            + mCurTokenDisplayId);
+                }
+                mIWindowManager.addWindowToken(mCurToken, TYPE_INPUT_METHOD, mCurTokenDisplayId);
             } catch (RemoteException e) {
             }
             return new InputBindResult(
                     InputBindResult.ResultCode.SUCCESS_WAITING_IME_BINDING,
-                    null, null, mCurId, mCurSeq,
-                    mCurUserActionNotificationSequenceNumber);
+                    null, null, mCurId, mCurSeq);
         }
         mCurIntent = null;
         Slog.w(TAG, "Failure connecting to input method service: " + mCurIntent);
@@ -1970,8 +1978,9 @@
                     return;
                 }
                 if (DEBUG) Slog.v(TAG, "Initiating attach with token: " + mCurToken);
-                executeOrSendMessage(mCurMethod, mCaller.obtainMessageOO(
-                        MSG_ATTACH_TOKEN, mCurMethod, mCurToken));
+                // Dispatch display id for InputMethodService to update context display.
+                executeOrSendMessage(mCurMethod, mCaller.obtainMessageIOO(
+                        MSG_INITIALIZE_IME, mCurTokenDisplayId, mCurMethod, mCurToken));
                 if (mCurClient != null) {
                     clearClientSessionLocked(mCurClient);
                     requestClientSessionLocked(mCurClient);
@@ -2017,15 +2026,19 @@
 
         if (mCurToken != null) {
             try {
-                if (DEBUG) Slog.v(TAG, "Removing window token: " + mCurToken);
+                if (DEBUG) {
+                    Slog.v(TAG, "Removing window token: " + mCurToken + " for display: "
+                            + mCurTokenDisplayId);
+                }
                 if ((mImeWindowVis & InputMethodService.IME_ACTIVE) != 0 && savePosition) {
                     // The current IME is shown. Hence an IME switch (transition) is happening.
                     mWindowManagerInternal.saveLastInputMethodWindowForTransition();
                 }
-                mIWindowManager.removeWindowToken(mCurToken, DEFAULT_DISPLAY);
+                mIWindowManager.removeWindowToken(mCurToken, mCurTokenDisplayId);
             } catch (RemoteException e) {
             }
             mCurToken = null;
+            mCurTokenDisplayId = INVALID_DISPLAY;
         }
 
         mCurId = null;
@@ -2115,8 +2128,9 @@
         }
     }
 
-    @Override
-    public void updateStatusIcon(IBinder token, String packageName, int iconId) {
+    @BinderThread
+    private void updateStatusIcon(@NonNull IBinder token, String packageName,
+            @DrawableRes int iconId) {
         synchronized (mMethodMap) {
             if (!calledWithValidToken(token)) {
                 return;
@@ -2220,8 +2234,7 @@
 
     @BinderThread
     @SuppressWarnings("deprecation")
-    @Override
-    public void setImeWindowStatus(IBinder token, int vis, int backDisposition) {
+    private void setImeWindowStatus(IBinder token, int vis, int backDisposition) {
         if (!calledWithValidToken(token)) {
             return;
         }
@@ -2256,8 +2269,7 @@
     }
 
     @BinderThread
-    @Override
-    public void reportStartInput(IBinder token, IBinder startInputToken) {
+    private void reportStartInput(IBinder token, IBinder startInputToken) {
         if (!calledWithValidToken(token)) {
             return;
         }
@@ -2523,19 +2535,14 @@
             synchronized (mMethodMap) {
                 if (mCurClient == null || client == null
                         || mCurClient.client.asBinder() != client.asBinder()) {
-                    try {
-                        // We need to check if this is the current client with
-                        // focus in the window manager, to allow this call to
-                        // be made before input is started in it.
-                        if (!mIWindowManager.inputMethodClientHasFocus(client)) {
-                            Slog.w(TAG, "Ignoring showSoftInput of uid " + uid + ": " + client);
-                            return false;
-                        }
-                    } catch (RemoteException e) {
+                    // We need to check if this is the current client with
+                    // focus in the window manager, to allow this call to
+                    // be made before input is started in it.
+                    if (!mWindowManagerInternal.inputMethodClientHasFocus(client)) {
+                        Slog.w(TAG, "Ignoring showSoftInput of uid " + uid + ": " + client);
                         return false;
                     }
                 }
-
                 if (DEBUG) Slog.v(TAG, "Client requesting input be shown");
                 return showCurrentInputLocked(flags, resultReceiver);
             }
@@ -2608,16 +2615,13 @@
             synchronized (mMethodMap) {
                 if (mCurClient == null || client == null
                         || mCurClient.client.asBinder() != client.asBinder()) {
-                    try {
-                        // We need to check if this is the current client with
-                        // focus in the window manager, to allow this call to
-                        // be made before input is started in it.
-                        if (!mIWindowManager.inputMethodClientHasFocus(client)) {
-                            if (DEBUG) Slog.w(TAG, "Ignoring hideSoftInput of uid "
-                                    + uid + ": " + client);
-                            return false;
+                    // We need to check if this is the current client with
+                    // focus in the window manager, to allow this call to
+                    // be made before input is started in it.
+                    if (!mWindowManagerInternal.inputMethodClientHasFocus(client)) {
+                        if (DEBUG) {
+                            Slog.w(TAG, "Ignoring hideSoftInput of uid " + uid + ": " + client);
                         }
-                    } catch (RemoteException e) {
                         return false;
                     }
                 }
@@ -2732,20 +2736,17 @@
                             + client.asBinder());
                 }
 
-                try {
-                    if (!mIWindowManager.inputMethodClientHasFocus(cs.client)) {
-                        // Check with the window manager to make sure this client actually
-                        // has a window with focus.  If not, reject.  This is thread safe
-                        // because if the focus changes some time before or after, the
-                        // next client receiving focus that has any interest in input will
-                        // be calling through here after that change happens.
-                        if (DEBUG) {
-                            Slog.w(TAG, "Focus gain on non-focused client " + cs.client
-                                    + " (uid=" + cs.uid + " pid=" + cs.pid + ")");
-                        }
-                        return InputBindResult.NOT_IME_TARGET_WINDOW;
+                if (!mWindowManagerInternal.inputMethodClientHasFocus(cs.client)) {
+                    // Check with the window manager to make sure this client actually
+                    // has a window with focus.  If not, reject.  This is thread safe
+                    // because if the focus changes some time before or after, the
+                    // next client receiving focus that has any interest in input will
+                    // be calling through here after that change happens.
+                    if (DEBUG) {
+                        Slog.w(TAG, "Focus gain on non-focused client " + cs.client
+                                + " (uid=" + cs.uid + " pid=" + cs.pid + ")");
                     }
-                } catch (RemoteException e) {
+                    return InputBindResult.NOT_IME_TARGET_WINDOW;
                 }
 
                 if (!calledFromValidUser) {
@@ -2767,7 +2768,7 @@
                     }
                     return new InputBindResult(
                             InputBindResult.ResultCode.SUCCESS_REPORT_WINDOW_FOCUS_ONLY,
-                            null, null, null, -1, -1);
+                            null, null, null, -1);
                 }
                 mCurFocusedWindow = windowToken;
                 mCurFocusedWindowSoftInputMode = softInputMode;
@@ -2803,6 +2804,15 @@
                                 // soft input window if it is shown.
                                 if (DEBUG) Slog.v(TAG, "Unspecified window will hide input");
                                 hideCurrentInputLocked(InputMethodManager.HIDE_NOT_ALWAYS, null);
+
+                                // If focused display changed, we should unbind current method
+                                // to make app window in previous display relayout after Ime
+                                // window token removed.
+                                final int newFocusDisplayId =
+                                        mWindowManagerInternal.getDisplayIdForWindow(windowToken);
+                                if (newFocusDisplayId != mCurTokenDisplayId) {
+                                    unbindCurrentMethodLocked(false);
+                                }
                             }
                         } else if (isTextEditor && doAutoShow && (softInputMode &
                                 WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) != 0) {
@@ -3075,8 +3085,8 @@
         }
     }
 
-    @Override
-    public boolean shouldOfferSwitchingToNextInputMethod(IBinder token) {
+    @BinderThread
+    private boolean shouldOfferSwitchingToNextInputMethod(@NonNull IBinder token) {
         if (!calledFromValidUser()) {
             return false;
         }
@@ -3159,13 +3169,21 @@
         return;
     }
 
+    /**
+     * This is kept due to {@link android.annotation.UnsupportedAppUsage} in
+     * {@link InputMethodManager#getInputMethodWindowVisibleHeight()} and a dependency in
+     * {@link InputMethodService#onCreate()}.
+     *
+     * <p>TODO(Bug 113914148): Check if we can remove this.</p>
+     * @return {@link WindowManagerInternal#getInputMethodWindowVisibleHeight()}
+     */
     @Override
     public int getInputMethodWindowVisibleHeight() {
-        return mWindowManagerInternal.getInputMethodWindowVisibleHeight();
+        return mWindowManagerInternal.getInputMethodWindowVisibleHeight(mCurTokenDisplayId);
     }
 
-    @Override
-    public void clearLastInputMethodWindowForTransition(IBinder token) {
+    @BinderThread
+    private void clearLastInputMethodWindowForTransition(IBinder token) {
         if (!calledFromValidUser()) {
             return;
         }
@@ -3177,17 +3195,16 @@
         mWindowManagerInternal.clearLastInputMethodWindowForTransition();
     }
 
-    @Override
-    public void notifyUserAction(int sequenceNumber) {
+    @BinderThread
+    private void notifyUserAction(@NonNull IBinder token) {
         if (DEBUG) {
-            Slog.d(TAG, "Got the notification of a user action. sequenceNumber:" + sequenceNumber);
+            Slog.d(TAG, "Got the notification of a user action.");
         }
         synchronized (mMethodMap) {
-            if (mCurUserActionNotificationSequenceNumber != sequenceNumber) {
+            if (mCurToken != token) {
                 if (DEBUG) {
-                    Slog.d(TAG, "Ignoring the user action notification due to the sequence number "
-                            + "mismatch. expected:" + mCurUserActionNotificationSequenceNumber
-                            + " actual: " + sequenceNumber);
+                    Slog.d(TAG, "Ignoring the user action notification from IMEs that are no longer"
+                            + " active.");
                 }
                 return;
             }
@@ -3227,8 +3244,8 @@
         }
     }
 
-    @Override
-    public void hideMySoftInput(IBinder token, int flags) {
+    @BinderThread
+    private void hideMySoftInput(@NonNull IBinder token, int flags) {
         if (!calledFromValidUser()) {
             return;
         }
@@ -3245,8 +3262,8 @@
         }
     }
 
-    @Override
-    public void showMySoftInput(IBinder token, int flags) {
+    @BinderThread
+    private void showMySoftInput(@NonNull IBinder token, int flags) {
         if (!calledFromValidUser()) {
             return;
         }
@@ -3360,11 +3377,16 @@
                     hideCurrentInputLocked(0, null);
                 }
                 return true;
-            case MSG_ATTACH_TOKEN:
+            case MSG_INITIALIZE_IME:
                 args = (SomeArgs)msg.obj;
                 try {
-                    if (DEBUG) Slog.v(TAG, "Sending attach of token: " + args.arg2);
-                    ((IInputMethod)args.arg1).attachToken((IBinder)args.arg2);
+                    if (DEBUG) {
+                        Slog.v(TAG, "Sending attach of token: " + args.arg2 + " for display: "
+                                + msg.arg1);
+                    }
+                    final IBinder token = (IBinder) args.arg2;
+                    ((IInputMethod) args.arg1).initializeInternal(token, msg.arg1,
+                            new InputMethodPrivilegedOperationsImpl(this, token));
                 } catch (RemoteException e) {
                 }
                 args.recycle();
@@ -3407,15 +3429,6 @@
             }
 
             // ---------------------------------------------------------
-            case MSG_ADD_CLIENT:
-                addClient((ClientState) msg.obj);
-                return true;
-
-            case MSG_REMOVE_CLIENT:
-                removeClient((IInputMethodClient) msg.obj);
-                return true;
-
-            // ---------------------------------------------------------
 
             case MSG_UNBIND_CLIENT:
                 try {
@@ -3457,20 +3470,6 @@
             case MSG_START_VR_INPUT:
                 startVrInputMethodNoCheck((ComponentName) msg.obj);
                 return true;
-            case MSG_SET_USER_ACTION_NOTIFICATION_SEQUENCE_NUMBER: {
-                final int sequenceNumber = msg.arg1;
-                final ClientState clientState = (ClientState)msg.obj;
-                try {
-                    clientState.client.setUserActionNotificationSequenceNumber(sequenceNumber);
-                } catch (RemoteException e) {
-                    Slog.w(TAG, "Got RemoteException sending "
-                            + "setUserActionNotificationSequenceNumber("
-                            + sequenceNumber + ") notification to pid "
-                            + clientState.pid + " uid "
-                            + clientState.uid);
-                }
-                return true;
-            }
             case MSG_REPORT_FULLSCREEN_MODE: {
                 final boolean fullscreen = msg.arg1 != 0;
                 final ClientState clientState = (ClientState)msg.obj;
@@ -3956,19 +3955,6 @@
             mSettings.saveCurrentInputMethodAndSubtypeToHistory(mCurMethodId, mCurrentSubtype);
         }
 
-        mCurUserActionNotificationSequenceNumber =
-                Math.max(mCurUserActionNotificationSequenceNumber + 1, 1);
-        if (DEBUG) {
-            Slog.d(TAG, "Bump mCurUserActionNotificationSequenceNumber:"
-                    + mCurUserActionNotificationSequenceNumber);
-        }
-
-        if (mCurClient != null && mCurClient.client != null) {
-            executeOrSendMessage(mCurClient.client, mCaller.obtainMessageIO(
-                    MSG_SET_USER_ACTION_NOTIFICATION_SEQUENCE_NUMBER,
-                    mCurUserActionNotificationSequenceNumber, mCurClient));
-        }
-
         if (isVrInput) {
             // Updates to InputMethod are transient in VR mode. Any changes to Settings are skipped.
             return;
@@ -4408,45 +4394,47 @@
 
     private static final class LocalServiceImpl extends InputMethodManagerInternal {
         @NonNull
-        private final Handler mHandler;
+        private final InputMethodManagerService mService;
 
-        LocalServiceImpl(@NonNull final Handler handler) {
-            mHandler = handler;
+        LocalServiceImpl(@NonNull InputMethodManagerService service) {
+            mService = service;
         }
 
         @Override
         public void addClient(IInputMethodClient client, IInputContext inputContext, int uid,
                 int pid) {
-            mHandler.sendMessage(mHandler.obtainMessage(MSG_ADD_CLIENT,
-                    new ClientState(client, inputContext, uid, pid)));
+            // Work around Bug 113877122: We need to handle this synchronously.  Otherwise, some
+            // IMM binder calls from the client process before we register this client.
+            mService.addClient(new ClientState(client, inputContext, uid, pid));
         }
 
         @Override
         public void removeClient(IInputMethodClient client) {
-            mHandler.sendMessage(mHandler.obtainMessage(MSG_REMOVE_CLIENT, client));
+            // Handle this synchronously to be consistent with addClient().
+            mService.removeClient(client);
         }
 
         @Override
         public void setInteractive(boolean interactive) {
             // Do everything in handler so as not to block the caller.
-            mHandler.sendMessage(mHandler.obtainMessage(MSG_SET_INTERACTIVE,
-                    interactive ? 1 : 0, 0));
+            mService.mHandler.obtainMessage(MSG_SET_INTERACTIVE, interactive ? 1 : 0, 0)
+                    .sendToTarget();
         }
 
         @Override
         public void hideCurrentInputMethod() {
-            mHandler.removeMessages(MSG_HIDE_CURRENT_INPUT_METHOD);
-            mHandler.sendEmptyMessage(MSG_HIDE_CURRENT_INPUT_METHOD);
+            mService.mHandler.removeMessages(MSG_HIDE_CURRENT_INPUT_METHOD);
+            mService.mHandler.sendEmptyMessage(MSG_HIDE_CURRENT_INPUT_METHOD);
         }
 
         @Override
         public void startVrInputMethodNoCheck(@Nullable ComponentName componentName) {
-            mHandler.sendMessage(mHandler.obtainMessage(MSG_START_VR_INPUT, componentName));
+            mService.mHandler.obtainMessage(MSG_START_VR_INPUT, componentName).sendToTarget();
         }
     }
 
-    @Override
-    public IInputContentUriToken createInputContentUriToken(@Nullable IBinder token,
+    @BinderThread
+    private IInputContentUriToken createInputContentUriToken(@Nullable IBinder token,
             @Nullable Uri contentUri, @Nullable String packageName) {
         if (!calledFromValidUser()) {
             return null;
@@ -4503,8 +4491,8 @@
         }
     }
 
-    @Override
-    public void reportFullscreenMode(IBinder token, boolean fullscreen) {
+    @BinderThread
+    private void reportFullscreenMode(IBinder token, boolean fullscreen) {
         if (!calledFromValidUser()) {
             return;
         }
@@ -4559,6 +4547,7 @@
             p.println("  mCurId=" + mCurId + " mHaveConnection=" + mHaveConnection
                     + " mBoundToMethod=" + mBoundToMethod + " mVisibleBound=" + mVisibleBound);
             p.println("  mCurToken=" + mCurToken);
+            p.println("  mCurTokenDisplayId=" + mCurTokenDisplayId);
             p.println("  mCurIntent=" + mCurIntent);
             method = mCurMethod;
             p.println("  mCurMethod=" + mCurMethod);
@@ -4568,8 +4557,6 @@
                     + " mShowForced=" + mShowForced
                     + " mInputShown=" + mInputShown);
             p.println("  mInFullscreenMode=" + mInFullscreenMode);
-            p.println("  mCurUserActionNotificationSequenceNumber="
-                    + mCurUserActionNotificationSequenceNumber);
             p.println("  mSystemReady=" + mSystemReady + " mInteractive=" + mIsInteractive);
             p.println("  mSettingsObserver=" + mSettingsObserver);
             p.println("  mSwitchingController:");
@@ -4979,4 +4966,99 @@
             return ShellCommandResult.SUCCESS;
         }
     }
+
+    private static final class InputMethodPrivilegedOperationsImpl
+            extends IInputMethodPrivilegedOperations.Stub {
+        private final InputMethodManagerService mImms;
+        private final IBinder mToken;
+        InputMethodPrivilegedOperationsImpl(InputMethodManagerService imms, IBinder token) {
+            mImms = imms;
+            mToken = token;
+        }
+
+        @BinderThread
+        @Override
+        public void setImeWindowStatus(int vis, int backDisposition) {
+            mImms.setImeWindowStatus(mToken, vis, backDisposition);
+        }
+
+        @BinderThread
+        @Override
+        public void reportStartInput(IBinder startInputToken) {
+            mImms.reportStartInput(mToken, startInputToken);
+        }
+
+        @BinderThread
+        @Override
+        public void clearLastInputMethodWindowForTransition() {
+            mImms.clearLastInputMethodWindowForTransition(mToken);
+        }
+
+        @BinderThread
+        @Override
+        public IInputContentUriToken createInputContentUriToken(Uri contentUri,
+                String packageName) {
+            return mImms.createInputContentUriToken(mToken, contentUri, packageName);
+        }
+
+        @BinderThread
+        @Override
+        public void reportFullscreenMode(boolean fullscreen) {
+            mImms.reportFullscreenMode(mToken, fullscreen);
+        }
+
+        @BinderThread
+        @Override
+        public void setInputMethod(String id) {
+            mImms.setInputMethod(mToken, id);
+        }
+
+        @BinderThread
+        @Override
+        public void setInputMethodAndSubtype(String id, InputMethodSubtype subtype) {
+            mImms.setInputMethodAndSubtype(mToken, id, subtype);
+        }
+
+        @BinderThread
+        @Override
+        public void hideMySoftInput(int flags) {
+            mImms.hideMySoftInput(mToken, flags);
+        }
+
+        @BinderThread
+        @Override
+        public void showMySoftInput(int flags) {
+            mImms.showMySoftInput(mToken, flags);
+        }
+
+        @BinderThread
+        @Override
+        public void updateStatusIcon(String packageName, @DrawableRes int iconId) {
+            mImms.updateStatusIcon(mToken, packageName, iconId);
+        }
+
+        @BinderThread
+        @Override
+        public boolean switchToPreviousInputMethod() {
+            return mImms.switchToPreviousInputMethod(mToken);
+        }
+
+        @BinderThread
+        @Override
+        public boolean switchToNextInputMethod(boolean onlyCurrentIme) {
+            return mImms.switchToNextInputMethod(mToken, onlyCurrentIme);
+        }
+
+        @BinderThread
+        @Override
+        public boolean shouldOfferSwitchingToNextInputMethod() {
+            return mImms.shouldOfferSwitchingToNextInputMethod(mToken);
+        }
+
+        @BinderThread
+        @Override
+        public void notifyUserActionAsync() {
+            mImms.notifyUserAction(mToken);
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index 260633a..389782a 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -2413,6 +2413,8 @@
                 BatteryStatsInternal mBatteryStatsInternal = LocalServices.getService
                         (BatteryStatsInternal.class);
                 mBatteryStatsInternal.noteJobsDeferred(uid, counter.numDeferred(), sinceLast);
+                StatsLog.write_non_chained(StatsLog.DEFERRED_JOB_STATS_REPORTED, uid, null,
+                        counter.numDeferred(), sinceLast);
             }
         }
     }
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index a54811b..31cf9e3 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -69,7 +69,6 @@
 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;
@@ -1577,6 +1576,8 @@
             mSingleShot = false;
             native_stop();
             mLastFixTime = 0;
+            // native_stop() may reset the position mode in hardware.
+            mLastPositionMode = null;
 
             // reset SV count to zero
             updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE);
diff --git a/services/core/java/com/android/server/net/NetworkPolicyLogger.java b/services/core/java/com/android/server/net/NetworkPolicyLogger.java
index b4bc7f5..452b699 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyLogger.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyLogger.java
@@ -46,9 +46,9 @@
     static final boolean LOGV = Log.isLoggable(TAG, Log.VERBOSE);
 
     private static final int MAX_LOG_SIZE =
-            ActivityManager.isLowRamDeviceStatic() ? 20 : 50;
+            ActivityManager.isLowRamDeviceStatic() ? 100 : 400;
     private static final int MAX_NETWORK_BLOCKED_LOG_SIZE =
-            ActivityManager.isLowRamDeviceStatic() ? 50 : 100;
+            ActivityManager.isLowRamDeviceStatic() ? 100 : 400;
 
     private static final int EVENT_TYPE_GENERIC = 0;
     private static final int EVENT_NETWORK_BLOCKED = 1;
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 76f9695..48e09d7 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -796,7 +796,7 @@
             try {
                 mActivityManager.registerUidObserver(mUidObserver,
                         ActivityManager.UID_OBSERVER_PROCSTATE|ActivityManager.UID_OBSERVER_GONE,
-                        ActivityManager.PROCESS_STATE_UNKNOWN, null);
+                        NetworkPolicyManager.FOREGROUND_THRESHOLD_STATE, "android");
                 mNetworkManager.registerObserver(mAlertObserver);
             } catch (RemoteException e) {
                 // ignored; both services live in system_server
diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java
index 340ae0a..7751f5f 100644
--- a/services/core/java/com/android/server/notification/ManagedServices.java
+++ b/services/core/java/com/android/server/notification/ManagedServices.java
@@ -694,7 +694,8 @@
 
             for (int userId : userIds) {
                 if (enabled) {
-                    if (isPackageOrComponentAllowed(component.toString(), userId)) {
+                    if (isPackageOrComponentAllowed(component.toString(), userId)
+                            || isPackageOrComponentAllowed(component.getPackageName(), userId)) {
                         registerServiceLocked(component, userId);
                     } else {
                         Slog.d(TAG, component + " no longer has permission to be bound");
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index ce71dd2..60597b5 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -35,6 +35,8 @@
 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR;
 import static android.content.pm.PackageManager.FEATURE_LEANBACK;
 import static android.content.pm.PackageManager.FEATURE_TELEVISION;
+import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE;
+import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_CRITICAL;
 import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_NORMAL;
@@ -203,6 +205,7 @@
 import com.android.server.lights.LightsManager;
 import com.android.server.notification.ManagedServices.ManagedServiceInfo;
 import com.android.server.notification.ManagedServices.UserProfiles;
+import com.android.server.pm.PackageManagerService;
 import com.android.server.policy.PhoneWindowManager;
 import com.android.server.statusbar.StatusBarManagerInternal;
 import com.android.server.uri.UriGrantsManagerInternal;
@@ -342,7 +345,7 @@
     private String mSoundNotificationKey;
     private String mVibrateNotificationKey;
 
-    private final SparseArray<ArraySet<ManagedServiceInfo>> mListenersDisablingEffects =
+    private final SparseArray<ArraySet<ComponentName>> mListenersDisablingEffects =
             new SparseArray<>();
     private List<ComponentName> mEffectsSuppressors = new ArrayList<>();
     private int mListenerHints;  // right now, all hints are global
@@ -470,8 +473,8 @@
                 // Gather all notification listener components for candidate pkgs.
                 Set<ComponentName> approvedListeners =
                         mListeners.queryPackageForServices(whitelisted,
-                                PackageManager.MATCH_DIRECT_BOOT_AWARE
-                                        | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userId);
+                                MATCH_DIRECT_BOOT_AWARE
+                                        | MATCH_DIRECT_BOOT_UNAWARE, userId);
                 for (ComponentName cn : approvedListeners) {
                     try {
                         getBinderService().setNotificationListenerAccessGrantedForUser(cn,
@@ -507,8 +510,8 @@
             // only be one
             Set<ComponentName> approvedAssistants =
                     mAssistants.queryPackageForServices(defaultAssistantAccess,
-                            PackageManager.MATCH_DIRECT_BOOT_AWARE
-                                    | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userId);
+                            MATCH_DIRECT_BOOT_AWARE
+                                    | MATCH_DIRECT_BOOT_UNAWARE, userId);
             for (ComponentName cn : approvedAssistants) {
                 try {
                     getBinderService().setNotificationAssistantAccessGrantedForUser(
@@ -1377,7 +1380,7 @@
             NotificationUsageStats usageStats, AtomicFile policyFile,
             ActivityManager activityManager, GroupHelper groupHelper, IActivityManager am,
             UsageStatsManagerInternal appUsageStats, DevicePolicyManagerInternal dpm,
-            IUriGrantsManager ugm, UriGrantsManagerInternal ugmInternal) {
+            IUriGrantsManager ugm, UriGrantsManagerInternal ugmInternal, AppOpsManager appOps) {
         Resources resources = getContext().getResources();
         mMaxPackageEnqueueRate = Settings.Global.getFloat(getContext().getContentResolver(),
                 Settings.Global.MAX_NOTIFICATION_ENQUEUE_RATE,
@@ -1390,7 +1393,7 @@
         mUgmInternal = ugmInternal;
         mPackageManager = packageManager;
         mPackageManagerClient = packageManagerClient;
-        mAppOps = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE);
+        mAppOps = appOps;
         mVibrator = (Vibrator) getContext().getSystemService(Context.VIBRATOR_SERVICE);
         mAppUsageStats = appUsageStats;
         mAlarmManager = (AlarmManager) getContext().getSystemService(Context.ALARM_SERVICE);
@@ -1544,7 +1547,8 @@
                 LocalServices.getService(UsageStatsManagerInternal.class),
                 LocalServices.getService(DevicePolicyManagerInternal.class),
                 UriGrantsManager.getService(),
-                LocalServices.getService(UriGrantsManagerInternal.class));
+                LocalServices.getService(UriGrantsManagerInternal.class),
+                (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE));
 
         // register for various Intents
         IntentFilter filter = new IntentFilter();
@@ -1780,10 +1784,10 @@
     private ArrayList<ComponentName> getSuppressors() {
         ArrayList<ComponentName> names = new ArrayList<ComponentName>();
         for (int i = mListenersDisablingEffects.size() - 1; i >= 0; --i) {
-            ArraySet<ManagedServiceInfo> serviceInfoList = mListenersDisablingEffects.valueAt(i);
+            ArraySet<ComponentName> serviceInfoList = mListenersDisablingEffects.valueAt(i);
 
-            for (ManagedServiceInfo info : serviceInfoList) {
-                names.add(info.component);
+            for (ComponentName info : serviceInfoList) {
+                names.add(info);
             }
         }
 
@@ -1799,11 +1803,10 @@
 
         for (int i = mListenersDisablingEffects.size() - 1; i >= 0; --i) {
             final int hint = mListenersDisablingEffects.keyAt(i);
-            final ArraySet<ManagedServiceInfo> listeners =
-                    mListenersDisablingEffects.valueAt(i);
+            final ArraySet<ComponentName> listeners = mListenersDisablingEffects.valueAt(i);
 
             if (hints == 0 || (hint & hints) == hint) {
-                removed = removed || listeners.remove(info);
+                removed |= listeners.remove(info.component);
             }
         }
 
@@ -1826,18 +1829,18 @@
 
     private void addDisabledHint(ManagedServiceInfo info, int hint) {
         if (mListenersDisablingEffects.indexOfKey(hint) < 0) {
-            mListenersDisablingEffects.put(hint, new ArraySet<ManagedServiceInfo>());
+            mListenersDisablingEffects.put(hint, new ArraySet<>());
         }
 
-        ArraySet<ManagedServiceInfo> hintListeners = mListenersDisablingEffects.get(hint);
-        hintListeners.add(info);
+        ArraySet<ComponentName> hintListeners = mListenersDisablingEffects.get(hint);
+        hintListeners.add(info.component);
     }
 
     private int calculateHints() {
         int hints = 0;
         for (int i = mListenersDisablingEffects.size() - 1; i >= 0; --i) {
             int hint = mListenersDisablingEffects.keyAt(i);
-            ArraySet<ManagedServiceInfo> serviceInfoList = mListenersDisablingEffects.valueAt(i);
+            ArraySet<ComponentName> serviceInfoList = mListenersDisablingEffects.valueAt(i);
 
             if (!serviceInfoList.isEmpty()) {
                 hints |= hint;
@@ -2234,6 +2237,60 @@
         }
 
         @Override
+        public void setNotificationDelegate(String callingPkg, String delegate) {
+            checkCallerIsSameApp(callingPkg);
+            final int callingUid = Binder.getCallingUid();
+            UserHandle user = UserHandle.getUserHandleForUid(callingUid);
+            try {
+                ApplicationInfo info =
+                        mPackageManager.getApplicationInfo(delegate,
+                                MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE,
+                                user.getIdentifier());
+                if (info != null) {
+                    mPreferencesHelper.setNotificationDelegate(
+                            callingPkg, callingUid, delegate, info.uid);
+                    savePolicyFile();
+                }
+            } catch (RemoteException e) {
+                // :(
+            }
+        }
+
+        @Override
+        public void revokeNotificationDelegate(String callingPkg) {
+            checkCallerIsSameApp(callingPkg);
+            mPreferencesHelper.revokeNotificationDelegate(callingPkg, Binder.getCallingUid());
+            savePolicyFile();
+        }
+
+        @Override
+        public String getNotificationDelegate(String callingPkg) {
+            // callable by Settings also
+            checkCallerIsSystemOrSameApp(callingPkg);
+            return mPreferencesHelper.getNotificationDelegate(callingPkg, Binder.getCallingUid());
+        }
+
+        @Override
+        public boolean canNotifyAsPackage(String callingPkg, String targetPkg) {
+            checkCallerIsSameApp(callingPkg);
+            final int callingUid = Binder.getCallingUid();
+            UserHandle user = UserHandle.getUserHandleForUid(callingUid);
+            try {
+                ApplicationInfo info =
+                        mPackageManager.getApplicationInfo(targetPkg,
+                                MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE,
+                                user.getIdentifier());
+                if (info != null) {
+                    return mPreferencesHelper.isDelegateAllowed(
+                            targetPkg, info.uid, callingPkg, callingUid);
+                }
+            } catch (RemoteException e) {
+                // :(
+            }
+            return false;
+        }
+
+        @Override
         public void updateNotificationChannelGroupForPackage(String pkg, int uid,
                 NotificationChannelGroup group) throws RemoteException {
             enforceSystemOrSystemUI("Caller not system or systemui");
@@ -2897,6 +2954,21 @@
         }
 
         @Override
+        public void clearRequestedListenerHints(INotificationListener token) {
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                synchronized (mNotificationLock) {
+                    final ManagedServiceInfo info = mListeners.checkServiceTokenLocked(token);
+                    removeDisabledHints(info);
+                    updateListenerHintsLocked();
+                    updateEffectsSuppressorLocked();
+                }
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
+
+        @Override
         public void requestHintsFromListener(INotificationListener token, int hints) {
             final long identity = Binder.clearCallingIdentity();
             try {
@@ -3802,11 +3874,12 @@
 
                 proto.write(
                     ListenersDisablingEffectsProto.HINT, mListenersDisablingEffects.keyAt(i));
-                final ArraySet<ManagedServiceInfo> listeners =
+                final ArraySet<ComponentName> listeners =
                     mListenersDisablingEffects.valueAt(i);
                 for (int j = 0; j < listeners.size(); j++) {
-                    final ManagedServiceInfo listener = listeners.valueAt(i);
-                    listener.writeToProto(proto, ListenersDisablingEffectsProto.LISTENERS, null);
+                    final ComponentName componentName = listeners.valueAt(i);
+                    componentName.writeToProto(proto,
+                            ListenersDisablingEffectsProto.LISTENER_COMPONENTS);
                 }
 
                 proto.end(effectsToken);
@@ -3945,15 +4018,14 @@
                     if (i > 0) pw.print(';');
                     pw.print("hint[" + hint + "]:");
 
-                    final ArraySet<ManagedServiceInfo> listeners =
-                            mListenersDisablingEffects.valueAt(i);
+                    final ArraySet<ComponentName> listeners = mListenersDisablingEffects.valueAt(i);
                     final int listenerSize = listeners.size();
 
                     for (int j = 0; j < listenerSize; j++) {
                         if (i > 0) pw.print(',');
-                        final ManagedServiceInfo listener = listeners.valueAt(i);
+                        final ComponentName listener = listeners.valueAt(i);
                         if (listener != null) {
-                            pw.print(listener.component);
+                            pw.print(listener);
                         }
                     }
                 }
@@ -4012,25 +4084,30 @@
         public void removeForegroundServiceFlagFromNotification(String pkg, int notificationId,
                 int userId) {
             checkCallerIsSystem();
-            mHandler.post(new Runnable() {
-                @Override
-                public void run() {
-                    synchronized (mNotificationLock) {
-                        removeForegroundServiceFlagByListLocked(
-                                mEnqueuedNotifications, pkg, notificationId, userId);
-                        removeForegroundServiceFlagByListLocked(
-                                mNotificationList, pkg, notificationId, userId);
+            mHandler.post(() -> {
+                synchronized (mNotificationLock) {
+                    // strip flag from all enqueued notifications. listeners will be informed
+                    // in post runnable.
+                    List<NotificationRecord> enqueued = findNotificationsByListLocked(
+                            mEnqueuedNotifications, pkg, null, notificationId, userId);
+                    for (int i = 0; i < enqueued.size(); i++) {
+                        removeForegroundServiceFlagLocked(enqueued.get(i));
+                    }
+
+                    // if posted notification exists, strip its flag and tell listeners
+                    NotificationRecord r = findNotificationByListLocked(
+                            mNotificationList, pkg, null, notificationId, userId);
+                    if (r != null) {
+                        removeForegroundServiceFlagLocked(r);
+                        mRankingHelper.sort(mNotificationList);
+                        mListeners.notifyPostedLocked(r, r);
                     }
                 }
             });
         }
 
         @GuardedBy("mNotificationLock")
-        private void removeForegroundServiceFlagByListLocked(
-                ArrayList<NotificationRecord> notificationList, String pkg, int notificationId,
-                int userId) {
-            NotificationRecord r = findNotificationByListLocked(
-                    notificationList, pkg, null, notificationId, userId);
+        private void removeForegroundServiceFlagLocked(NotificationRecord r) {
             if (r == null) {
                 return;
             }
@@ -4041,8 +4118,6 @@
             // initially *and* force remove FLAG_FOREGROUND_SERVICE.
             sbn.getNotification().flags =
                     (r.mOriginalFlags & ~FLAG_FOREGROUND_SERVICE);
-            mRankingHelper.sort(mNotificationList);
-            mListeners.notifyPostedLocked(r, r);
         }
     };
 
@@ -4053,20 +4128,21 @@
             Slog.v(TAG, "enqueueNotificationInternal: pkg=" + pkg + " id=" + id
                     + " notification=" + notification);
         }
-        checkCallerIsSystemOrSameApp(pkg);
-        checkRestrictedCategories(notification);
-
-        final int userId = ActivityManager.handleIncomingUser(callingPid,
-                callingUid, incomingUserId, true, false, "enqueueNotification", pkg);
-        final UserHandle user = new UserHandle(userId);
 
         if (pkg == null || notification == null) {
             throw new IllegalArgumentException("null not allowed: pkg=" + pkg
                     + " id=" + id + " notification=" + notification);
         }
 
-        // The system can post notifications for any package, let us resolve that.
-        final int notificationUid = resolveNotificationUid(opPkg, callingUid, userId);
+        final int userId = ActivityManager.handleIncomingUser(callingPid,
+                callingUid, incomingUserId, true, false, "enqueueNotification", pkg);
+        final UserHandle user = UserHandle.of(userId);
+
+        // Can throw a SecurityException if the calling uid doesn't have permission to post
+        // as "pkg"
+        final int notificationUid = resolveNotificationUid(opPkg, pkg, callingUid, userId);
+
+        checkRestrictedCategories(notification);
 
         // Fix the notification as best we can.
         try {
@@ -4193,17 +4269,28 @@
         }
     }
 
-    private int resolveNotificationUid(String opPackageName, int callingUid, int userId) {
-        // The system can post notifications on behalf of any package it wants
-        if (isCallerSystemOrPhone() && opPackageName != null && !"android".equals(opPackageName)) {
-            try {
-                return getContext().getPackageManager()
-                        .getPackageUidAsUser(opPackageName, userId);
-            } catch (NameNotFoundException e) {
-                /* ignore */
-            }
+    @VisibleForTesting
+    int resolveNotificationUid(String callingPkg, String targetPkg,
+            int callingUid, int userId) {
+        // posted from app A on behalf of app A
+        if (isCallerSameApp(targetPkg, callingUid) && TextUtils.equals(callingPkg, targetPkg)) {
+            return callingUid;
         }
-        return callingUid;
+
+        int targetUid = -1;
+        try {
+            targetUid = mPackageManagerClient.getPackageUidAsUser(targetPkg, userId);
+        } catch (NameNotFoundException e) {
+            /* ignore */
+        }
+        // posted from app A on behalf of app B
+        if (targetUid != -1 && (isCallerAndroid(callingPkg, callingUid)
+                || mPreferencesHelper.isDelegateAllowed(
+                        targetPkg, targetUid, callingPkg, callingUid))) {
+            return targetUid;
+        }
+
+        throw new SecurityException("Caller " + callingUid + " cannot post for pkg " + targetPkg);
     }
 
     /**
@@ -4222,7 +4309,8 @@
         // package or a registered listener can enqueue.  Prevents DOS attacks and deals with leaks.
         if (!isSystemNotification && !isNotificationFromListener) {
             synchronized (mNotificationLock) {
-                if (mNotificationsByKey.get(r.sbn.getKey()) == null && isCallerInstantApp(pkg)) {
+                if (mNotificationsByKey.get(r.sbn.getKey()) == null
+                        && isCallerInstantApp(pkg, callingUid)) {
                     // Ephemeral apps have some special constraints for notifications.
                     // They are not allowed to create new notifications however they are allowed to
                     // update notifications created by the system (e.g. a foreground service
@@ -5149,11 +5237,11 @@
                     try {
                         Thread.sleep(waitMs);
                     } catch (InterruptedException e) { }
-                    mVibrator.vibrate(record.sbn.getUid(), record.sbn.getOpPkg(),
+                    mVibrator.vibrate(record.sbn.getUid(), record.sbn.getPackageName(),
                             effect, "Notification (delayed)", record.getAudioAttributes());
                 }).start();
             } else {
-                mVibrator.vibrate(record.sbn.getUid(), record.sbn.getOpPkg(),
+                mVibrator.vibrate(record.sbn.getUid(), record.sbn.getPackageName(),
                         effect, "Notification", record.getAudioAttributes());
             }
             return true;
@@ -6182,6 +6270,21 @@
     }
 
     @GuardedBy("mNotificationLock")
+    private List<NotificationRecord> findNotificationsByListLocked(
+            ArrayList<NotificationRecord> list, String pkg, String tag, int id, int userId) {
+        List<NotificationRecord> matching = new ArrayList<>();
+        final int len = list.size();
+        for (int i = 0; i < len; i++) {
+            NotificationRecord r = list.get(i);
+            if (notificationMatchesUserId(r, userId) && r.sbn.getId() == id &&
+                    TextUtils.equals(r.sbn.getTag(), tag) && r.sbn.getPackageName().equals(pkg)) {
+                matching.add(r);
+            }
+        }
+        return matching;
+    }
+
+    @GuardedBy("mNotificationLock")
     private NotificationRecord findNotificationByListLocked(ArrayList<NotificationRecord> list,
             String key) {
         final int N = list.size();
@@ -6282,6 +6385,11 @@
         checkCallerIsSameApp(pkg);
     }
 
+    private boolean isCallerAndroid(String callingPkg, int uid) {
+        return isUidSystemOrPhone(uid) && callingPkg != null
+                && PackageManagerService.PLATFORM_PACKAGE_NAME.equals(callingPkg);
+    }
+
     /**
      * Check if the notification is of a category type that is restricted to system use only,
      * if so throw SecurityException
@@ -6302,13 +6410,13 @@
         }
     }
 
-    private boolean isCallerInstantApp(String pkg) {
+    private boolean isCallerInstantApp(String pkg, int callingUid) {
         // System is always allowed to act for ephemeral apps.
-        if (isCallerSystemOrPhone()) {
+        if (isUidSystemOrPhone(callingUid)) {
             return false;
         }
 
-        mAppOps.checkPackage(Binder.getCallingUid(), pkg);
+        mAppOps.checkPackage(callingUid, pkg);
 
         try {
             ApplicationInfo ai = mPackageManager.getApplicationInfo(pkg, 0,
@@ -6324,7 +6432,10 @@
     }
 
     private void checkCallerIsSameApp(String pkg) {
-        final int uid = Binder.getCallingUid();
+        checkCallerIsSameApp(pkg, Binder.getCallingUid());
+    }
+
+    private void checkCallerIsSameApp(String pkg, int uid) {
         try {
             ApplicationInfo ai = mPackageManager.getApplicationInfo(
                     pkg, 0, UserHandle.getCallingUserId());
@@ -6340,6 +6451,24 @@
         }
     }
 
+    private boolean isCallerSameApp(String pkg) {
+        try {
+            checkCallerIsSameApp(pkg);
+            return true;
+        } catch (SecurityException e) {
+            return false;
+        }
+    }
+
+    private boolean isCallerSameApp(String pkg, int uid) {
+        try {
+            checkCallerIsSameApp(pkg, uid);
+            return true;
+        } catch (SecurityException e) {
+            return false;
+        }
+    }
+
     private static String callStateToString(int state) {
         switch (state) {
             case TelephonyManager.CALL_STATE_IDLE: return "CALL_STATE_IDLE";
diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java
index 432d17c..13ff6e8 100644
--- a/services/core/java/com/android/server/notification/PreferencesHelper.java
+++ b/services/core/java/com/android/server/notification/PreferencesHelper.java
@@ -20,6 +20,7 @@
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.app.Notification;
 import android.app.NotificationChannel;
 import android.app.NotificationChannelGroup;
@@ -66,12 +67,14 @@
 public class PreferencesHelper implements RankingConfig {
     private static final String TAG = "NotificationPrefHelper";
     private static final int XML_VERSION = 1;
+    private static final int UNKNOWN_UID = UserHandle.USER_NULL;
 
     @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 TAG_DELEGATE = "delegate";
 
     private static final String ATT_VERSION = "version";
     private static final String ATT_NAME = "name";
@@ -82,6 +85,8 @@
     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 String ATT_ENABLED = "enabled";
+    private static final String ATT_USER_ALLOWED = "allowed";
 
     private static final int DEFAULT_PRIORITY = Notification.PRIORITY_DEFAULT;
     private static final int DEFAULT_VISIBILITY = NotificationManager.VISIBILITY_NO_OVERRIDE;
@@ -102,7 +107,7 @@
     }
 
     // pkg|uid => PackagePreferences
-    private final ArrayMap<String, PackagePreferences> mPackagePreferencess = new ArrayMap<>();
+    private final ArrayMap<String, PackagePreferences> mPackagePreferences = new ArrayMap<>();
     // pkg => PackagePreferences
     private final ArrayMap<String, PackagePreferences> mRestoredWithoutUids = new ArrayMap<>();
 
@@ -137,92 +142,117 @@
         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
-                            }
-                        }
+        synchronized (mPackagePreferences) {
+            // Clobber groups and channels with the xml, but don't delete other data that wasn't present
 
-                        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);
+            // 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, 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
                                 }
                             }
-                            // 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);
+
+                            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);
                                     }
-                                    r.channels.put(id, channel);
                                 }
-                            }
-                        }
+                                // 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);
+                                    }
+                                }
+                                // Delegate
+                                if (TAG_DELEGATE.equals(tagName)) {
+                                    int delegateId =
+                                            XmlUtils.readIntAttribute(parser, ATT_UID, UNKNOWN_UID);
+                                    String delegateName =
+                                            XmlUtils.readStringAttribute(parser, ATT_NAME);
+                                    boolean delegateEnabled = XmlUtils.readBooleanAttribute(
+                                            parser, ATT_ENABLED, Delegate.DEFAULT_ENABLED);
+                                    boolean userAllowed = XmlUtils.readBooleanAttribute(
+                                            parser, ATT_USER_ALLOWED,
+                                            Delegate.DEFAULT_USER_ALLOWED);
+                                    Delegate d = null;
+                                    if (delegateId != UNKNOWN_UID && !TextUtils.isEmpty(
+                                            delegateName)) {
+                                        d = new Delegate(
+                                                delegateName, delegateId, delegateEnabled,
+                                                userAllowed);
+                                    }
+                                    r.delegate = d;
+                                }
 
-                        try {
-                            deleteDefaultChannelIfNeeded(r);
-                        } catch (PackageManager.NameNotFoundException e) {
-                            Slog.e(TAG, "deleteDefaultChannelIfNeeded - Exception: " + e);
+                            }
+
+                            try {
+                                deleteDefaultChannelIfNeeded(r);
+                            } catch (PackageManager.NameNotFoundException e) {
+                                Slog.e(TAG, "deleteDefaultChannelIfNeeded - Exception: " + e);
+                            }
                         }
                     }
                 }
@@ -233,8 +263,8 @@
 
     private PackagePreferences getPackagePreferences(String pkg, int uid) {
         final String key = packagePreferencesKey(pkg, uid);
-        synchronized (mPackagePreferencess) {
-            return mPackagePreferencess.get(key);
+        synchronized (mPackagePreferences) {
+            return mPackagePreferences.get(key);
         }
     }
 
@@ -246,10 +276,10 @@
     private PackagePreferences getOrCreatePackagePreferences(String pkg, int uid, int importance,
             int priority, int visibility, boolean showBadge) {
         final String key = packagePreferencesKey(pkg, uid);
-        synchronized (mPackagePreferencess) {
+        synchronized (mPackagePreferences) {
             PackagePreferences
-                    r = (uid == PackagePreferences.UNKNOWN_UID) ? mRestoredWithoutUids.get(pkg)
-                    : mPackagePreferencess.get(key);
+                    r = (uid == UNKNOWN_UID) ? mRestoredWithoutUids.get(pkg)
+                    : mPackagePreferences.get(key);
             if (r == null) {
                 r = new PackagePreferences();
                 r.pkg = pkg;
@@ -265,10 +295,10 @@
                     Slog.e(TAG, "createDefaultChannelIfNeeded - Exception: " + e);
                 }
 
-                if (r.uid == PackagePreferences.UNKNOWN_UID) {
+                if (r.uid == UNKNOWN_UID) {
                     mRestoredWithoutUids.put(pkg, r);
                 } else {
-                    mPackagePreferencess.put(key, r);
+                    mPackagePreferences.put(key, r);
                 }
             }
             return r;
@@ -342,10 +372,10 @@
         out.startTag(null, TAG_RANKING);
         out.attribute(null, ATT_VERSION, Integer.toString(XML_VERSION));
 
-        synchronized (mPackagePreferencess) {
-            final int N = mPackagePreferencess.size();
+        synchronized (mPackagePreferences) {
+            final int N = mPackagePreferences.size();
             for (int i = 0; i < N; i++) {
-                final PackagePreferences r = mPackagePreferencess.valueAt(i);
+                final PackagePreferences r = mPackagePreferences.valueAt(i);
                 //TODO: http://b/22388012
                 if (forBackup && UserHandle.getUserId(r.uid) != UserHandle.USER_SYSTEM) {
                     continue;
@@ -357,7 +387,8 @@
                                 || r.showBadge != DEFAULT_SHOW_BADGE
                                 || r.lockedAppFields != DEFAULT_LOCKED_APP_FIELDS
                                 || r.channels.size() > 0
-                                || r.groups.size() > 0;
+                                || r.groups.size() > 0
+                                || r.delegate != null;
                 if (hasNonDefaultSettings) {
                     out.startTag(null, TAG_PACKAGE);
                     out.attribute(null, ATT_NAME, r.pkg);
@@ -378,6 +409,21 @@
                         out.attribute(null, ATT_UID, Integer.toString(r.uid));
                     }
 
+                    if (r.delegate != null) {
+                        out.startTag(null, TAG_DELEGATE);
+
+                        out.attribute(null, ATT_NAME, r.delegate.mPkg);
+                        out.attribute(null, ATT_UID, Integer.toString(r.delegate.mUid));
+                        if (r.delegate.mEnabled != Delegate.DEFAULT_ENABLED) {
+                            out.attribute(null, ATT_ENABLED, Boolean.toString(r.delegate.mEnabled));
+                        }
+                        if (r.delegate.mUserAllowed != Delegate.DEFAULT_USER_ALLOWED) {
+                            out.attribute(null, ATT_USER_ALLOWED,
+                                    Boolean.toString(r.delegate.mUserAllowed));
+                        }
+                        out.endTag(null, TAG_DELEGATE);
+                    }
+
                     for (NotificationChannelGroup group : r.groups.values()) {
                         group.writeXml(out);
                     }
@@ -844,10 +890,10 @@
 
     public int getBlockedAppCount(int userId) {
         int count = 0;
-        synchronized (mPackagePreferencess) {
-            final int N = mPackagePreferencess.size();
+        synchronized (mPackagePreferences) {
+            final int N = mPackagePreferences.size();
             for (int i = 0; i < N; i++) {
-                final PackagePreferences r = mPackagePreferencess.valueAt(i);
+                final PackagePreferences r = mPackagePreferences.valueAt(i);
                 if (userId == UserHandle.getUserId(r.uid)
                         && r.importance == IMPORTANCE_NONE) {
                     count++;
@@ -858,11 +904,11 @@
     }
 
     public void updateChannelsBypassingDnd() {
-        synchronized (mPackagePreferencess) {
-            final int numPackagePreferencess = mPackagePreferencess.size();
+        synchronized (mPackagePreferences) {
+            final int numPackagePreferencess = mPackagePreferences.size();
             for (int PackagePreferencesIndex = 0; PackagePreferencesIndex < numPackagePreferencess;
                     PackagePreferencesIndex++) {
-                final PackagePreferences r = mPackagePreferencess.valueAt(PackagePreferencesIndex);
+                final PackagePreferences r = mPackagePreferences.valueAt(PackagePreferencesIndex);
                 final int numChannels = r.channels.size();
 
                 for (int channelIndex = 0; channelIndex < numChannels; channelIndex++) {
@@ -923,16 +969,76 @@
      * 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) {
+        PackagePreferences prefs = getOrCreatePackagePreferences(packageName, uid);
+        if ((prefs.lockedAppFields & LockableAppFields.USER_LOCKED_IMPORTANCE) != 0) {
             return;
         }
 
-        PackagePreferences.lockedAppFields =
-                PackagePreferences.lockedAppFields | LockableAppFields.USER_LOCKED_IMPORTANCE;
+        prefs.lockedAppFields = prefs.lockedAppFields | LockableAppFields.USER_LOCKED_IMPORTANCE;
         updateConfig();
     }
 
+    /**
+     * Returns the delegate for a given package, if it's allowed by the package and the user.
+     */
+    public @Nullable String getNotificationDelegate(String sourcePkg, int sourceUid) {
+        PackagePreferences prefs = getPackagePreferences(sourcePkg, sourceUid);
+
+        if (prefs == null || prefs.delegate == null) {
+            return null;
+        }
+        if (!prefs.delegate.mUserAllowed || !prefs.delegate.mEnabled) {
+            return null;
+        }
+        return prefs.delegate.mPkg;
+    }
+
+    /**
+     * Used by an app to delegate notification posting privileges to another apps.
+     */
+    public void setNotificationDelegate(String sourcePkg, int sourceUid,
+            String delegatePkg, int delegateUid) {
+        PackagePreferences prefs = getOrCreatePackagePreferences(sourcePkg, sourceUid);
+
+        boolean userAllowed = prefs.delegate == null || prefs.delegate.mUserAllowed;
+        Delegate delegate = new Delegate(delegatePkg, delegateUid, true, userAllowed);
+        prefs.delegate = delegate;
+        updateConfig();
+    }
+
+    /**
+     * Used by an app to turn off its notification delegate.
+     */
+    public void revokeNotificationDelegate(String sourcePkg, int sourceUid) {
+        PackagePreferences prefs = getPackagePreferences(sourcePkg, sourceUid);
+        if (prefs != null && prefs.delegate != null) {
+            prefs.delegate.mEnabled = false;
+            updateConfig();
+        }
+    }
+
+    /**
+     * Toggles whether an app can have a notification delegate on behalf of a user.
+     */
+    public void toggleNotificationDelegate(String sourcePkg, int sourceUid, boolean userAllowed) {
+        PackagePreferences prefs = getPackagePreferences(sourcePkg, sourceUid);
+        if (prefs != null && prefs.delegate != null) {
+            prefs.delegate.mUserAllowed = userAllowed;
+            updateConfig();
+        }
+    }
+
+    /**
+     * Returns whether the given app is allowed on post notifications on behalf of the other given
+     * app.
+     */
+    public boolean isDelegateAllowed(String sourcePkg, int sourceUid,
+            String potentialDelegatePkg, int potentialDelegateUid) {
+        PackagePreferences prefs = getPackagePreferences(sourcePkg, sourceUid);
+
+        return prefs != null && prefs.isValidDelegate(potentialDelegatePkg, potentialDelegateUid);
+    }
+
     @VisibleForTesting
     void lockFieldsForUpdate(NotificationChannel original, NotificationChannel update) {
         if (original.canBypassDnd() != update.canBypassDnd()) {
@@ -966,8 +1072,8 @@
         pw.println("per-package config:");
 
         pw.println("PackagePreferencess:");
-        synchronized (mPackagePreferencess) {
-            dumpPackagePreferencess(pw, prefix, filter, mPackagePreferencess);
+        synchronized (mPackagePreferences) {
+            dumpPackagePreferencess(pw, prefix, filter, mPackagePreferences);
         }
         pw.println("Restored without uid:");
         dumpPackagePreferencess(pw, prefix, filter, mRestoredWithoutUids);
@@ -975,9 +1081,9 @@
 
     public void dump(ProtoOutputStream proto,
             @NonNull NotificationManagerService.DumpFilter filter) {
-        synchronized (mPackagePreferencess) {
+        synchronized (mPackagePreferences) {
             dumpPackagePreferencess(proto, RankingHelperProto.RECORDS, filter,
-                    mPackagePreferencess);
+                    mPackagePreferences);
         }
         dumpPackagePreferencess(proto, RankingHelperProto.RECORDS_RESTORED_WITHOUT_UID, filter,
                 mRestoredWithoutUids);
@@ -994,8 +1100,7 @@
                 pw.print("  AppSettings: ");
                 pw.print(r.pkg);
                 pw.print(" (");
-                pw.print(r.uid == PackagePreferences.UNKNOWN_UID ? "UNKNOWN_UID"
-                        : Integer.toString(r.uid));
+                pw.print(r.uid == UNKNOWN_UID ? "UNKNOWN_UID" : Integer.toString(r.uid));
                 pw.print(')');
                 if (r.importance != DEFAULT_IMPORTANCE) {
                     pw.print(" importance=");
@@ -1063,10 +1168,10 @@
         } catch (JSONException e) {
             // pass
         }
-        synchronized (mPackagePreferencess) {
-            final int N = mPackagePreferencess.size();
+        synchronized (mPackagePreferences) {
+            final int N = mPackagePreferences.size();
             for (int i = 0; i < N; i++) {
-                final PackagePreferences r = mPackagePreferencess.valueAt(i);
+                final PackagePreferences r = mPackagePreferences.valueAt(i);
                 if (filter == null || filter.matches(r.pkg)) {
                     JSONObject PackagePreferences = new JSONObject();
                     try {
@@ -1143,11 +1248,11 @@
     }
 
     public Map<Integer, String> getPackageBans() {
-        synchronized (mPackagePreferencess) {
-            final int N = mPackagePreferencess.size();
+        synchronized (mPackagePreferences) {
+            final int N = mPackagePreferences.size();
             ArrayMap<Integer, String> packageBans = new ArrayMap<>(N);
             for (int i = 0; i < N; i++) {
-                final PackagePreferences r = mPackagePreferencess.valueAt(i);
+                final PackagePreferences r = mPackagePreferences.valueAt(i);
                 if (r.importance == IMPORTANCE_NONE) {
                     packageBans.put(r.uid, r.pkg);
                 }
@@ -1187,9 +1292,9 @@
 
     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);
+        synchronized (mPackagePreferences) {
+            for (int i = 0; i < mPackagePreferences.size(); i++) {
+                final PackagePreferences r = mPackagePreferences.valueAt(i);
                 int channelCount = 0;
                 for (int j = 0; j < r.channels.size(); j++) {
                     if (!r.channels.valueAt(j).isDeleted()) {
@@ -1203,22 +1308,22 @@
     }
 
     public void onUserRemoved(int userId) {
-        synchronized (mPackagePreferencess) {
-            int N = mPackagePreferencess.size();
+        synchronized (mPackagePreferences) {
+            int N = mPackagePreferences.size();
             for (int i = N - 1; i >= 0; i--) {
-                PackagePreferences PackagePreferences = mPackagePreferencess.valueAt(i);
+                PackagePreferences PackagePreferences = mPackagePreferences.valueAt(i);
                 if (UserHandle.getUserId(PackagePreferences.uid) == userId) {
-                    mPackagePreferencess.removeAt(i);
+                    mPackagePreferences.removeAt(i);
                 }
             }
         }
     }
 
     protected void onLocaleChanged(Context context, int userId) {
-        synchronized (mPackagePreferencess) {
-            int N = mPackagePreferencess.size();
+        synchronized (mPackagePreferences) {
+            int N = mPackagePreferences.size();
             for (int i = 0; i < N; i++) {
-                PackagePreferences PackagePreferences = mPackagePreferencess.valueAt(i);
+                PackagePreferences PackagePreferences = mPackagePreferences.valueAt(i);
                 if (UserHandle.getUserId(PackagePreferences.uid) == userId) {
                     if (PackagePreferences.channels.containsKey(
                             NotificationChannel.DEFAULT_CHANNEL_ID)) {
@@ -1244,8 +1349,8 @@
             for (int i = 0; i < size; i++) {
                 final String pkg = pkgList[i];
                 final int uid = uidList[i];
-                synchronized (mPackagePreferencess) {
-                    mPackagePreferencess.remove(packagePreferencesKey(pkg, uid));
+                synchronized (mPackagePreferences) {
+                    mPackagePreferences.remove(packagePreferencesKey(pkg, uid));
                 }
                 mRestoredWithoutUids.remove(pkg);
                 updated = true;
@@ -1258,8 +1363,8 @@
                     try {
                         r.uid = mPm.getPackageUidAsUser(r.pkg, changeUserId);
                         mRestoredWithoutUids.remove(pkg);
-                        synchronized (mPackagePreferencess) {
-                            mPackagePreferencess.put(packagePreferencesKey(r.pkg, r.uid), r);
+                        synchronized (mPackagePreferences) {
+                            mPackagePreferences.put(packagePreferencesKey(r.pkg, r.uid), r);
                         }
                         updated = true;
                     } catch (PackageManager.NameNotFoundException e) {
@@ -1268,11 +1373,13 @@
                 }
                 // Package upgrade
                 try {
-                    PackagePreferences fullPackagePreferences = getPackagePreferences(pkg,
-                            mPm.getPackageUidAsUser(pkg, changeUserId));
-                    if (fullPackagePreferences != null) {
-                        createDefaultChannelIfNeeded(fullPackagePreferences);
-                        deleteDefaultChannelIfNeeded(fullPackagePreferences);
+                    synchronized (mPackagePreferences) {
+                        PackagePreferences fullPackagePreferences = getPackagePreferences(pkg,
+                                mPm.getPackageUidAsUser(pkg, changeUserId));
+                        if (fullPackagePreferences != null) {
+                            createDefaultChannelIfNeeded(fullPackagePreferences);
+                            deleteDefaultChannelIfNeeded(fullPackagePreferences);
+                        }
                     }
                 } catch (PackageManager.NameNotFoundException e) {
                 }
@@ -1356,8 +1463,6 @@
     }
 
     private static class PackagePreferences {
-        static int UNKNOWN_UID = UserHandle.USER_NULL;
-
         String pkg;
         int uid = UNKNOWN_UID;
         int importance = DEFAULT_IMPORTANCE;
@@ -1366,7 +1471,37 @@
         boolean showBadge = DEFAULT_SHOW_BADGE;
         int lockedAppFields = DEFAULT_LOCKED_APP_FIELDS;
 
+        Delegate delegate = null;
         ArrayMap<String, NotificationChannel> channels = new ArrayMap<>();
         Map<String, NotificationChannelGroup> groups = new ConcurrentHashMap<>();
+
+        public boolean isValidDelegate(String pkg, int uid) {
+            return delegate != null && delegate.isAllowed(pkg, uid);
+        }
+    }
+
+    private static class Delegate {
+        static final boolean DEFAULT_ENABLED = true;
+        static final boolean DEFAULT_USER_ALLOWED = true;
+        String mPkg;
+        int mUid = UNKNOWN_UID;
+        boolean mEnabled = DEFAULT_ENABLED;
+        boolean mUserAllowed = DEFAULT_USER_ALLOWED;
+
+        Delegate(String pkg, int uid, boolean enabled, boolean userAllowed) {
+            mPkg = pkg;
+            mUid = uid;
+            mEnabled = enabled;
+            mUserAllowed = userAllowed;
+        }
+
+        public boolean isAllowed(String pkg, int uid) {
+            if (pkg == null || uid == UNKNOWN_UID) {
+                return false;
+            }
+            return pkg.equals(mPkg)
+                    && uid == mUid
+                    && (mUserAllowed && mEnabled);
+        }
     }
 }
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index 6ac72d3..4dd2bf2 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -501,9 +501,14 @@
     }
 
     protected AutomaticZenRule createAutomaticZenRule(ZenRule rule) {
-        return new AutomaticZenRule(rule.name, rule.component, rule.conditionId,
-                NotificationManager.zenModeToInterruptionFilter(rule.zenMode), rule.enabled,
-                rule.creationTime);
+        if (rule.zenPolicy != null) {
+            return new AutomaticZenRule(rule.name, rule.component, rule.conditionId, rule.zenPolicy,
+                    rule.enabled, rule.creationTime);
+        } else {
+            return new AutomaticZenRule(rule.name, rule.component, rule.conditionId,
+                    NotificationManager.zenModeToInterruptionFilter(rule.zenMode), rule.enabled,
+                    rule.creationTime);
+        }
     }
 
     public void setManualZenMode(int zenMode, Uri conditionId, String caller, String reason) {
@@ -667,6 +672,9 @@
         }
     }
 
+    /**
+     * @return user-specified default notification policy for priority only do not disturb
+     */
     public Policy getNotificationPolicy() {
         return getNotificationPolicy(mConfig);
     }
@@ -675,6 +683,9 @@
         return config == null ? null : config.toNotificationPolicy();
     }
 
+    /**
+     * Sets the global notification policy used for priority only do not disturb
+     */
     public void setNotificationPolicy(Policy policy) {
         if (policy == null || mConfig == null) return;
         synchronized (mConfig) {
@@ -770,9 +781,7 @@
             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
-        }
+        evaluateZenMode(reason, setRingerMode);
         mConditions.evaluateConfig(config, triggeringComponent, true /*processSubscriptions*/);
     }
 
@@ -798,7 +807,7 @@
     }
 
     @VisibleForTesting
-    protected boolean evaluateZenMode(String reason, boolean setRingerMode) {
+    protected void evaluateZenMode(String reason, boolean setRingerMode) {
         if (DEBUG) Log.d(TAG, "evaluateZenMode");
         final int zenBefore = mZenMode;
         final int zen = computeZenMode();
@@ -813,7 +822,6 @@
         if (zen != zenBefore) {
             mHandler.postDispatchOnZenModeChanged();
         }
-        return true;
     }
 
     private void updateRingerModeAffectedStreams() {
@@ -822,7 +830,9 @@
         }
     }
 
+
     private int computeZenMode() {
+        // TODO: use mConfig.zenPolicy
         if (mConfig == null) return Global.ZEN_MODE_OFF;
         synchronized (mConfig) {
             if (mConfig.manualRule != null) return mConfig.manualRule.zenMode;
diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java
index c738701..f1b03d1 100644
--- a/services/core/java/com/android/server/om/OverlayManagerService.java
+++ b/services/core/java/com/android/server/om/OverlayManagerService.java
@@ -558,8 +558,8 @@
         @Override
         public boolean setEnabledExclusive(@Nullable final String packageName, final boolean enable,
                 int userId) throws RemoteException {
-            enforceChangeOverlayPackagesPermission("setEnabled");
-            userId = handleIncomingUser(userId, "setEnabled");
+            enforceChangeOverlayPackagesPermission("setEnabledExclusive");
+            userId = handleIncomingUser(userId, "setEnabledExclusive");
             if (packageName == null || !enable) {
                 return false;
             }
@@ -578,8 +578,8 @@
         @Override
         public boolean setEnabledExclusiveInCategory(@Nullable String packageName, int userId)
                 throws RemoteException {
-            enforceChangeOverlayPackagesPermission("setEnabled");
-            userId = handleIncomingUser(userId, "setEnabled");
+            enforceChangeOverlayPackagesPermission("setEnabledExclusiveInCategory");
+            userId = handleIncomingUser(userId, "setEnabledExclusiveInCategory");
             if (packageName == null) {
                 return false;
             }
diff --git a/services/core/java/com/android/server/pm/OtaDexoptService.java b/services/core/java/com/android/server/pm/OtaDexoptService.java
index cf47d4e..bca3ca7 100644
--- a/services/core/java/com/android/server/pm/OtaDexoptService.java
+++ b/services/core/java/com/android/server/pm/OtaDexoptService.java
@@ -40,6 +40,7 @@
 import java.io.FileDescriptor;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.List;
 import java.util.concurrent.TimeUnit;
 
@@ -124,7 +125,8 @@
         synchronized (mPackageManagerService.mPackages) {
             // Important: the packages we need to run with ab-ota compiler-reason.
             important = PackageManagerServiceUtils.getPackagesForDexopt(
-                    mPackageManagerService.mPackages.values(), mPackageManagerService);
+                    mPackageManagerService.mPackages.values(), mPackageManagerService,
+                    DEBUG_DEXOPT);
             // Others: we should optimize this with the (first-)boot compiler-reason.
             others = new ArrayList<>(mPackageManagerService.mPackages.values());
             others.removeAll(important);
@@ -157,6 +159,24 @@
         long spaceAvailableNow = getAvailableSpace();
 
         prepareMetricsLogging(important.size(), others.size(), spaceAvailable, spaceAvailableNow);
+
+        if (DEBUG_DEXOPT) {
+            try {
+                // Output some data about the packages.
+                PackageParser.Package lastUsed = Collections.max(important,
+                        (pkg1, pkg2) -> Long.compare(
+                                pkg1.getLatestForegroundPackageUseTimeInMills(),
+                                pkg2.getLatestForegroundPackageUseTimeInMills()));
+                Log.d(TAG, "A/B OTA: lastUsed time = "
+                        + lastUsed.getLatestForegroundPackageUseTimeInMills());
+                Log.d(TAG, "A/B OTA: deprioritized packages:");
+                for (PackageParser.Package pkg : others) {
+                    Log.d(TAG, "  " + pkg.packageName + " - "
+                            + pkg.getLatestForegroundPackageUseTimeInMills());
+                }
+            } catch (Exception ignored) {
+            }
+        }
     }
 
     @Override
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index d305032..8f2833f 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -59,6 +59,7 @@
 import android.content.pm.PackageParser.ApkLite;
 import android.content.pm.PackageParser.PackageLite;
 import android.content.pm.PackageParser.PackageParserException;
+import android.content.pm.dex.DexMetadataHelper;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.os.Binder;
@@ -99,7 +100,6 @@
 import com.android.server.pm.Installer.InstallerException;
 import com.android.server.pm.PackageInstallerService.PackageInstallObserverAdapter;
 
-import android.content.pm.dex.DexMetadataHelper;
 import libcore.io.IoUtils;
 
 import org.xmlpull.v1.XmlPullParser;
@@ -122,7 +122,6 @@
     private static final boolean LOGD = true;
     private static final String REMOVE_SPLIT_MARKER_EXTENSION = ".removed";
 
-    private static final int MSG_EARLY_BIND = 0;
     private static final int MSG_COMMIT = 1;
     private static final int MSG_ON_PACKAGE_INSTALLED = 2;
 
@@ -168,7 +167,6 @@
     final int userId;
     final SessionParams params;
     final long createdMillis;
-    final int defaultContainerGid;
 
     /** Staging location where client data is written. */
     final File stageDir;
@@ -285,9 +283,6 @@
         @Override
         public boolean handleMessage(Message msg) {
             switch (msg.what) {
-                case MSG_EARLY_BIND:
-                    earlyBindToDefContainer();
-                    break;
                 case MSG_COMMIT:
                     synchronized (mLock) {
                         try {
@@ -323,10 +318,6 @@
         }
     };
 
-    private void earlyBindToDefContainer() {
-        mPm.earlyBindToDefContainer();
-    }
-
     /**
      * @return {@code true} iff the installing is app an device owner or affiliated profile owner.
      */
@@ -413,19 +404,6 @@
                 }
             }
         }
-
-        final long identity = Binder.clearCallingIdentity();
-        try {
-            final int uid = mPm.getPackageUid(PackageManagerService.DEFAULT_CONTAINER_PACKAGE,
-                    PackageManager.MATCH_SYSTEM_ONLY, UserHandle.USER_SYSTEM);
-            defaultContainerGid = UserHandle.getSharedAppGid(uid);
-        } finally {
-            Binder.restoreCallingIdentity(identity);
-        }
-        // attempt to bind to the DefContainer as early as possible
-        if ((params.installFlags & PackageManager.INSTALL_INSTANT_APP) != 0) {
-            mHandler.sendMessage(mHandler.obtainMessage(MSG_EARLY_BIND));
-        }
     }
 
     public SessionInfo generateInfo() {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 182901a..adf95dc 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -88,8 +88,6 @@
 import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
 import static android.os.storage.StorageManager.FLAG_STORAGE_CE;
 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;
@@ -137,7 +135,6 @@
 import android.content.IntentFilter;
 import android.content.IntentSender;
 import android.content.IntentSender.SendIntentException;
-import android.content.ServiceConnection;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.AppsQueryHelper;
@@ -207,14 +204,12 @@
 import android.os.Bundle;
 import android.os.Debug;
 import android.os.Environment;
-import android.os.Environment.UserEnvironment;
 import android.os.FileUtils;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.Message;
 import android.os.Parcel;
-import android.os.ParcelFileDescriptor;
 import android.os.PatternMatcher;
 import android.os.PersistableBundle;
 import android.os.Process;
@@ -273,12 +268,10 @@
 
 import com.android.internal.R;
 import com.android.internal.annotations.GuardedBy;
-import com.android.internal.app.IMediaContainerService;
 import com.android.internal.app.ResolverActivity;
 import com.android.internal.content.NativeLibraryHelper;
 import com.android.internal.content.PackageHelper;
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.os.IParcelFileDescriptorFactory;
 import com.android.internal.os.SomeArgs;
 import com.android.internal.os.Zygote;
 import com.android.internal.telephony.CarrierAppUtils;
@@ -551,12 +544,6 @@
 
     public static final String PLATFORM_PACKAGE_NAME = "android";
 
-    public static final String DEFAULT_CONTAINER_PACKAGE = "com.android.defcontainer";
-
-    public static final ComponentName DEFAULT_CONTAINER_COMPONENT = new ComponentName(
-            DEFAULT_CONTAINER_PACKAGE,
-            "com.android.defcontainer.DefaultContainerService");
-
     private static final String KILL_APP_REASON_GIDS_CHANGED =
             "permission grant or revoke changed gids";
 
@@ -1238,18 +1225,9 @@
     }
     final PendingPackageBroadcasts mPendingBroadcasts = new PendingPackageBroadcasts();
 
-    // Service Connection to remote media container service to copy
-    // package uri's from external media onto secure containers
-    // or internal storage.
-    private IMediaContainerService mContainerService = null;
-
     static final int SEND_PENDING_BROADCAST = 1;
-    static final int MCS_BOUND = 3;
     static final int INIT_COPY = 5;
-    static final int MCS_UNBIND = 6;
     static final int POST_INSTALL = 9;
-    static final int MCS_RECONNECT = 10;
-    static final int MCS_GIVE_UP = 11;
     static final int WRITE_SETTINGS = 13;
     static final int WRITE_PACKAGE_RESTRICTIONS = 14;
     static final int PACKAGE_VERIFIED = 15;
@@ -1258,7 +1236,6 @@
     static final int INTENT_FILTER_VERIFIED = 18;
     static final int WRITE_PACKAGE_LIST = 19;
     static final int INSTANT_APP_RESOLUTION_PHASE_TWO = 20;
-    static final int DEF_CONTAINER_BIND = 21;
 
     static final int WRITE_SETTINGS_DELAY = 10*1000;  // 10 seconds
 
@@ -1273,21 +1250,6 @@
     // Stores a list of users whose package restrictions file needs to be updated
     private ArraySet<Integer> mDirtyUsers = new ArraySet<>();
 
-    final private DefaultContainerConnection mDefContainerConn =
-            new DefaultContainerConnection();
-    class DefaultContainerConnection implements ServiceConnection {
-        public void onServiceConnected(ComponentName name, IBinder service) {
-            if (DEBUG_SD_INSTALL) Log.i(TAG, "onServiceConnected");
-            final IMediaContainerService imcs = IMediaContainerService.Stub
-                    .asInterface(Binder.allowBlocking(service));
-            mHandler.sendMessage(mHandler.obtainMessage(MCS_BOUND, imcs));
-        }
-
-        public void onServiceDisconnected(ComponentName name) {
-            if (DEBUG_SD_INSTALL) Log.i(TAG, "onServiceDisconnected");
-        }
-    }
-
     // Recordkeeping of restore-after-install operations that are currently in flight
     // between the Package Manager and the Backup Manager
     static class PostInstallData {
@@ -1346,31 +1308,6 @@
     private final CompilerStats mCompilerStats = new CompilerStats();
 
     class PackageHandler extends Handler {
-        private boolean mBound = false;
-        final ArrayList<HandlerParams> mPendingInstalls =
-                new ArrayList<>();
-
-        private boolean connectToService() {
-            if (DEBUG_INSTALL) Log.i(TAG, "Trying to bind to DefaultContainerService");
-            Intent service = new Intent().setComponent(DEFAULT_CONTAINER_COMPONENT);
-            Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
-            if (mContext.bindServiceAsUser(service, mDefContainerConn,
-                    Context.BIND_AUTO_CREATE, UserHandle.SYSTEM)) {
-                Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
-                mBound = true;
-                return true;
-            }
-            Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
-            return false;
-        }
-
-        private void disconnectService() {
-            mContainerService = null;
-            mBound = false;
-            Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
-            mContext.unbindService(mDefContainerConn);
-            Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
-        }
 
         PackageHandler(Looper looper) {
             super(looper);
@@ -1386,167 +1323,18 @@
 
         void doHandleMessage(Message msg) {
             switch (msg.what) {
-                case DEF_CONTAINER_BIND:
-                    if (!mBound) {
-                        Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "earlyBindingMCS",
-                                System.identityHashCode(mHandler));
-                        if (!connectToService()) {
-                            Slog.e(TAG, "Failed to bind to media container service");
-                        }
-                        Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "earlyBindingMCS",
-                                System.identityHashCode(mHandler));
-                    }
-                    break;
                 case INIT_COPY: {
                     HandlerParams params = (HandlerParams) msg.obj;
-                    int idx = mPendingInstalls.size();
-                    if (DEBUG_INSTALL) Slog.i(TAG, "init_copy idx=" + idx + ": " + params);
-                    // If a bind was already initiated we dont really
-                    // need to do anything. The pending install
-                    // will be processed later on.
-                    if (!mBound) {
-                        Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "bindingMCS",
-                                System.identityHashCode(mHandler));
-                        // If this is the only one pending we might
-                        // have to bind to the service again.
-                        if (!connectToService()) {
-                            Slog.e(TAG, "Failed to bind to media container service");
-                            params.serviceError();
-                            Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "bindingMCS",
-                                    System.identityHashCode(mHandler));
-                            if (params.traceMethod != null) {
-                                Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, params.traceMethod,
-                                        params.traceCookie);
-                            }
-                            return;
-                        } else {
-                            // Once we bind to the service, the first
-                            // pending request will be processed.
-                            mPendingInstalls.add(idx, params);
-                        }
-                    } else {
-                        mPendingInstalls.add(idx, params);
-                        // Already bound to the service. Just make
-                        // sure we trigger off processing the first request.
-                        if (idx == 0) {
-                            mHandler.sendEmptyMessage(MCS_BOUND);
-                        }
+                    if (params != null) {
+                        if (DEBUG_INSTALL) Slog.i(TAG, "init_copy: " + params);
+                        Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "queueInstall",
+                                System.identityHashCode(params));
+                        Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "startCopy");
+                        params.startCopy();
+                        Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
                     }
                     break;
                 }
-                case MCS_BOUND: {
-                    if (DEBUG_INSTALL) Slog.i(TAG, "mcs_bound");
-                    if (msg.obj != null) {
-                        mContainerService = (IMediaContainerService) msg.obj;
-                        Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "bindingMCS",
-                                System.identityHashCode(mHandler));
-                    }
-                    if (mContainerService == null) {
-                        if (!mBound) {
-                            // Something seriously wrong since we are not bound and we are not
-                            // waiting for connection. Bail out.
-                            Slog.e(TAG, "Cannot bind to media container service");
-                            for (HandlerParams params : mPendingInstalls) {
-                                // Indicate service bind error
-                                params.serviceError();
-                                Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "queueInstall",
-                                        System.identityHashCode(params));
-                                if (params.traceMethod != null) {
-                                    Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER,
-                                            params.traceMethod, params.traceCookie);
-                                }
-                            }
-                            mPendingInstalls.clear();
-                        } else {
-                            Slog.w(TAG, "Waiting to connect to media container service");
-                        }
-                    } else if (mPendingInstalls.size() > 0) {
-                        HandlerParams params = mPendingInstalls.get(0);
-                        if (params != null) {
-                            Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "queueInstall",
-                                    System.identityHashCode(params));
-                            Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "startCopy");
-                            if (params.startCopy()) {
-                                // We are done...  look for more work or to
-                                // go idle.
-                                if (DEBUG_SD_INSTALL) Log.i(TAG,
-                                        "Checking for more work or unbind...");
-                                // Delete pending install
-                                if (mPendingInstalls.size() > 0) {
-                                    mPendingInstalls.remove(0);
-                                }
-                                if (mPendingInstalls.size() == 0) {
-                                    if (mBound) {
-                                        if (DEBUG_SD_INSTALL) Log.i(TAG,
-                                                "Posting delayed MCS_UNBIND");
-                                        removeMessages(MCS_UNBIND);
-                                        Message ubmsg = obtainMessage(MCS_UNBIND);
-                                        // Unbind after a little delay, to avoid
-                                        // continual thrashing.
-                                        sendMessageDelayed(ubmsg, 10000);
-                                    }
-                                } else {
-                                    // There are more pending requests in queue.
-                                    // Just post MCS_BOUND message to trigger processing
-                                    // of next pending install.
-                                    if (DEBUG_SD_INSTALL) Log.i(TAG,
-                                            "Posting MCS_BOUND for next work");
-                                    mHandler.sendEmptyMessage(MCS_BOUND);
-                                }
-                            }
-                            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
-                        }
-                    } else {
-                        // Should never happen ideally.
-                        Slog.w(TAG, "Empty queue");
-                    }
-                    break;
-                }
-                case MCS_RECONNECT: {
-                    if (DEBUG_INSTALL) Slog.i(TAG, "mcs_reconnect");
-                    if (mPendingInstalls.size() > 0) {
-                        if (mBound) {
-                            disconnectService();
-                        }
-                        if (!connectToService()) {
-                            Slog.e(TAG, "Failed to bind to media container service");
-                            for (HandlerParams params : mPendingInstalls) {
-                                // Indicate service bind error
-                                params.serviceError();
-                                Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "queueInstall",
-                                        System.identityHashCode(params));
-                            }
-                            mPendingInstalls.clear();
-                        }
-                    }
-                    break;
-                }
-                case MCS_UNBIND: {
-                    // If there is no actual work left, then time to unbind.
-                    if (DEBUG_INSTALL) Slog.i(TAG, "mcs_unbind");
-
-                    if (mPendingInstalls.size() == 0 && mPendingVerification.size() == 0) {
-                        if (mBound) {
-                            if (DEBUG_INSTALL) Slog.i(TAG, "calling disconnectService()");
-
-                            disconnectService();
-                        }
-                    } else if (mPendingInstalls.size() > 0) {
-                        // There are more pending requests in queue.
-                        // Just post MCS_BOUND message to trigger processing
-                        // of next pending install.
-                        mHandler.sendEmptyMessage(MCS_BOUND);
-                    }
-
-                    break;
-                }
-                case MCS_GIVE_UP: {
-                    if (DEBUG_INSTALL) Slog.i(TAG, "mcs_giveup too many retries");
-                    HandlerParams params = mPendingInstalls.remove(0);
-                    Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "queueInstall",
-                            System.identityHashCode(params));
-                    break;
-                }
                 case SEND_PENDING_BROADCAST: {
                     String packages[];
                     ArrayList<String> components[];
@@ -1685,11 +1473,7 @@
                                     PackageManager.VERIFICATION_ALLOW_WITHOUT_SUFFICIENT);
                             broadcastPackageVerified(verificationId, originUri,
                                     PackageManager.VERIFICATION_ALLOW, user);
-                            try {
-                                ret = args.copyApk(mContainerService, true);
-                            } catch (RemoteException e) {
-                                Slog.e(TAG, "Could not contact the ContainerService");
-                            }
+                            ret = args.copyApk();
                         } else {
                             broadcastPackageVerified(verificationId, originUri,
                                     PackageManager.VERIFICATION_REJECT, user);
@@ -1699,7 +1483,6 @@
                                 TRACE_TAG_PACKAGE_MANAGER, "verification", verificationId);
 
                         processPendingInstall(args, ret);
-                        mHandler.sendEmptyMessage(MCS_UNBIND);
                     }
                     break;
                 }
@@ -1724,14 +1507,9 @@
 
                         int ret;
                         if (state.isInstallAllowed()) {
-                            ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
                             broadcastPackageVerified(verificationId, originUri,
                                     response.code, state.getInstallArgs().getUser());
-                            try {
-                                ret = args.copyApk(mContainerService, true);
-                            } catch (RemoteException e) {
-                                Slog.e(TAG, "Could not contact the ContainerService");
-                            }
+                            ret = args.copyApk();
                         } else {
                             ret = PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE;
                         }
@@ -1740,7 +1518,6 @@
                                 TRACE_TAG_PACKAGE_MANAGER, "verification", verificationId);
 
                         processPendingInstall(args, ret);
-                        mHandler.sendEmptyMessage(MCS_UNBIND);
                     }
 
                     break;
@@ -1988,6 +1765,14 @@
                             mRequiredVerifierPackage, null /*finishedReceiver*/,
                             updateUserIds, instantUserIds);
                 }
+                // If package installer is defined, notify package installer about new
+                // app installed
+                if (mRequiredInstallerPackage != null) {
+                    sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
+                            extras, Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND /*flags*/,
+                            mRequiredInstallerPackage, null /*finishedReceiver*/,
+                            firstUserIds, instantUserIds);
+                }
 
                 // Send replaced for users that don't see the package for the first time
                 if (update) {
@@ -8571,7 +8356,7 @@
      *  Traces a package scan.
      *  @see #scanPackageLI(File, int, int, long, UserHandle)
      */
-    @GuardedBy("mInstallLock")
+    @GuardedBy({"mInstallLock", "mPackages"})
     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() + "]");
@@ -8960,15 +8745,15 @@
     }
 
     /**
-     * Enforces that only the system UID or shell's UID can call a method exposed
-     * via Binder.
+     * Enforces that only the system UID or root's 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) {
+    private static void enforceSystemOrRootOrShell(String message) {
         final int uid = Binder.getCallingUid();
-        if (uid != Process.SYSTEM_UID && uid != Process.SHELL_UID) {
+        if (uid != Process.SYSTEM_UID && uid != Process.ROOT_UID && uid != Process.SHELL_UID) {
             throw new SecurityException(message);
         }
     }
@@ -9454,7 +9239,7 @@
         if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
             return false;
         }
-        enforceSystemOrShell("runBackgroundDexoptJob");
+        enforceSystemOrRootOrShell("runBackgroundDexoptJob");
         final long identity = Binder.clearCallingIdentity();
         try {
             return BackgroundDexOptService.runIdleOptimizationsNow(this, mContext, packageNames);
@@ -12422,14 +12207,6 @@
         return installReason;
     }
 
-    /**
-     * Attempts to bind to the default container service explicitly instead of doing so lazily on
-     * install commit.
-     */
-    void earlyBindToDefContainer() {
-        mHandler.sendMessage(mHandler.obtainMessage(DEF_CONTAINER_BIND));
-    }
-
     void installStage(String packageName, File stagedDir,
             IPackageInstallObserver2 observer, PackageInstaller.SessionParams sessionParams,
             String installerPackageName, int installerUid, UserHandle user,
@@ -13776,14 +13553,6 @@
     }
 
     private abstract class HandlerParams {
-        private static final int MAX_RETRIES = 4;
-
-        /**
-         * Number of times startCopy() has been attempted and had a non-fatal
-         * error.
-         */
-        private int mRetries = 0;
-
         /** User handle for the user requesting the information or installation. */
         private final UserHandle mUser;
         String traceMethod;
@@ -13807,37 +13576,13 @@
             return this;
         }
 
-        final boolean startCopy() {
-            boolean res;
-            try {
-                if (DEBUG_INSTALL) Slog.i(TAG, "startCopy " + mUser + ": " + this);
-
-                if (++mRetries > MAX_RETRIES) {
-                    Slog.w(TAG, "Failed to invoke remote methods on default container service. Giving up");
-                    mHandler.sendEmptyMessage(MCS_GIVE_UP);
-                    handleServiceError();
-                    return false;
-                } else {
-                    handleStartCopy();
-                    res = true;
-                }
-            } catch (RemoteException e) {
-                if (DEBUG_INSTALL) Slog.i(TAG, "Posting install MCS_RECONNECT");
-                mHandler.sendEmptyMessage(MCS_RECONNECT);
-                res = false;
-            }
-            handleReturnCode();
-            return res;
-        }
-
-        final void serviceError() {
-            if (DEBUG_INSTALL) Slog.i(TAG, "serviceError");
-            handleServiceError();
+        final void startCopy() {
+            if (DEBUG_INSTALL) Slog.i(TAG, "startCopy " + mUser + ": " + this);
+            handleStartCopy();
             handleReturnCode();
         }
 
-        abstract void handleStartCopy() throws RemoteException;
-        abstract void handleServiceError();
+        abstract void handleStartCopy();
         abstract void handleReturnCode();
     }
 
@@ -14080,7 +13825,7 @@
          * policy if needed and then create install arguments based
          * on the install location.
          */
-        public void handleStartCopy() throws RemoteException {
+        public void handleStartCopy() {
             int ret = PackageManager.INSTALL_SUCCEEDED;
 
             // If we're already staged, we've firmly committed to an install location
@@ -14106,8 +13851,8 @@
                 Slog.w(TAG,  "Conflicting flags specified for installing ephemeral on external");
                 ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
             } else {
-                pkgLite = mContainerService.getMinimalPackageInfo(origin.resolvedPath, installFlags,
-                        packageAbiOverride);
+                pkgLite = PackageManagerServiceUtils.getMinimalPackageInfo(mContext,
+                        origin.resolvedPath, installFlags, packageAbiOverride);
 
                 if (DEBUG_INSTANT && ephemeral) {
                     Slog.v(TAG, "pkgLite for install: " + pkgLite);
@@ -14124,15 +13869,16 @@
                     final long lowThreshold = storage.getStorageLowBytes(
                             Environment.getDataDirectory());
 
-                    final long sizeBytes = mContainerService.calculateInstalledSize(
+                    final long sizeBytes = PackageManagerServiceUtils.calculateInstalledSize(
                             origin.resolvedPath, packageAbiOverride);
-
-                    try {
-                        mInstaller.freeCache(null, sizeBytes + lowThreshold, 0, 0);
-                        pkgLite = mContainerService.getMinimalPackageInfo(origin.resolvedPath,
-                                installFlags, packageAbiOverride);
-                    } catch (InstallerException e) {
-                        Slog.w(TAG, "Failed to free cache", e);
+                    if (sizeBytes >= 0) {
+                        try {
+                            mInstaller.freeCache(null, sizeBytes + lowThreshold, 0, 0);
+                            pkgLite = PackageManagerServiceUtils.getMinimalPackageInfo(mContext,
+                                    origin.resolvedPath, installFlags, packageAbiOverride);
+                        } catch (InstallerException e) {
+                            Slog.w(TAG, "Failed to free cache", e);
+                        }
                     }
 
                     /*
@@ -14343,7 +14089,7 @@
                      * No package verification is enabled, so immediately start
                      * the remote call to initiate copy using temporary file.
                      */
-                    ret = args.copyApk(mContainerService, true);
+                    ret = args.copyApk();
                 }
             }
 
@@ -14352,19 +14098,10 @@
 
         @Override
         void handleReturnCode() {
-            // If mArgs is null, then MCS couldn't be reached. When it
-            // reconnects, it will try again to install. At that point, this
-            // will succeed.
             if (mArgs != null) {
                 processPendingInstall(mArgs, mRet);
             }
         }
-
-        @Override
-        void handleServiceError() {
-            mArgs = createInstallArgs(this);
-            mRet = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
-        }
     }
 
     private InstallArgs createInstallArgs(InstallParams params) {
@@ -14431,7 +14168,7 @@
             this.installReason = installReason;
         }
 
-        abstract int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException;
+        abstract int copyApk();
         abstract int doPreInstall(int status);
 
         /**
@@ -14539,16 +14276,16 @@
             this.resourceFile = (resourcePath != null) ? new File(resourcePath) : null;
         }
 
-        int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException {
+        int copyApk() {
             Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "copyApk");
             try {
-                return doCopyApk(imcs, temp);
+                return doCopyApk();
             } finally {
                 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
             }
         }
 
-        private int doCopyApk(IMediaContainerService imcs, boolean temp) throws RemoteException {
+        private int doCopyApk() {
             if (origin.staged) {
                 if (DEBUG_INSTALL) Slog.d(TAG, origin.file + " already staged; skipping copy");
                 codeFile = origin.file;
@@ -14567,25 +14304,8 @@
                 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
             }
 
-            final IParcelFileDescriptorFactory target = new IParcelFileDescriptorFactory.Stub() {
-                @Override
-                public ParcelFileDescriptor open(String name, int mode) throws RemoteException {
-                    if (!FileUtils.isValidExtFilename(name)) {
-                        throw new IllegalArgumentException("Invalid filename: " + name);
-                    }
-                    try {
-                        final File file = new File(codeFile, name);
-                        final FileDescriptor fd = Os.open(file.getAbsolutePath(),
-                                O_RDWR | O_CREAT, 0644);
-                        Os.chmod(file.getAbsolutePath(), 0644);
-                        return new ParcelFileDescriptor(fd);
-                    } catch (ErrnoException e) {
-                        throw new RemoteException("Failed to open: " + e.getMessage());
-                    }
-                }
-            };
-
-            int ret = imcs.copyPackage(origin.file.getAbsolutePath(), target);
+            int ret = PackageManagerServiceUtils.copyPackage(
+                    origin.file.getAbsolutePath(), codeFile);
             if (ret != PackageManager.INSTALL_SUCCEEDED) {
                 Slog.e(TAG, "Failed to copy package");
                 return ret;
@@ -14746,7 +14466,7 @@
                     params.installReason);
         }
 
-        int copyApk(IMediaContainerService imcs, boolean temp) {
+        int copyApk() {
             if (DEBUG_INSTALL) Slog.d(TAG, "Moving " + move.packageName + " from "
                     + move.fromUuid + " to " + move.toUuid);
             synchronized (mInstaller) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
index 1aea8f0..36948fc 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
@@ -18,23 +18,21 @@
 
 import static android.content.pm.PackageManager.INSTALL_FAILED_SHARED_USER_INCOMPATIBLE;
 import static android.content.pm.PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
+import static android.system.OsConstants.O_CREAT;
+import static android.system.OsConstants.O_RDWR;
+
 import static com.android.server.pm.PackageManagerService.COMPRESSED_EXTENSION;
 import static com.android.server.pm.PackageManagerService.DEBUG_COMPRESSION;
 import static com.android.server.pm.PackageManagerService.DEBUG_DEXOPT;
 import static com.android.server.pm.PackageManagerService.STUB_SUFFIX;
 import static com.android.server.pm.PackageManagerService.TAG;
-import static com.android.server.pm.PackageManagerServiceUtils.logCriticalInfo;
-
-import com.android.internal.content.NativeLibraryHelper;
-import com.android.internal.util.FastPrintWriter;
-import com.android.server.EventLogTags;
-import com.android.server.pm.dex.DexManager;
-import com.android.server.pm.dex.PackageDexUsage;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.AppGlobals;
+import android.content.Context;
 import android.content.Intent;
+import android.content.pm.PackageInfoLite;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageParser;
 import android.content.pm.PackageParser.PackageParserException;
@@ -53,18 +51,24 @@
 import android.system.Os;
 import android.util.ArraySet;
 import android.util.Log;
-import android.util.PackageUtils;
 import android.util.Slog;
 import android.util.proto.ProtoOutputStream;
 
+import com.android.internal.content.NativeLibraryHelper;
+import com.android.internal.content.PackageHelper;
+import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.FastPrintWriter;
+import com.android.server.EventLogTags;
+import com.android.server.pm.dex.DexManager;
+import com.android.server.pm.dex.PackageDexUsage;
+
 import dalvik.system.VMRuntime;
 
 import libcore.io.IoUtils;
-import libcore.io.Libcore;
-import libcore.io.Streams;
 
 import java.io.BufferedReader;
 import java.io.File;
+import java.io.FileDescriptor;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.FileReader;
@@ -73,8 +77,6 @@
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.PrintWriter;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
 import java.security.cert.CertificateEncodingException;
 import java.security.cert.CertificateException;
 import java.text.SimpleDateFormat;
@@ -164,6 +166,13 @@
     public static List<PackageParser.Package> getPackagesForDexopt(
             Collection<PackageParser.Package> packages,
             PackageManagerService packageManagerService) {
+        return getPackagesForDexopt(packages, packageManagerService, DEBUG_DEXOPT);
+    }
+
+    public static List<PackageParser.Package> getPackagesForDexopt(
+            Collection<PackageParser.Package> packages,
+            PackageManagerService packageManagerService,
+            boolean debug) {
         ArrayList<PackageParser.Package> remainingPkgs = new ArrayList<>(packages);
         LinkedList<PackageParser.Package> result = new LinkedList<>();
         ArrayList<PackageParser.Package> sortTemp = new ArrayList<>(remainingPkgs.size());
@@ -189,14 +198,14 @@
         // TODO: add a property to control this?
         Predicate<PackageParser.Package> remainingPredicate;
         if (!remainingPkgs.isEmpty() && packageManagerService.isHistoricalPackageUsageAvailable()) {
-            if (DEBUG_DEXOPT) {
+            if (debug) {
                 Log.i(TAG, "Looking at historical package use");
             }
             // Get the package that was used last.
             PackageParser.Package lastUsed = Collections.max(remainingPkgs, (pkg1, pkg2) ->
                     Long.compare(pkg1.getLatestForegroundPackageUseTimeInMills(),
                             pkg2.getLatestForegroundPackageUseTimeInMills()));
-            if (DEBUG_DEXOPT) {
+            if (debug) {
                 Log.i(TAG, "Taking package " + lastUsed.packageName + " as reference in time use");
             }
             long estimatedPreviousSystemUseTime =
@@ -218,7 +227,7 @@
         applyPackageFilter(remainingPredicate, result, remainingPkgs, sortTemp,
                 packageManagerService);
 
-        if (DEBUG_DEXOPT) {
+        if (debug) {
             Log.i(TAG, "Packages to be dexopted: " + packagesToString(result));
             Log.i(TAG, "Packages skipped from dexopt: " + packagesToString(remainingPkgs));
         }
@@ -703,4 +712,120 @@
         final File[] compressedFiles = getCompressedFiles(codePath);
         return compressedFiles != null && compressedFiles.length > 0;
     }
+
+    /**
+     * Parse given package and return minimal details.
+     */
+    public static PackageInfoLite getMinimalPackageInfo(Context context, String packagePath,
+            int flags, String abiOverride) {
+        final PackageInfoLite ret = new PackageInfoLite();
+        if (packagePath == null) {
+            Slog.i(TAG, "Invalid package file " + packagePath);
+            ret.recommendedInstallLocation = PackageHelper.RECOMMEND_FAILED_INVALID_APK;
+            return ret;
+        }
+
+        final File packageFile = new File(packagePath);
+        final PackageParser.PackageLite pkg;
+        final long sizeBytes;
+        try {
+            pkg = PackageParser.parsePackageLite(packageFile, 0);
+            sizeBytes = PackageHelper.calculateInstalledSize(pkg, abiOverride);
+        } catch (PackageParserException | IOException e) {
+            Slog.w(TAG, "Failed to parse package at " + packagePath + ": " + e);
+
+            if (!packageFile.exists()) {
+                ret.recommendedInstallLocation = PackageHelper.RECOMMEND_FAILED_INVALID_URI;
+            } else {
+                ret.recommendedInstallLocation = PackageHelper.RECOMMEND_FAILED_INVALID_APK;
+            }
+
+            return ret;
+        }
+
+        final int recommendedInstallLocation = PackageHelper.resolveInstallLocation(context,
+                pkg.packageName, pkg.installLocation, sizeBytes, flags);
+
+        ret.packageName = pkg.packageName;
+        ret.splitNames = pkg.splitNames;
+        ret.versionCode = pkg.versionCode;
+        ret.versionCodeMajor = pkg.versionCodeMajor;
+        ret.baseRevisionCode = pkg.baseRevisionCode;
+        ret.splitRevisionCodes = pkg.splitRevisionCodes;
+        ret.installLocation = pkg.installLocation;
+        ret.verifiers = pkg.verifiers;
+        ret.recommendedInstallLocation = recommendedInstallLocation;
+        ret.multiArch = pkg.multiArch;
+
+        return ret;
+    }
+
+    /**
+     * Calculate estimated footprint of given package post-installation.
+     *
+     * @return -1 if there's some error calculating the size, otherwise installed size of the
+     *         package.
+     */
+    public static long calculateInstalledSize(String packagePath, String abiOverride) {
+        final File packageFile = new File(packagePath);
+        final PackageParser.PackageLite pkg;
+        try {
+            pkg = PackageParser.parsePackageLite(packageFile, 0);
+            return PackageHelper.calculateInstalledSize(pkg, abiOverride);
+        } catch (PackageParserException | IOException e) {
+            Slog.w(TAG, "Failed to calculate installed size: " + e);
+            return -1;
+        }
+    }
+
+    /**
+     * Copy package to the target location.
+     *
+     * @param packagePath absolute path to the package to be copied. Can be
+     *                    a single monolithic APK file or a cluster directory
+     *                    containing one or more APKs.
+     * @return returns status code according to those in
+     *         {@link PackageManager}
+     */
+    public static int copyPackage(String packagePath, File targetDir) {
+        if (packagePath == null) {
+            return PackageManager.INSTALL_FAILED_INVALID_URI;
+        }
+
+        try {
+            final File packageFile = new File(packagePath);
+            final PackageParser.PackageLite pkg = PackageParser.parsePackageLite(packageFile, 0);
+            copyFile(pkg.baseCodePath, targetDir, "base.apk");
+            if (!ArrayUtils.isEmpty(pkg.splitNames)) {
+                for (int i = 0; i < pkg.splitNames.length; i++) {
+                    copyFile(pkg.splitCodePaths[i], targetDir,
+                            "split_" + pkg.splitNames[i] + ".apk");
+                }
+            }
+            return PackageManager.INSTALL_SUCCEEDED;
+        } catch (PackageParserException | IOException | ErrnoException e) {
+            Slog.w(TAG, "Failed to copy package at " + packagePath + ": " + e);
+            return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
+        }
+    }
+
+    private static void copyFile(String sourcePath, File targetDir, String targetName)
+            throws ErrnoException, IOException {
+        if (!FileUtils.isValidExtFilename(targetName)) {
+            throw new IllegalArgumentException("Invalid filename: " + targetName);
+        }
+        Slog.d(TAG, "Copying " + sourcePath + " to " + targetName);
+
+        final File targetFile = new File(targetDir, targetName);
+        final FileDescriptor targetFd = Os.open(targetFile.getAbsolutePath(),
+                O_RDWR | O_CREAT, 0644);
+        Os.chmod(targetFile.getAbsolutePath(), 0644);
+        FileInputStream source = null;
+        try {
+            source = new FileInputStream(sourcePath);
+            FileUtils.copy(source.getFD(), targetFd);
+        } finally {
+            IoUtils.closeQuietly(source);
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index f2c0395..361416a 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -1302,6 +1302,7 @@
         }
         boolean result = mInterface.runBackgroundDexoptJob(packageNames.isEmpty() ? null :
                 packageNames);
+        getOutPrintWriter().println(result ? "Success" : "Failure");
         return result ? 0 : -1;
     }
 
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 5befc1f..846c7b7 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -63,7 +63,6 @@
 
 import com.android.internal.util.XmlUtils;
 import com.android.server.LocalServices;
-import com.android.server.pm.PackageManagerService;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -455,13 +454,6 @@
             grantRuntimePermissions(storagePackage, STORAGE_PERMISSIONS, true, userId);
         }
 
-        // Container service
-        PackageParser.Package containerPackage = getSystemPackage(
-                PackageManagerService.DEFAULT_CONTAINER_PACKAGE);
-        if (containerPackage != null) {
-            grantRuntimePermissions(containerPackage, STORAGE_PERMISSIONS, true, userId);
-        }
-
         // CertInstaller
         Intent certInstallerIntent = new Intent(Credentials.INSTALL_ACTION);
         PackageParser.Package certInstallerPackage = getDefaultSystemHandlerActivityPackage(
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 3e0429f..350d6b6 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -4732,8 +4732,8 @@
         }
         final WindowManager.LayoutParams attrs = win.getAttrs();
         final boolean isDefaultDisplay = win.isDefaultDisplay();
-        final boolean needsToOffsetInputMethodTarget = isDefaultDisplay &&
-                (win == mLastInputMethodTargetWindow && mLastInputMethodWindow != null);
+        final boolean needsToOffsetInputMethodTarget =
+                (win == mLastInputMethodTargetWindow) && (mLastInputMethodWindow != null);
         if (needsToOffsetInputMethodTarget) {
             if (DEBUG_LAYOUT) Slog.i(TAG, "Offset ime target window by the last ime window state");
             offsetInputMethodWindowLw(mLastInputMethodWindow, displayFrames);
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 91d4717..bdf12ca 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -334,9 +334,6 @@
     // True if boot completed occurred.  We keep the screen on until this happens.
     private boolean mBootCompleted;
 
-    // Runnables that should be triggered on boot completed
-    private Runnable[] mBootCompletedRunnables;
-
     // True if auto-suspend mode is enabled.
     // Refer to autosuspend.h.
     private boolean mHalAutoSuspendModeEnabled;
@@ -732,14 +729,6 @@
                 userActivityNoUpdateLocked(
                         now, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);
                 updatePowerStateLocked();
-
-                if (!ArrayUtils.isEmpty(mBootCompletedRunnables)) {
-                    Slog.d(TAG, "Posting " + mBootCompletedRunnables.length + " delayed runnables");
-                    for (Runnable r : mBootCompletedRunnables) {
-                        BackgroundThread.getHandler().post(r);
-                    }
-                }
-                mBootCompletedRunnables = null;
             }
         }
     }
@@ -954,16 +943,6 @@
         mDirty |= DIRTY_SETTINGS;
     }
 
-    private void postAfterBootCompleted(Runnable r) {
-        if (mBootCompleted) {
-            BackgroundThread.getHandler().post(r);
-        } else {
-            Slog.d(TAG, "Delaying runnable until system is booted");
-            mBootCompletedRunnables = ArrayUtils.appendElement(Runnable.class,
-                    mBootCompletedRunnables, r);
-        }
-    }
-
     private void handleSettingsChangedLocked() {
         updateSettingsLocked();
         updatePowerStateLocked();
diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java
index 556038f..9f09c81 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,9 @@
 import android.os.IBinder;
 import android.os.IStatsCompanionService;
 import android.os.IStatsManager;
+import android.os.IStoraged;
+import android.os.IThermalEventListener;
+import android.os.IThermalService;
 import android.os.Parcelable;
 import android.os.Process;
 import android.os.RemoteException;
@@ -53,8 +55,10 @@
 import android.os.StatsLogEventWrapper;
 import android.os.SynchronousResultReceiver;
 import android.os.SystemClock;
+import android.os.Temperature;
 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;
@@ -65,20 +69,30 @@
 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.LooperStats;
 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;
@@ -158,6 +172,8 @@
     private KernelUidCpuClusterTimeReader mKernelUidCpuClusterTimeReader =
             new KernelUidCpuClusterTimeReader();
 
+    private static IThermalService sThermalService;
+
     public StatsCompanionService(Context context) {
         super();
         mContext = context;
@@ -202,6 +218,24 @@
         long[] freqs = mKernelUidCpuFreqTimeReader.readFreqs(powerProfile);
         mKernelUidCpuClusterTimeReader.setThrottleInterval(0);
         mKernelUidCpuActiveTimeReader.setThrottleInterval(0);
+
+        // Enable push notifications of throttling from vendor thermal
+        // management subsystem via thermalservice.
+        IBinder b = ServiceManager.getService("thermalservice");
+
+        if (b != null) {
+            sThermalService = IThermalService.Stub.asInterface(b);
+            try {
+                sThermalService.registerThermalEventListener(
+                        new ThermalEventListener());
+                Slog.i(TAG, "register thermal listener successfully");
+            } catch (RemoteException e) {
+                // Should never happen.
+                Slog.e(TAG, "register thermal listener error");
+            }
+        } else {
+            Slog.e(TAG, "cannot find thermalservice, no throttling push notifications");
+        }
     }
 
     @Override
@@ -328,7 +362,6 @@
                             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();
@@ -337,7 +370,6 @@
                         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);
@@ -864,14 +896,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());
@@ -942,6 +966,206 @@
         }
     }
 
+    private void pullLooperStats(int tagId, List<StatsLogEventWrapper> pulledData) {
+        LooperStats looperStats = LocalServices.getService(LooperStats.class);
+        if (looperStats == null) {
+            return;
+        }
+
+        List<LooperStats.ExportedEntry> entries = looperStats.getEntries();
+        long elapsedNanos = SystemClock.elapsedRealtimeNanos();
+        for (LooperStats.ExportedEntry entry : entries) {
+            StatsLogEventWrapper e = new StatsLogEventWrapper(elapsedNanos, tagId, 9 /* fields */);
+            e.writeLong(0); // uid collection not implemented yet
+            e.writeString(entry.handlerClassName);
+            e.writeString(entry.threadName);
+            e.writeString(entry.messageName);
+            e.writeLong(entry.messageCount);
+            e.writeLong(entry.exceptionCount);
+            e.writeLong(entry.recordedMessageCount);
+            e.writeLong(entry.totalLatencyMicros);
+            e.writeLong(entry.cpuUsageMicros);
+            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.
      */
@@ -1016,10 +1240,6 @@
                 pullSystemElapsedRealtime(tagId, ret);
                 break;
             }
-            case StatsLog.DISK_SPACE: {
-                pullDiskSpace(tagId, ret);
-                break;
-            }
             case StatsLog.PROCESS_MEMORY_STATE: {
                 pullProcessMemoryState(tagId, ret);
                 break;
@@ -1032,6 +1252,26 @@
                 pullBinderCallsStatsExceptions(tagId, ret);
                 break;
             }
+            case StatsLog.LOOPER_STATS: {
+                pullLooperStats(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;
@@ -1239,4 +1479,11 @@
         }
     }
 
+    // Thermal event received from vendor thermal management subsystem
+    private static final class ThermalEventListener extends IThermalEventListener.Stub {
+        @Override public void notifyThrottling(boolean isThrottling, Temperature temp) {
+            StatsLog.write(StatsLog.THERMAL_THROTTLING, temp.getType(),
+                    isThrottling ? 1 : 0, temp.getValue());
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index b8c9be7..c2d8188 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -565,10 +565,11 @@
     }
 
     @Override
-    public void showBiometricDialog(Bundle bundle, IBiometricPromptReceiver receiver) {
+    public void showBiometricDialog(Bundle bundle, IBiometricPromptReceiver receiver, int type) {
+        enforceBiometricDialog();
         if (mBar != null) {
             try {
-                mBar.showBiometricDialog(bundle, receiver);
+                mBar.showBiometricDialog(bundle, receiver, type);
             } catch (RemoteException ex) {
             }
         }
@@ -576,6 +577,7 @@
 
     @Override
     public void onBiometricAuthenticated() {
+        enforceBiometricDialog();
         if (mBar != null) {
             try {
                 mBar.onBiometricAuthenticated();
@@ -586,6 +588,7 @@
 
     @Override
     public void onBiometricHelp(String message) {
+        enforceBiometricDialog();
         if (mBar != null) {
             try {
                 mBar.onBiometricHelp(message);
@@ -596,6 +599,7 @@
 
     @Override
     public void onBiometricError(String error) {
+        enforceBiometricDialog();
         if (mBar != null) {
             try {
                 mBar.onBiometricError(error);
@@ -606,6 +610,7 @@
 
     @Override
     public void hideBiometricDialog() {
+        enforceBiometricDialog();
         if (mBar != null) {
             try {
                 mBar.hideBiometricDialog();
@@ -866,6 +871,12 @@
                 "StatusBarManagerService");
     }
 
+    private void enforceBiometricDialog() {
+        mContext.enforceCallingOrSelfPermission(
+                android.Manifest.permission.MANAGE_BIOMETRIC_DIALOG,
+                "StatusBarManagerService");
+    }
+
     // ================================================================================
     // Callbacks from the status bar service.
     // ================================================================================
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index c8bd211..479f427 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -55,7 +55,6 @@
 import android.graphics.BitmapFactory;
 import android.graphics.BitmapRegionDecoder;
 import android.graphics.Color;
-import android.graphics.Point;
 import android.graphics.Rect;
 import android.os.Binder;
 import android.os.Bundle;
@@ -99,7 +98,6 @@
 import com.android.server.FgThread;
 import com.android.server.SystemService;
 
-import java.lang.reflect.InvocationTargetException;
 import libcore.io.IoUtils;
 
 import org.xmlpull.v1.XmlPullParser;
@@ -120,7 +118,6 @@
 import java.util.Arrays;
 import java.util.List;
 import java.util.Objects;
-import com.android.internal.R;
 
 public class WallpaperManagerService extends IWallpaperManager.Stub
         implements IWallpaperManagerService {
@@ -1544,14 +1541,6 @@
         return false;
     }
 
-    private Point getDefaultDisplaySize() {
-        Point p = new Point();
-        WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
-        Display d = wm.getDefaultDisplay();
-        d.getRealSize(p);
-        return p;
-    }
-
     public void setDimensionHints(int width, int height, String callingPackage)
             throws RemoteException {
         checkPermission(android.Manifest.permission.SET_WALLPAPER_HINTS);
@@ -1564,10 +1553,6 @@
             if (width <= 0 || height <= 0) {
                 throw new IllegalArgumentException("width and height must be > 0");
             }
-            // Make sure it is at least as large as the display.
-            Point displaySize = getDefaultDisplaySize();
-            width = Math.max(width, displaySize.x);
-            height = Math.max(height, displaySize.y);
 
             if (width != wallpaper.width || height != wallpaper.height) {
                 wallpaper.width = width;
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index b775918..6da9f10 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -32,29 +32,11 @@
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
-
+import static android.view.WindowManager.TRANSIT_UNSET;
 import static android.view.WindowManager.TRANSIT_WALLPAPER_OPEN;
+
 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
-import static android.view.WindowManager.TRANSIT_UNSET;
-
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
-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_STARTING_WINDOW;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW_VERBOSE;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TOKEN_MOVEMENT;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT;
-import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
-import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
-import static com.android.server.wm.WindowManagerService.H.NOTIFY_ACTIVITY_DRAWN;
-import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
-import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
-import static com.android.server.wm.WindowManagerService.logWithStack;
 import static com.android.server.wm.AppWindowTokenProto.ALL_DRAWN;
 import static com.android.server.wm.AppWindowTokenProto.APP_STOPPED;
 import static com.android.server.wm.AppWindowTokenProto.CLIENT_HIDDEN;
@@ -78,6 +60,23 @@
 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.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
+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_STARTING_WINDOW;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW_VERBOSE;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TOKEN_MOVEMENT;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+import static com.android.server.wm.WindowManagerService.H.NOTIFY_ACTIVITY_DRAWN;
+import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
+import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
+import static com.android.server.wm.WindowManagerService.logWithStack;
 import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_AFTER_ANIM;
 
 import android.annotation.CallSuper;
@@ -1845,8 +1844,8 @@
             surfaceInsets = win.getAttrs().surfaceInsets;
             // XXX(b/72757033): These are insets relative to the window frame, but we're really
             // interested in the insets relative to the frame we chose in the if-blocks above.
-            insets.set(win.mContentInsets);
-            stableInsets.set(win.mStableInsets);
+            win.getContentInsets(insets);
+            win.getStableInsets(stableInsets);
         }
 
         if (mLaunchTaskBehind) {
@@ -2099,7 +2098,7 @@
         WindowState win = findMainWindow();
         Rect appRect = win != null ? win.getContentFrameLw() :
                 new Rect(0, 0, displayInfo.appWidth, displayInfo.appHeight);
-        Rect insets = win != null ? win.mContentInsets : null;
+        final Rect insets = win != null ? win.getContentInsets() : null;
         final Configuration displayConfig = mDisplayContent.getConfiguration();
         return mService.mAppTransition.createThumbnailAspectScaleAnimationLocked(
                 appRect, insets, thumbnailHeader, getTask().mTaskId, displayConfig.uiMode,
diff --git a/services/core/java/com/android/server/wm/BoundsAnimationController.java b/services/core/java/com/android/server/wm/BoundsAnimationController.java
index a693071..731ebb8a 100644
--- a/services/core/java/com/android/server/wm/BoundsAnimationController.java
+++ b/services/core/java/com/android/server/wm/BoundsAnimationController.java
@@ -26,9 +26,9 @@
 import android.annotation.IntDef;
 import android.content.Context;
 import android.graphics.Rect;
+import android.os.Debug;
 import android.os.Handler;
 import android.os.IBinder;
-import android.os.Debug;
 import android.util.ArrayMap;
 import android.util.Slog;
 import android.view.Choreographer;
@@ -36,8 +36,8 @@
 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;
 
@@ -178,7 +178,7 @@
         BoundsAnimator(BoundsAnimationTarget target, Rect from, Rect to,
                 @SchedulePipModeChangedState int schedulePipModeChangedState,
                 @SchedulePipModeChangedState int prevShedulePipModeChangedState,
-                boolean moveFromFullscreen, boolean moveToFullscreen) {
+                boolean moveFromFullscreen, boolean moveToFullscreen, Rect frozenTask) {
             super();
             mTarget = target;
             mFrom.set(from);
@@ -198,8 +198,8 @@
                 mFrozenTaskWidth = mTo.width();
                 mFrozenTaskHeight = mTo.height();
             } else {
-                mFrozenTaskWidth = mFrom.width();
-                mFrozenTaskHeight = mFrom.height();
+                mFrozenTaskWidth = frozenTask.isEmpty() ? mFrom.width() : frozenTask.width();
+                mFrozenTaskHeight = frozenTask.isEmpty() ? mFrom.height() : frozenTask.height();
             }
         }
 
@@ -425,6 +425,7 @@
                 + " schedulePipModeChangedState=" + schedulePipModeChangedState
                 + " replacing=" + replacing);
 
+        Rect frozenTask = new Rect();
         if (replacing) {
             if (existing.isAnimatingTo(to) && (!moveToFullscreen || existing.mMoveToFullscreen)
                     && (!moveFromFullscreen || existing.mMoveFromFullscreen)) {
@@ -467,12 +468,17 @@
                 moveFromFullscreen = existing.mMoveFromFullscreen;
             }
 
+            // We are in the middle of an existing animation, so that this new animation may
+            // start from an interpolated bounds. We should keep using the existing frozen task
+            // width/height for consistent configurations.
+            frozenTask.set(0, 0, existing.mFrozenTaskWidth, existing.mFrozenTaskHeight);
+
             // Since we are replacing, we skip both animation start and end callbacks
             existing.cancel();
         }
         final BoundsAnimator animator = new BoundsAnimator(target, from, to,
                 schedulePipModeChangedState, prevSchedulePipModeChangedState,
-                moveFromFullscreen, moveToFullscreen);
+                moveFromFullscreen, moveToFullscreen, frozenTask);
         mRunningAnimations.put(target, animator);
         animator.setFloatValues(0f, 1f);
         animator.setDuration((animationDuration != -1 ? animationDuration
diff --git a/services/core/java/com/android/server/wm/ConfigurationContainer.java b/services/core/java/com/android/server/wm/ConfigurationContainer.java
index f2ce63c..64553a8 100644
--- a/services/core/java/com/android/server/wm/ConfigurationContainer.java
+++ b/services/core/java/com/android/server/wm/ConfigurationContainer.java
@@ -29,6 +29,7 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
 import static android.app.WindowConfiguration.activityTypeToString;
 import static android.app.WindowConfiguration.windowingModeToString;
+
 import static com.android.server.wm.ConfigurationContainerProto.FULL_CONFIGURATION;
 import static com.android.server.wm.ConfigurationContainerProto.MERGED_OVERRIDE_CONFIGURATION;
 import static com.android.server.wm.ConfigurationContainerProto.OVERRIDE_CONFIGURATION;
@@ -295,6 +296,10 @@
         return mFullConfiguration.windowConfiguration.getWindowingMode();
     }
 
+    public int getOverrideWindowingMode() {
+        return mOverrideConfiguration.windowConfiguration.getWindowingMode();
+    }
+
     /** Sets the windowing mode for the configuration container. */
     public void setWindowingMode(/*@WindowConfiguration.WindowingMode*/ int windowingMode) {
         mTmpConfig.setTo(getOverrideConfiguration());
@@ -513,7 +518,8 @@
         final String childPrefix = prefix + " ";
         pw.println(getName()
                 + " type=" + activityTypeToString(getActivityType())
-                + " mode=" + windowingModeToString(getWindowingMode()));
+                + " mode=" + windowingModeToString(getWindowingMode())
+                + " override-mode=" + windowingModeToString(getOverrideWindowingMode()));
         for (int i = getChildCount() - 1; i >= 0; --i) {
             final E cc = getChildAt(i);
             pw.print(childPrefix + "#" + i + " ");
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index ba46737..ac65826 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -409,6 +409,11 @@
 
     private InputMonitor mInputMonitor;
 
+    /**
+     * The input method window for this display.
+     */
+    WindowState mInputMethodWindow;
+
     private final Consumer<WindowState> mUpdateWindowsForAnimator = w -> {
         WindowStateAnimator winAnimator = w.mWinAnimator;
         final AppWindowToken atoken = w.mAppToken;
@@ -814,9 +819,7 @@
         // {@link DisplayContent} ready for use.
         mDisplayReady = true;
 
-        // TODO(b/112081256): Use independent InputMonitor.
-        mInputMonitor = isDefaultDisplay ? new InputMonitor(service, mDisplayId)
-                : mService.getDefaultDisplayContentLocked().mInputMonitor;
+        mInputMonitor = new InputMonitor(service, mDisplayId);
     }
 
     boolean isReady() {
@@ -921,6 +924,11 @@
     }
 
     @Override
+    DisplayWindowController getController() {
+        return (DisplayWindowController) super.getController();
+    }
+
+    @Override
     public Display getDisplay() {
         return mDisplay;
     }
@@ -1421,7 +1429,7 @@
         config.densityDpi = displayInfo.logicalDensityDpi;
 
         config.colorMode =
-                (displayInfo.isHdr()
+                ((displayInfo.isHdr() && mService.hasHdrSupport())
                         ? Configuration.COLOR_MODE_HDR_YES
                         : Configuration.COLOR_MODE_HDR_NO)
                         | (displayInfo.isWideColorGamut() && mService.hasWideColorGamutSupport()
@@ -2104,18 +2112,16 @@
                 mTouchExcludeRegion.op(mTmpRect2, Region.Op.UNION);
             }
         }
-        final WindowState inputMethod = mService.mInputMethodWindow;
-        if (inputMethod != null && inputMethod.isVisibleLw()) {
+        if (mInputMethodWindow != null && mInputMethodWindow.isVisibleLw()) {
             // If the input method is visible and the user is typing, we don't want these touch
             // events to be intercepted and used to change focus. This would likely cause a
             // disappearance of the input method.
-            inputMethod.getTouchableRegion(mTmpRegion);
-            if (inputMethod.getDisplayId() == mDisplayId) {
+            mInputMethodWindow.getTouchableRegion(mTmpRegion);
+            if (mInputMethodWindow.getDisplayId() == mDisplayId) {
                 mTouchExcludeRegion.op(mTmpRegion, Op.UNION);
             } else {
                 // IME is on a different display, so we need to update its tap detector.
-                // TODO(multidisplay): Remove when IME will always appear on same display.
-                inputMethod.getDisplayContent().setTouchExcludeRegion(null /* focusedTask */);
+                setTouchExcludeRegion(null /* focusedTask */);
             }
         }
         for (int i = mTapExcludedWindows.size() - 1; i >= 0; i--) {
@@ -2180,6 +2186,7 @@
             mRemovingDisplay = false;
         }
 
+        mInputMonitor.onRemoved();
         mService.onDisplayRemoved(mDisplayId);
     }
 
@@ -2253,7 +2260,7 @@
     }
 
     void adjustForImeIfNeeded() {
-        final WindowState imeWin = mService.mInputMethodWindow;
+        final WindowState imeWin = mInputMethodWindow;
         final boolean imeVisible = imeWin != null && imeWin.isVisibleLw() && imeWin.isDisplayedLw()
                 && !mDividerControllerLocked.isImeHideRequested();
         final boolean dockVisible = isStackVisible(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
@@ -2636,12 +2643,21 @@
     }
 
     /**
+     * Set input method window for the display.
+     * @param win Set when window added or Null when destroyed.
+     */
+    void setInputMethodWindowLocked(WindowState win) {
+        mInputMethodWindow = win;
+        computeImeTarget(true /* updateImeTarget */);
+    }
+
+    /**
      * Determine and return the window that should be the IME target.
      * @param updateImeTarget If true the system IME target will be updated to match what we found.
      * @return The window that should be used as the IME target or null if there isn't any.
      */
     WindowState computeImeTarget(boolean updateImeTarget) {
-        if (mService.mInputMethodWindow == null) {
+        if (mInputMethodWindow == null) {
             // There isn't an IME so there shouldn't be a target...That was easy!
             if (updateImeTarget) {
                 if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from "
@@ -3004,7 +3020,7 @@
             if (w.isVisibleLw() && (w.mAppToken != null || keyguard)) {
                 w.mWinAnimator.mDrawState = DRAW_PENDING;
                 // Force add to mResizingWindows.
-                w.mLastContentInsets.set(-1, -1, -1, -1);
+                w.resetLastContentInsets();
                 mService.mWaitingForDrawn.add(w);
             }
         }, true /* traverseTopToBottom */);
@@ -3590,6 +3606,18 @@
             final int targetPosition = findPositionForStack(position, child, false /* adding */);
             super.positionChildAt(targetPosition, child, includingParents);
 
+            if (includingParents) {
+                // We still want to move the display of this stack container to top because even the
+                // target position is adjusted to non-top, the intention of the condition is to have
+                // higher z-order to gain focus (e.g. moving a task of a fullscreen stack to front
+                // in a non-top display which is using picture-in-picture mode).
+                final int topChildPosition = getChildCount() - 1;
+                if (targetPosition < topChildPosition && position >= topChildPosition) {
+                    getParent().positionChildAt(POSITION_TOP, this /* child */,
+                            true /* includingParents */);
+                }
+            }
+
             setLayoutNeeded();
         }
 
diff --git a/services/core/java/com/android/server/wm/DisplayWindowController.java b/services/core/java/com/android/server/wm/DisplayWindowController.java
index 74a8a35..76b6dbe 100644
--- a/services/core/java/com/android/server/wm/DisplayWindowController.java
+++ b/services/core/java/com/android/server/wm/DisplayWindowController.java
@@ -73,6 +73,10 @@
         // override configuration propagation to just here.
     }
 
+    public int getDisplayId() {
+        return mDisplayId;
+    }
+
     /**
      * Positions the task stack at the given position in the task stack container.
      */
diff --git a/services/core/java/com/android/server/wm/InputConsumerImpl.java b/services/core/java/com/android/server/wm/InputConsumerImpl.java
index 6a08f4d..585a4f5 100644
--- a/services/core/java/com/android/server/wm/InputConsumerImpl.java
+++ b/services/core/java/com/android/server/wm/InputConsumerImpl.java
@@ -20,9 +20,9 @@
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.UserHandle;
-import android.view.Display;
 import android.view.InputChannel;
 import android.view.WindowManager;
+
 import com.android.server.input.InputApplicationHandle;
 import com.android.server.input.InputWindowHandle;
 
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index c4beb55..ef3a770 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -268,11 +268,11 @@
             }
             final InputWindowHandle dragWindowHandle =
                     mService.mDragDropController.getInputWindowHandleLocked();
-            if (dragWindowHandle != null) {
-                addInputWindowHandle(dragWindowHandle);
-            } else {
+            if (dragWindowHandle == null) {
                 Slog.w(TAG_WM, "Drag is in progress but there is no "
                         + "drag window handle.");
+            } else if (dragWindowHandle.displayId == mDisplayId) {
+                addInputWindowHandle(dragWindowHandle);
             }
         }
 
@@ -283,11 +283,11 @@
             }
             final InputWindowHandle dragWindowHandle =
                     mService.mTaskPositioningController.getDragWindowHandleLocked();
-            if (dragWindowHandle != null) {
-                addInputWindowHandle(dragWindowHandle);
-            } else {
+            if (dragWindowHandle == null) {
                 Slog.e(TAG_WM,
                         "Repositioning is in progress but there is no drag window handle.");
+            } else if (dragWindowHandle.displayId == mDisplayId) {
+                addInputWindowHandle(dragWindowHandle);
             }
         }
 
@@ -367,6 +367,13 @@
         }
     }
 
+    void onRemoved() {
+        // If DisplayContent removed, we need find a way to remove window handles of this display
+        // from InputDispatcher, so pass an empty InputWindowHandles to remove them.
+        mService.mInputManager.setInputWindows(mInputWindowHandles, mFocusedInputWindowHandle,
+                mDisplayId);
+    }
+
     private final class UpdateInputForAllWindowsConsumer implements Consumer<WindowState> {
         InputConsumerImpl navInputConsumer;
         InputConsumerImpl pipInputConsumer;
@@ -399,8 +406,7 @@
             this.inDrag = inDrag;
             wallpaperController = mService.mRoot.mWallpaperController;
 
-            // TODO(b/112081256): Use independent InputMonitor for each display.
-            mService.mRoot/*.getDisplayContent(mDisplayId)*/.forAllWindows(this,
+            mService.mRoot.getDisplayContent(mDisplayId).forAllWindows(this,
                     true /* traverseTopToBottom */);
             if (mAddWallpaperInputConsumerHandle) {
                 // No visible wallpaper found, add the wallpaper input consumer at the end.
@@ -408,8 +414,8 @@
             }
 
             // Send windows to native code.
-            // TODO: Update Input windows and focus by display?
-            mService.mInputManager.setInputWindows(mInputWindowHandles, mFocusedInputWindowHandle);
+            mService.mInputManager.setInputWindows(mInputWindowHandles, mFocusedInputWindowHandle,
+                    mDisplayId);
 
             clearInputWindowHandlesLw();
 
@@ -429,7 +435,8 @@
             final int flags = w.mAttrs.flags;
             final int privateFlags = w.mAttrs.privateFlags;
             final int type = w.mAttrs.type;
-            final boolean hasFocus = w == mInputFocus;
+            // TODO(b/111361570): multi-display focus, one focus window per display.
+            final boolean hasFocus = w.isFocused();
             final boolean isVisible = w.isVisibleLw();
 
             if (mAddRecentsAnimationInputConsumerHandle) {
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index 03c61f0..1eae567 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -21,6 +21,7 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
 import static android.view.RemoteAnimationTarget.MODE_CLOSING;
 import static android.view.WindowManager.INPUT_CONSUMER_RECENTS_ANIMATION;
+
 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
 import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_RECENTS_ANIM;
 import static com.android.server.wm.AnimationAdapterProto.REMOTE;
@@ -48,8 +49,6 @@
 import android.view.SurfaceControl;
 import android.view.SurfaceControl.Transaction;
 
-import com.google.android.collect.Sets;
-
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.server.LocalServices;
 import com.android.server.input.InputWindowHandle;
@@ -57,6 +56,8 @@
 import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
 import com.android.server.wm.utils.InsetUtils;
 
+import com.google.android.collect.Sets;
+
 import java.io.PrintWriter;
 import java.util.ArrayList;
 
@@ -370,10 +371,14 @@
                     && mTargetAppToken.inSplitScreenSecondaryWindowingMode()
                             ? mMinimizedHomeBounds
                             : null;
-            final Rect contentInsets = mTargetAppToken != null
-                    && mTargetAppToken.findMainWindow() != null
-                            ? mTargetAppToken.findMainWindow().mContentInsets
-                            : null;
+            final Rect contentInsets;
+            if (mTargetAppToken != null && mTargetAppToken.findMainWindow() != null) {
+                contentInsets = mTargetAppToken.findMainWindow().getContentInsets();
+            } else {
+                // If the window for the activity had not yet been created, use the display insets.
+                mService.getStableInsets(mDisplayId, mTmpRect);
+                contentInsets = mTmpRect;
+            }
             mRunner.onAnimationStart(mController, appTargets, contentInsets, minimizedHomeBounds);
             if (DEBUG_RECENTS_ANIMATIONS) {
                 Slog.d(TAG, "startAnimation(): Notify animation start:");
@@ -578,7 +583,8 @@
             if (mainWindow == null) {
                 return null;
             }
-            final Rect insets = new Rect(mainWindow.mContentInsets);
+            final Rect insets = new Rect();
+            mainWindow.getContentInsets(insets);
             InsetUtils.addInsets(insets, mainWindow.mAppToken.getLetterboxInsets());
             mTarget = new RemoteAnimationTarget(mTask.mTaskId, MODE_CLOSING, mCapturedLeash,
                     !topApp.fillsParent(), mainWindow.mWinAnimator.mLastClipRect,
diff --git a/services/core/java/com/android/server/wm/RemoteAnimationController.java b/services/core/java/com/android/server/wm/RemoteAnimationController.java
index 67ef471..00422e3 100644
--- a/services/core/java/com/android/server/wm/RemoteAnimationController.java
+++ b/services/core/java/com/android/server/wm/RemoteAnimationController.java
@@ -305,7 +305,8 @@
                     || mCapturedLeash == null) {
                 return null;
             }
-            final Rect insets = new Rect(mainWindow.mContentInsets);
+            final Rect insets = new Rect();
+            mainWindow.getContentInsets(insets);
             InsetUtils.addInsets(insets, mAppWindowToken.getLetterboxInsets());
             mTarget = new RemoteAnimationTarget(task.mTaskId, getMode(),
                     mCapturedLeash, !mAppWindowToken.fillsParent(),
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index d8cbb26..d92818a 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -174,24 +174,6 @@
         return null;
     }
 
-    /**
-     * Get an array with display ids ordered by focus priority - last items should be given
-     * focus first. Sparse array just maps position to displayId.
-     */
-    void getDisplaysInFocusOrder(SparseIntArray displaysInFocusOrder) {
-        displaysInFocusOrder.clear();
-
-        final int size = mChildren.size();
-        for (int i = 0; i < size; ++i) {
-            final DisplayContent displayContent = mChildren.get(i);
-            if (displayContent.isRemovalDeferred()) {
-                // Don't report displays that are going to be removed soon.
-                continue;
-            }
-            displaysInFocusOrder.put(i, displayContent.getDisplayId());
-        }
-    }
-
     DisplayContent getDisplayContent(int displayId) {
         for (int i = mChildren.size() - 1; i >= 0; --i) {
             final DisplayContent current = mChildren.get(i);
@@ -699,10 +681,11 @@
                 i--;
                 WindowState win = mService.mDestroySurface.get(i);
                 win.mDestroying = false;
-                if (mService.mInputMethodWindow == win) {
-                    mService.setInputMethodWindowLocked(null);
+                final DisplayContent displayContent = win.getDisplayContent();
+                if (displayContent.mInputMethodWindow == win) {
+                    displayContent.setInputMethodWindowLocked(null);
                 }
-                if (win.getDisplayContent().mWallpaperController.isWallpaperTarget(win)) {
+                if (displayContent.mWallpaperController.isWallpaperTarget(win)) {
                     wallpaperDestroyed = true;
                 }
                 win.destroySurfaceUnchecked();
@@ -1098,6 +1081,25 @@
     }
 
     @Override
+    void positionChildAt(int position, DisplayContent child, boolean includingParents) {
+        super.positionChildAt(position, child, includingParents);
+        final RootWindowContainerController controller = getController();
+        if (controller != null) {
+            controller.onChildPositionChanged(child, position);
+        }
+    }
+
+    void positionChildAt(int position, DisplayContent child) {
+        // Only called from controller so no need to notify the change to controller.
+        super.positionChildAt(position, child, false /* includingParents */);
+    }
+
+    @Override
+    RootWindowContainerController getController() {
+        return (RootWindowContainerController) super.getController();
+    }
+
+    @Override
     void scheduleAnimation() {
         mService.scheduleAnimationLocked();
     }
@@ -1112,4 +1114,18 @@
             callback.accept(mChildren.get(i));
         }
     }
+
+    /**
+     * Get current topmost focused IME window in system.
+     * Will look on all displays in current Z-order.
+     */
+    WindowState getCurrentInputMethodWindow() {
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            final DisplayContent displayContent = mChildren.get(i);
+            if (displayContent.mInputMethodWindow != null) {
+                return displayContent.mInputMethodWindow;
+            }
+        }
+        return null;
+    }
 }
diff --git a/services/core/java/com/android/server/wm/RootWindowContainerController.java b/services/core/java/com/android/server/wm/RootWindowContainerController.java
new file mode 100644
index 0000000..93be6e9
--- /dev/null
+++ b/services/core/java/com/android/server/wm/RootWindowContainerController.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.wm;
+
+/**
+ * Controller for the root container. This is created by activity manager to link activity
+ * stack supervisor to the root window container they use in window manager.
+ */
+public class RootWindowContainerController
+        extends WindowContainerController<RootWindowContainer, RootWindowContainerListener> {
+
+    public RootWindowContainerController(RootWindowContainerListener listener) {
+        super(listener, WindowManagerService.getInstance());
+        synchronized (mWindowMap) {
+            mRoot.setController(this);
+        }
+    }
+
+    void onChildPositionChanged(DisplayContent child, int position) {
+        // This callback invokes to AM directly so here assumes AM lock is held. If there is another
+        // path called only with WM lock, it should change to use handler to post or move outside of
+        // WM lock with adding AM lock.
+        mListener.onChildPositionChanged(child.getController(), position);
+    }
+
+    /** Move the display to the given position. */
+    public void positionChildAt(DisplayWindowController child, int position) {
+        synchronized (mWindowMap) {
+            mContainer.positionChildAt(position, child.mContainer);
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/wm/RootWindowContainerListener.java b/services/core/java/com/android/server/wm/RootWindowContainerListener.java
new file mode 100644
index 0000000..f413e3f7
--- /dev/null
+++ b/services/core/java/com/android/server/wm/RootWindowContainerListener.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;
+
+/**
+ * Interface used by the creator of {@link RootWindowContainerController} to notify the changes to
+ * the display container in activity manager.
+ */
+public interface RootWindowContainerListener extends WindowContainerListener {
+    /** Called when the z-order of display is changed. */
+    void onChildPositionChanged(DisplayWindowController childController, int position);
+}
diff --git a/services/core/java/com/android/server/wm/TEST_MAPPING b/services/core/java/com/android/server/wm/TEST_MAPPING
index e885afa..c99329a 100644
--- a/services/core/java/com/android/server/wm/TEST_MAPPING
+++ b/services/core/java/com/android/server/wm/TEST_MAPPING
@@ -24,6 +24,20 @@
           "exclude-annotation": "android.support.test.filters.FlakyTest"
         }
       ]
+    },
+    {
+      "name": "WmTests",
+      "options": [
+        {
+          "include-filter": "com.android.server.wm."
+        },
+        {
+          "include-annotation": "android.platform.test.annotations.Presubmit"
+        },
+        {
+          "exclude-annotation": "android.support.test.filters.FlakyTest"
+        }
+      ]
     }
   ],
   "postsubmit": [
@@ -37,6 +51,14 @@
           "include-filter": "com.android.server.wm."
         }
       ]
+    },
+    {
+      "name": "WmTests",
+      "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 71f34c9..eb419c9 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -22,10 +22,8 @@
 import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
 import static android.content.res.Configuration.EMPTY;
+
 import static com.android.server.EventLogTags.WM_TASK_REMOVED;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
-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.TaskProto.APP_WINDOW_TOKENS;
 import static com.android.server.wm.TaskProto.BOUNDS;
 import static com.android.server.wm.TaskProto.DEFER_REMOVAL;
@@ -33,6 +31,9 @@
 import static com.android.server.wm.TaskProto.ID;
 import static com.android.server.wm.TaskProto.TEMP_INSET_BOUNDS;
 import static com.android.server.wm.TaskProto.WINDOW_CONTAINER;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 
 import android.annotation.CallSuper;
 import android.app.ActivityManager.TaskDescription;
@@ -43,8 +44,8 @@
 import android.util.Slog;
 import android.util.proto.ProtoOutputStream;
 import android.view.Surface;
-
 import android.view.SurfaceControl;
+
 import com.android.internal.annotations.VisibleForTesting;
 
 import java.io.PrintWriter;
@@ -472,7 +473,8 @@
 
     void setDragResizing(boolean dragResizing, int dragResizeMode) {
         if (mDragResizing != dragResizing) {
-            if (!DragResizeMode.isModeAllowedForStack(mStack, dragResizeMode)) {
+            // No need to check if the mode is allowed if it's leaving dragResize
+            if (dragResizing && !DragResizeMode.isModeAllowedForStack(mStack, dragResizeMode)) {
                 throw new IllegalArgumentException("Drag resize mode not allow for stack stackId="
                         + mStack.mStackId + " dragResizeMode=" + dragResizeMode);
             }
diff --git a/services/core/java/com/android/server/wm/TaskPositioner.java b/services/core/java/com/android/server/wm/TaskPositioner.java
index 8effc6b..d2696c0 100644
--- a/services/core/java/com/android/server/wm/TaskPositioner.java
+++ b/services/core/java/com/android/server/wm/TaskPositioner.java
@@ -19,17 +19,17 @@
 import static android.app.ActivityTaskManager.RESIZE_MODE_USER;
 import static android.app.ActivityTaskManager.RESIZE_MODE_USER_FORCED;
 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
+
+import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_FREEFORM;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_POSITIONING;
 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.dipToPixel;
-import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_FREEFORM;
 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 android.annotation.IntDef;
-import android.app.IActivityManager;
 import android.app.IActivityTaskManager;
 import android.graphics.Point;
 import android.graphics.Rect;
@@ -51,7 +51,6 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.server.input.InputApplicationHandle;
 import com.android.server.input.InputWindowHandle;
-import com.android.server.wm.WindowManagerService.H;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -209,7 +208,6 @@
                     // 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) {
@@ -237,7 +235,7 @@
     }
 
     /**
-     * @param display The Display that the window being dragged is on.
+     * @param displayContent The Display that the window being dragged is on.
      */
     void register(DisplayContent displayContent) {
         final Display display = displayContent.getDisplay();
@@ -303,6 +301,9 @@
         }
         mDisplayContent.pauseRotationLocked();
 
+        // Notify InputMonitor to take mDragWindowHandle.
+        mDisplayContent.getInputMonitor().updateInputWindowsLw(true /*force*/);
+
         mSideMargin = dipToPixel(SIDE_MARGIN_DIP, mDisplayMetrics);
         mMinVisibleWidth = dipToPixel(MINIMUM_VISIBLE_WIDTH_IN_DP, mDisplayMetrics);
         mMinVisibleHeight = dipToPixel(MINIMUM_VISIBLE_HEIGHT_IN_DP, mDisplayMetrics);
@@ -334,6 +335,9 @@
         mDragApplicationHandle = null;
         mDragEnded = true;
 
+        // Notify InputMonitor to remove mDragWindowHandle.
+        mDisplayContent.getInputMonitor().updateInputWindowsLw(true /*force*/);
+
         // Resume rotations after a drag.
         if (DEBUG_ORIENTATION) {
             Slog.d(TAG, "Resuming rotation after re-position");
diff --git a/services/core/java/com/android/server/wm/TaskPositioningController.java b/services/core/java/com/android/server/wm/TaskPositioningController.java
index 9cdc6b7..33416f6 100644
--- a/services/core/java/com/android/server/wm/TaskPositioningController.java
+++ b/services/core/java/com/android/server/wm/TaskPositioningController.java
@@ -20,14 +20,13 @@
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 
 import android.annotation.Nullable;
-import android.app.IActivityManager;
 import android.app.IActivityTaskManager;
-import android.os.RemoteException;
 import android.os.Handler;
 import android.os.Looper;
+import android.os.RemoteException;
 import android.util.Slog;
-import android.view.Display;
 import android.view.IWindow;
+
 import com.android.internal.annotations.GuardedBy;
 import com.android.server.input.InputManagerService;
 import com.android.server.input.InputWindowHandle;
@@ -124,10 +123,8 @@
             return false;
         }
 
-        Display display = displayContent.getDisplay();
         mTaskPositioner = TaskPositioner.create(mService);
         mTaskPositioner.register(displayContent);
-        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
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index 6c8572a..b7507a4 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -303,7 +303,7 @@
     private Rect getInsets(WindowState state) {
         // XXX(b/72757033): These are insets relative to the window frame, but we're really
         // interested in the insets relative to the task bounds.
-        final Rect insets = minRect(state.mContentInsets, state.mStableInsets);
+        final Rect insets = minRect(state.getContentInsets(), state.getStableInsets());
         InsetUtils.addInsets(insets, state.mAppToken.getLetterboxInsets());
         return insets;
     }
@@ -373,7 +373,7 @@
         node.setClipToBounds(false);
         final DisplayListCanvas c = node.start(width, height);
         c.drawColor(color);
-        decorPainter.setInsets(mainWindow.mContentInsets, mainWindow.mStableInsets);
+        decorPainter.setInsets(mainWindow.getContentInsets(), mainWindow.getStableInsets());
         decorPainter.drawDecors(c, null /* statusBarExcludeFrame */);
         node.end(c);
         final Bitmap hwBitmap = ThreadedRenderer.createHardwareBitmap(node, width, height);
@@ -383,7 +383,7 @@
         // Note, the app theme snapshot is never translucent because we enforce a non-translucent
         // color above
         return new TaskSnapshot(hwBitmap.createGraphicBufferHandle(),
-                topChild.getConfiguration().orientation, mainWindow.mStableInsets,
+                topChild.getConfiguration().orientation, mainWindow.getStableInsets(),
                 ActivityManager.isLowRamDeviceStatic() /* reduced */, 1.0f /* scale */,
                 false /* isRealSnapshot */, task.getWindowingMode(), getSystemUiVisibility(task),
                 false);
diff --git a/services/core/java/com/android/server/wm/WindowFrames.java b/services/core/java/com/android/server/wm/WindowFrames.java
index 5f41df7..9381fc6 100644
--- a/services/core/java/com/android/server/wm/WindowFrames.java
+++ b/services/core/java/com/android/server/wm/WindowFrames.java
@@ -18,23 +18,30 @@
 
 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.CONTENT_INSETS;
 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.OUTSETS;
 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.OVERSCAN_INSETS;
 import static com.android.server.wm.WindowFramesProto.PARENT_FRAME;
+import static com.android.server.wm.WindowFramesProto.STABLE_INSETS;
 import static com.android.server.wm.WindowFramesProto.VISIBLE_FRAME;
+import static com.android.server.wm.WindowFramesProto.VISIBLE_INSETS;
 
 import android.annotation.NonNull;
 import android.graphics.Rect;
 import android.util.proto.ProtoOutputStream;
+import android.view.DisplayCutout;
+import android.view.WindowManager;
+
+import com.android.server.wm.utils.InsetUtils;
+import com.android.server.wm.utils.WmDisplayCutout;
 
 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.
@@ -42,6 +49,7 @@
  * TODO(b/111611553): Investigate which frames are still needed and which are duplicates
  */
 public class WindowFrames {
+    private static final StringBuilder sTmpSB = new StringBuilder();
 
     /**
      * In most cases, this is the area of the entire screen.
@@ -59,7 +67,7 @@
      *
      * TODO(b/111611553): The name is unclear and most likely should be swapped with
      * {@link #mParentFrame}
-    */
+     */
     public final Rect mDisplayFrame = new Rect();
 
     /**
@@ -117,6 +125,12 @@
      */
     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();
+
     /**
      * Whether the parent frame would have been different if there was no display cutout.
      */
@@ -130,7 +144,52 @@
     /**
      * The last cutout that has been reported to the client.
      */
-    WmDisplayCutout mLastDisplayCutout = WmDisplayCutout.NO_CUTOUT;
+    private WmDisplayCutout mLastDisplayCutout = WmDisplayCutout.NO_CUTOUT;
+
+    private boolean mDisplayCutoutChanged;
+
+    /**
+     * Insets that determine the area covered by the display overscan region.  These are in the
+     * application's coordinate space (without compatibility scale applied).
+     */
+    final Rect mOverscanInsets = new Rect();
+    final Rect mLastOverscanInsets = new Rect();
+    private boolean mOverscanInsetsChanged;
+
+    /**
+     * Insets that determine the area covered by the stable system windows.  These are in the
+     * application's coordinate space (without compatibility scale applied).
+     */
+    final Rect mStableInsets = new Rect();
+    final Rect mLastStableInsets = new Rect();
+    private boolean mStableInsetsChanged;
+
+    /**
+     * Outsets determine the area outside of the surface where we want to pretend that it's possible
+     * to draw anyway.
+     */
+    final Rect mOutsets = new Rect();
+    final Rect mLastOutsets = new Rect();
+    private boolean mOutsetsChanged = false;
+
+    /**
+     * Insets that determine the actually visible area.  These are in the application's
+     * coordinate space (without compatibility scale applied).
+     */
+    final Rect mVisibleInsets = new Rect();
+    final Rect mLastVisibleInsets = new Rect();
+    private boolean mVisibleInsetsChanged;
+
+    /**
+     * Insets that are covered by system windows (such as the status bar) and
+     * transient docking windows (such as the IME).  These are in the application's
+     * coordinate space (without compatibility scale applied).
+     */
+    final Rect mContentInsets = new Rect();
+    final Rect mLastContentInsets = new Rect();
+    private boolean mContentInsetsChanged;
+
+    private final Rect mTmpRect = new Rect();
 
     public WindowFrames() {
     }
@@ -170,15 +229,141 @@
     /**
      * @return true if the width or height has changed since last reported to the client.
      */
-    boolean didFrameSizeChange() {
+    private 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.
+     * Calculates the outsets for this windowFrame. The outsets are calculated by the area between
+     * the {@link #mOutsetFrame} and the {@link #mContentFrame}. If there are no outsets, then
+     * {@link #mOutsets} is set to empty.
+     *
+     * @param hasOutsets Whether this frame has outsets.
      */
-    boolean didDisplayCutoutChange() {
-        return !mLastDisplayCutout.equals(mDisplayCutout);
+    void calculateOutsets(boolean hasOutsets) {
+        if (hasOutsets) {
+            InsetUtils.insetsBetweenFrames(mOutsetFrame, mContentFrame, mOutsets);
+        } else {
+            mOutsets.setEmpty();
+        }
+    }
+
+    /**
+     * Calculate the insets for the type {@link WindowManager.LayoutParams#TYPE_DOCK_DIVIDER}
+     *
+     * @param cutoutInsets The insets for the cutout.
+     */
+    void calculateDockedDividerInsets(Rect cutoutInsets) {
+        // For the docked divider, we calculate the stable insets like a full-screen window
+        // so it can use it to calculate the snap positions.
+        mTmpRect.set(mDisplayFrame);
+        mTmpRect.inset(cutoutInsets);
+        mTmpRect.intersectUnchecked(mStableFrame);
+        InsetUtils.insetsBetweenFrames(mDisplayFrame, mTmpRect, mStableInsets);
+
+        // 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();
+        mDisplayCutout = WmDisplayCutout.NO_CUTOUT;
+    }
+
+    /**
+     * Calculate the insets for a window.
+     *
+     * @param windowsAreFloating    Whether the window is in a floating task such as pinned or
+     *                              freeform
+     * @param inFullscreenContainer Whether the window is in a container that takes up the screen's
+     *                              entire space
+     * @param windowBounds          The bounds for the window
+     */
+    void calculateInsets(boolean windowsAreFloating, boolean inFullscreenContainer,
+            Rect windowBounds) {
+        // 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 > windowBounds.right;
+        boolean overrideBottomInset = !windowsAreFloating && !inFullscreenContainer
+                && mFrame.bottom > windowBounds.bottom;
+
+        mTmpRect.set(mFrame.left, mFrame.top, overrideRightInset ? mTmpRect.right : mFrame.right,
+                overrideBottomInset ? mTmpRect.bottom : mFrame.bottom);
+
+        InsetUtils.insetsBetweenFrames(mTmpRect, mContentFrame, mContentInsets);
+        InsetUtils.insetsBetweenFrames(mTmpRect, mVisibleFrame, mVisibleInsets);
+        InsetUtils.insetsBetweenFrames(mTmpRect, mStableFrame, mStableInsets);
+    }
+
+    /**
+     * Scales all the insets by a specific amount.
+     *
+     * @param scale The amount to scale the insets by.
+     */
+    void scaleInsets(float scale) {
+        mOverscanInsets.scale(scale);
+        mContentInsets.scale(scale);
+        mVisibleInsets.scale(scale);
+        mStableInsets.scale(scale);
+        mOutsets.scale(scale);
+    }
+
+    void offsetFrames(int layoutXDiff, int layoutYDiff) {
+        mFrame.offset(layoutXDiff, layoutYDiff);
+        mContentFrame.offset(layoutXDiff, layoutYDiff);
+        mVisibleFrame.offset(layoutXDiff, layoutYDiff);
+        mStableFrame.offset(layoutXDiff, layoutYDiff);
+    }
+
+    /**
+     * Updates info about whether the size of the window has changed since last reported.
+     *
+     * @return true if info about size has changed since last reported.
+     */
+    boolean setReportResizeHints() {
+        mOverscanInsetsChanged |= !mLastOverscanInsets.equals(mOverscanInsets);
+        mContentInsetsChanged |= !mLastContentInsets.equals(mContentInsets);
+        mVisibleInsetsChanged |= !mLastVisibleInsets.equals(mVisibleInsets);
+        mStableInsetsChanged |= !mLastStableInsets.equals(mStableInsets);
+        mOutsetsChanged |= !mLastOutsets.equals(mOutsets);
+        mFrameSizeChanged |= didFrameSizeChange();
+        mDisplayCutoutChanged |= !mLastDisplayCutout.equals(mDisplayCutout);
+        return mOverscanInsetsChanged || mContentInsetsChanged || mVisibleInsetsChanged
+                || mStableInsetsChanged || mOutsetsChanged || mFrameSizeChanged
+                || mDisplayCutoutChanged;
+    }
+
+    /**
+     * Resets the insets changed flags so they're all set to false again. This should be called
+     * after the insets are reported to client.
+     */
+    void resetInsetsChanged() {
+        mOverscanInsetsChanged = false;
+        mContentInsetsChanged = false;
+        mVisibleInsetsChanged = false;
+        mStableInsetsChanged = false;
+        mOutsetsChanged = false;
+        mFrameSizeChanged = false;
+        mDisplayCutoutChanged = false;
+    }
+
+    /**
+     * Copy over inset values as the last insets that were sent to the client.
+     */
+    void updateLastInsetValues() {
+        mLastOverscanInsets.set(mOverscanInsets);
+        mLastContentInsets.set(mContentInsets);
+        mLastVisibleInsets.set(mVisibleInsets);
+        mLastStableInsets.set(mStableInsets);
+        mLastOutsets.set(mOutsets);
+        mLastDisplayCutout = mDisplayCutout;
+    }
+
+    /**
+     * Sets the last content insets as (-1, -1, -1, -1) to force the next layout pass to update
+     * the client.
+     */
+    void resetLastContentInsets() {
+        mLastContentInsets.set(-1, -1, -1, -1);
     }
 
     public void writeToProto(@NonNull ProtoOutputStream proto, long fieldId) {
@@ -193,33 +378,57 @@
         mContainingFrame.writeToProto(proto, CONTAINING_FRAME);
         mFrame.writeToProto(proto, FRAME);
         mDisplayCutout.getDisplayCutout().writeToProto(proto, CUTOUT);
+        mContentInsets.writeToProto(proto, CONTENT_INSETS);
+        mOverscanInsets.writeToProto(proto, OVERSCAN_INSETS);
+        mVisibleInsets.writeToProto(proto, VISIBLE_INSETS);
+        mStableInsets.writeToProto(proto, STABLE_INSETS);
+        mOutsets.writeToProto(proto, OUTSETS);
+
         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();
+        pw.println(prefix + "Frames: containing="
+                + mContainingFrame.toShortString(sTmpSB)
+                + " parent=" + mParentFrame.toShortString(sTmpSB));
+        pw.println(prefix + "    display=" + mDisplayFrame.toShortString(sTmpSB)
+                + " overscan=" + mOverscanFrame.toShortString(sTmpSB));
+        pw.println(prefix + "    content=" + mContentFrame.toShortString(sTmpSB)
+                + " visible=" + mVisibleFrame.toShortString(sTmpSB));
+        pw.println(prefix + "    decor=" + mDecorFrame.toShortString(sTmpSB));
+        pw.println(prefix + "    outset=" + mOutsetFrame.toShortString(sTmpSB));
+        pw.println(prefix + "mFrame=" + mFrame.toShortString(sTmpSB)
+                + " last=" + mLastFrame.toShortString(sTmpSB));
+        pw.println(prefix + " cutout=" + mDisplayCutout.getDisplayCutout()
+                + " last=" + mLastDisplayCutout.getDisplayCutout());
+        pw.print(prefix + "Cur insets: overscan=" + mOverscanInsets.toShortString(sTmpSB)
+                + " content=" + mContentInsets.toShortString(sTmpSB)
+                + " visible=" + mVisibleInsets.toShortString(sTmpSB)
+                + " stable=" + mStableInsets.toShortString(sTmpSB)
+                + " outsets=" + mOutsets.toShortString(sTmpSB));
+        pw.println(prefix + "Lst insets: overscan=" + mLastOverscanInsets.toShortString(sTmpSB)
+                + " content=" + mLastContentInsets.toShortString(sTmpSB)
+                + " visible=" + mLastVisibleInsets.toShortString(sTmpSB)
+                + " stable=" + mLastStableInsets.toShortString(sTmpSB)
+                + " outset=" + mLastOutsets.toShortString(sTmpSB));
+    }
+
+    String getInsetsInfo() {
+        return "ci=" + mContentInsets.toShortString()
+                + " vi=" + mVisibleInsets.toShortString()
+                + " si=" + mStableInsets.toShortString()
+                + " of=" + mOutsets.toShortString();
+    }
+
+    String getInsetsChangedInfo() {
+        return "contentInsetsChanged=" + mContentInsetsChanged
+                + " " + mContentInsets.toShortString()
+                + " visibleInsetsChanged=" + mVisibleInsetsChanged
+                + " " + mVisibleInsets.toShortString()
+                + " stableInsetsChanged=" + mStableInsetsChanged
+                + " " + mStableInsets.toShortString()
+                + " outsetsChanged=" + mOutsetsChanged
+                + " " + mOutsets.toShortString()
+                + " displayCutoutChanged=" + mDisplayCutoutChanged;
     }
 }
diff --git a/services/core/java/com/android/server/wm/WindowManagerInternal.java b/services/core/java/com/android/server/wm/WindowManagerInternal.java
index 44783f8..793ce60 100644
--- a/services/core/java/com/android/server/wm/WindowManagerInternal.java
+++ b/services/core/java/com/android/server/wm/WindowManagerInternal.java
@@ -30,6 +30,7 @@
 import android.view.MagnificationSpec;
 import android.view.WindowInfo;
 
+import com.android.internal.view.IInputMethodClient;
 import com.android.server.input.InputManagerService;
 import com.android.server.policy.WindowManagerPolicy;
 
@@ -334,9 +335,9 @@
     public abstract void registerAppTransitionListener(AppTransitionListener listener);
 
     /**
-     * Retrieves a height of input method window.
+     * Retrieves a height of input method window for given display.
      */
-    public abstract int getInputMethodWindowVisibleHeight();
+    public abstract int getInputMethodWindowVisibleHeight(int displayId);
 
     /**
       * Saves last input method window for transition.
@@ -355,8 +356,8 @@
     /**
      * Notifies WindowManagerService that the current IME window status is being changed.
      *
-     * <p>Only {@link com.android.server.InputMethodManagerService} is the expected and tested
-     * caller of this method.</p>
+     * <p>Only {@link com.android.server.inputmethod.InputMethodManagerService} is the expected and
+     * tested caller of this method.</p>
      *
      * @param imeToken token to track the active input method. Corresponding IME windows can be
      *                 identified by checking {@link android.view.WindowManager.LayoutParams#token}.
@@ -375,8 +376,8 @@
     /**
      * Notifies WindowManagerService that the current IME window status is being changed.
      *
-     * <p>Only {@link com.android.server.InputMethodManagerService} is the expected and tested
-     * caller of this method.</p>
+     * <p>Only {@link com.android.server.inputmethod.InputMethodManagerService} is the expected and
+     * tested caller of this method.</p>
      *
      * @param imeToken token to track the active input method. Corresponding IME windows can be
      *                 identified by checking {@link android.view.WindowManager.LayoutParams#token}.
@@ -441,4 +442,14 @@
      * Returns {@code true} if a Window owned by {@code uid} has focus.
      */
     public abstract boolean isUidFocused(int uid);
+
+    /**
+     * Returns {@code true} if a process that is identified by {@code client} has IME focus.
+     */
+    public abstract boolean inputMethodClientHasFocus(IInputMethodClient client);
+
+    /**
+     * Return the display Id for given window.
+     */
+    public abstract int getDisplayIdForWindow(IBinder windowToken);
 }
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index ea0dd7e..2ed09ae 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -650,8 +650,6 @@
     /** If true hold off on modifying the animation layer of mInputMethodTarget */
     boolean mInputMethodTargetWaitingAnim;
 
-    WindowState mInputMethodWindow = null;
-
     boolean mHardKeyboardAvailable;
     WindowManagerInternal.OnHardKeyboardStatusChangeListener mHardKeyboardStatusChangeListener;
     SettingsObserver mSettingsObserver;
@@ -734,8 +732,9 @@
     final DisplayManagerInternal mDisplayManagerInternal;
     final DisplayManager mDisplayManager;
 
-    // Indicates whether this device supports wide color gamut rendering
+    // Indicates whether this device supports wide color gamut / HDR rendering
     private boolean mHasWideColorGamutSupport;
+    private boolean mHasHdrSupport;
 
     // Who is holding the screen on.
     private Session mHoldingScreenOn;
@@ -1413,7 +1412,7 @@
             win.mToken.addWindow(win);
             if (type == TYPE_INPUT_METHOD) {
                 win.mGivenInsetsPending = true;
-                setInputMethodWindowLocked(win);
+                displayContent.setInputMethodWindowLocked(win);
                 imMayMove = false;
             } else if (type == TYPE_INPUT_METHOD_DIALOG) {
                 displayContent.computeImeTarget(true /* updateImeTarget */);
@@ -1686,8 +1685,9 @@
         mWindowsChanged = true;
         if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Final remove of window: " + win);
 
-        if (mInputMethodWindow == win) {
-            setInputMethodWindowLocked(null);
+        final DisplayContent displayContent = win.getDisplayContent();
+        if (displayContent.mInputMethodWindow == win) {
+            displayContent.setInputMethodWindowLocked(null);
         }
 
         final WindowToken token = win.mToken;
@@ -1732,13 +1732,6 @@
         dc.getInputMonitor().updateInputWindowsLw(true /*force*/);
     }
 
-    void setInputMethodWindowLocked(WindowState win) {
-        mInputMethodWindow = win;
-        final DisplayContent dc = win != null
-                ? win.getDisplayContent() : getDefaultDisplayContentLocked();
-        dc.computeImeTarget(true /* updateImeTarget */);
-    }
-
     private void updateHiddenWhileSuspendedState(ArraySet<String> packages, boolean suspended) {
         synchronized (mWindowMap) {
             mRoot.updateHiddenWhileSuspendedState(packages, suspended);
@@ -2057,8 +2050,10 @@
                 if ((result & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) {
                     focusMayChange = isDefaultDisplay;
                 }
-                if (win.mAttrs.type == TYPE_INPUT_METHOD && mInputMethodWindow == null) {
-                    setInputMethodWindowLocked(win);
+                final DisplayContent displayContent = win.getDisplayContent();
+                if (win.mAttrs.type == TYPE_INPUT_METHOD
+                        && displayContent.mInputMethodWindow == null) {
+                    displayContent.setInputMethodWindowLocked(win);
                     imMayMove = true;
                 }
                 win.adjustStartingWindowFlags();
@@ -2167,14 +2162,10 @@
             // The last inset values represent the last client state.
             win.updateLastInsetValues();
 
-            outFrame.set(win.mCompatFrame);
-            outOverscanInsets.set(win.mOverscanInsets);
-            outContentInsets.set(win.mContentInsets);
-            win.mLastRelayoutContentInsets.set(win.mContentInsets);
-            outVisibleInsets.set(win.mVisibleInsets);
-            outStableInsets.set(win.mStableInsets);
+            win.getCompatFrame(outFrame);
+            win.getInsetsForRelayout(outOverscanInsets, outContentInsets, outVisibleInsets,
+                    outStableInsets, outOutsets);
             outCutout.set(win.getWmDisplayCutout().getDisplayCutout());
-            outOutsets.set(win.mOutsets);
             outBackdropFrame.set(win.getBackdropFrame(win.getFrameLw()));
             if (localLOGV) Slog.v(
                 TAG_WM, "Relayout given client " + client.asBinder()
@@ -2225,8 +2216,9 @@
             // of a transaction to avoid artifacts.
             win.mAnimatingExit = true;
         } else {
-            if (mInputMethodWindow == win) {
-                setInputMethodWindowLocked(null);
+            final DisplayContent displayContent = win.getDisplayContent();
+            if (displayContent.mInputMethodWindow == win) {
+                displayContent.setInputMethodWindowLocked(null);
             }
             boolean stopped = win.mAppToken != null ? win.mAppToken.mAppStopped : true;
             // We set mDestroying=true so AppWindowToken#notifyAppStopped in-to destroy surfaces
@@ -2831,7 +2823,7 @@
 
     @Override
     public WindowManagerPolicy.WindowState getInputMethodWindowLw() {
-        return mInputMethodWindow;
+        return mRoot.getCurrentInputMethodWindow();
     }
 
     @Override
@@ -4504,6 +4496,7 @@
         mPolicy.systemReady();
         mTaskSnapshotController.systemReady();
         mHasWideColorGamutSupport = queryWideColorGamutSupport();
+        mHasHdrSupport = queryHdrSupport();
     }
 
     private static boolean queryWideColorGamutSupport() {
@@ -4519,6 +4512,19 @@
         return false;
     }
 
+    private static boolean queryHdrSupport() {
+        try {
+            ISurfaceFlingerConfigs surfaceFlinger = ISurfaceFlingerConfigs.getService();
+            OptionalBool hasHdr = surfaceFlinger.hasHDRDisplay();
+            if (hasHdr != null) {
+                return hasHdr.value;
+            }
+        } catch (RemoteException e) {
+            // Ignore, we're in big trouble if we can't talk to SurfaceFlinger's config store
+        }
+        return false;
+    }
+
     // -------------------------------------------------------------
     // Async Handler
     // -------------------------------------------------------------
@@ -5040,30 +5046,6 @@
     }
 
     @Override
-    public boolean inputMethodClientHasFocus(IInputMethodClient client) {
-        synchronized (mWindowMap) {
-            // TODO: multi-display
-            if (getDefaultDisplayContentLocked().inputMethodClientHasFocus(client)) {
-                return true;
-            }
-
-            // Okay, how about this...  what is the current focus?
-            // It seems in some cases we may not have moved the IM
-            // target window, such as when it was in a pop-up window,
-            // so let's also look at the current focus.  (An example:
-            // go to Gmail, start searching so the keyboard goes up,
-            // press home.  Sometimes the IME won't go down.)
-            // Would be nice to fix this more correctly, but it's
-            // way at the end of a release, and this should be good enough.
-            if (mCurrentFocus != null && mCurrentFocus.mSession.mClient != null
-                    && mCurrentFocus.mSession.mClient.asBinder() == client.asBinder()) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    @Override
     public void getInitialDisplaySize(int displayId, Point size) {
         synchronized (mWindowMap) {
             final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
@@ -5369,17 +5351,6 @@
         mWindowPlacerLocked.performSurfacePlacement();
     }
 
-    /**
-     * Get an array with display ids ordered by focus priority - last items should be given
-     * focus first. Sparse array just maps position to displayId.
-     */
-    // TODO: Maintain display list in focus order in ActivityManager and remove this call.
-    public void getDisplaysInFocusOrder(SparseIntArray displaysInFocusOrder) {
-        synchronized(mWindowMap) {
-            mRoot.getDisplaysInFocusOrder(displaysInFocusOrder);
-        }
-    }
-
     @Override
     public void setOverscan(int displayId, int left, int top, int right, int bottom) {
         if (mContext.checkCallingOrSelfPermission(
@@ -5599,10 +5570,10 @@
             // change message pending.
             mH.removeMessages(H.REPORT_FOCUS_CHANGE);
             mH.sendEmptyMessage(H.REPORT_FOCUS_CHANGE);
-            // TODO(multidisplay): Focused windows on default display only.
-            final DisplayContent displayContent = getDefaultDisplayContentLocked();
+            final DisplayContent displayContent = (newFocus != null) ? newFocus.getDisplayContent()
+                    : getDefaultDisplayContentLocked();
             boolean imWindowChanged = false;
-            if (mInputMethodWindow != null) {
+            if (displayContent.mInputMethodWindow != null) {
                 final WindowState prevTarget = mInputMethodTarget;
 
                 final WindowState newTarget =
@@ -5611,10 +5582,11 @@
 
                 if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS
                         && mode != UPDATE_FOCUS_WILL_PLACE_SURFACES) {
-                    final int prevImeAnimLayer = mInputMethodWindow.mWinAnimator.mAnimLayer;
+                    final int prevImeAnimLayer =
+                            displayContent.mInputMethodWindow.mWinAnimator.mAnimLayer;
                     displayContent.assignWindowLayers(false /* setLayoutNeeded */);
-                    imWindowChanged |=
-                            prevImeAnimLayer != mInputMethodWindow.mWinAnimator.mAnimLayer;
+                    imWindowChanged |= prevImeAnimLayer
+                            != displayContent.mInputMethodWindow.mWinAnimator.mAnimLayer;
                 }
             }
 
@@ -5637,7 +5609,7 @@
 
             int focusChanged = mPolicy.focusChangedLw(oldFocus, newFocus);
 
-            if (imWindowChanged && oldFocus != mInputMethodWindow) {
+            if (imWindowChanged && oldFocus != displayContent.mInputMethodWindow) {
                 // Focus of the input method window changed. Perform layout if needed.
                 if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
                     displayContent.performLayout(true /*initial*/,  updateInputWindows);
@@ -6028,11 +6000,10 @@
     }
 
     @Override
-    public void createInputConsumer(IBinder token, String name, InputChannel inputChannel) {
+    public void createInputConsumer(IBinder token, String name, int displayId,
+            InputChannel inputChannel) {
         synchronized (mWindowMap) {
-            // 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);
+            DisplayContent display = mRoot.getDisplayContent(displayId);
             if (display != null) {
                 display.getInputMonitor().createInputConsumer(token, name, inputChannel,
                         Binder.getCallingPid(), Binder.getCallingUserHandle());
@@ -6041,11 +6012,9 @@
     }
 
     @Override
-    public boolean destroyInputConsumer(String name) {
+    public boolean destroyInputConsumer(String name, int displayId) {
         synchronized (mWindowMap) {
-            // TODO(b/112049699): Fix this for multiple displays. For consistency with
-            // createInputConsumer above.
-            DisplayContent display = mRoot.getDisplayContent(Display.DEFAULT_DISPLAY);
+            DisplayContent display = mRoot.getDisplayContent(displayId);
             if (display != null) {
                 return display.getInputMonitor().destroyInputConsumer(name);
             }
@@ -6060,8 +6029,15 @@
         }
         synchronized (mWindowMap) {
             final Region r = new Region();
-            if (mInputMethodWindow != null) {
-                mInputMethodWindow.getTouchableRegion(r);
+            // TODO(b/111080190): this method is only return the recent focused IME touch region,
+            // For Multi-Session IME, will need to add API for given display Id to
+            // get the right IME touch region.
+            for (int i = mRoot.mChildren.size() - 1; i >= 0; --i) {
+                final DisplayContent displayContent = mRoot.mChildren.get(i);
+                if (displayContent.mInputMethodWindow != null) {
+                    displayContent.mInputMethodWindow.getTouchableRegion(r);
+                    return r;
+                }
             }
             return r;
         }
@@ -6244,8 +6220,9 @@
         if (mFocusedApp != null) {
             mFocusedApp.writeNameToProto(proto, FOCUSED_APP);
         }
-        if (mInputMethodWindow != null) {
-            mInputMethodWindow.writeIdentifierToProto(proto, INPUT_METHOD_WINDOW);
+        final WindowState imeWindow = mRoot.getCurrentInputMethodWindow();
+        if (imeWindow != null) {
+            imeWindow.writeIdentifierToProto(proto, INPUT_METHOD_WINDOW);
         }
         proto.write(DISPLAY_FROZEN, mDisplayFrozen);
         final DisplayContent defaultDisplayContent = getDefaultDisplayContentLocked();
@@ -6415,8 +6392,9 @@
                 pw.print("  mLastStatusBarVisibility=0x");
                         pw.println(Integer.toHexString(mLastStatusBarVisibility));
             }
-            if (mInputMethodWindow != null) {
-                pw.print("  mInputMethodWindow="); pw.println(mInputMethodWindow);
+            final WindowState imeWindow = mRoot.getCurrentInputMethodWindow();
+            if (imeWindow != null) {
+                pw.print("  mInputMethodWindow="); pw.println(imeWindow);
             }
             mWindowPlacerLocked.dump(pw, "  ");
             mRoot.mWallpaperController.dump(pw, "  ");
@@ -7314,10 +7292,9 @@
         }
 
         @Override
-        public int getInputMethodWindowVisibleHeight() {
+        public int getInputMethodWindowVisibleHeight(int displayId) {
             synchronized (mWindowMap) {
-                // TODO(multi-display): Have caller pass in the display they are interested in.
-                final DisplayContent dc = getDefaultDisplayContentLocked();
+                final DisplayContent dc = mRoot.getDisplayContent(displayId);
                 return dc.mDisplayFrames.getInputMethodWindowVisibleHeight();
             }
         }
@@ -7325,8 +7302,9 @@
         @Override
         public void saveLastInputMethodWindowForTransition() {
             synchronized (mWindowMap) {
-                if (mInputMethodWindow != null) {
-                    mPolicy.setLastInputMethodWindowLw(mInputMethodWindow, mInputMethodTarget);
+                final WindowState imeWindow = mRoot.getCurrentInputMethodWindow();
+                if (imeWindow != null) {
+                    mPolicy.setLastInputMethodWindowLw(imeWindow, mInputMethodTarget);
                 }
             }
         }
@@ -7432,6 +7410,44 @@
                 return mCurrentFocus != null ? uid == mCurrentFocus.getOwningUid() : false;
             }
         }
+
+    public boolean inputMethodClientHasFocus(IInputMethodClient client) {
+        boolean hasFocus;
+        synchronized (mWindowMap) {
+            // Check all displays if any input method window has focus.
+            for (int i = mRoot.mChildren.size() - 1; i >= 0; --i) {
+                final DisplayContent displayContent = mRoot.mChildren.get(i);
+                if (displayContent.inputMethodClientHasFocus(client)) {
+                    return true;
+                }
+            }
+
+            // Okay, how about this...  what is the current focus?
+            // It seems in some cases we may not have moved the IM
+            // target window, such as when it was in a pop-up window,
+            // so let's also look at the current focus.  (An example:
+            // go to Gmail, start searching so the keyboard goes up,
+            // press home.  Sometimes the IME won't go down.)
+            // Would be nice to fix this more correctly, but it's
+            // way at the end of a release, and this should be good enough.
+            if (mCurrentFocus != null && mCurrentFocus.mSession.mClient != null
+                    && mCurrentFocus.mSession.mClient.asBinder() == client.asBinder()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+        @Override
+        public int getDisplayIdForWindow(IBinder windowToken) {
+            synchronized (mWindowMap) {
+                final WindowState window = mWindowMap.get(windowToken);
+                if (window != null) {
+                    return window.getDisplayContent().getDisplayId();
+                }
+                return Display.INVALID_DISPLAY;
+            }
+        }
     }
 
     void registerAppFreezeListener(AppFreezeListener listener) {
@@ -7510,6 +7526,10 @@
                 SystemProperties.getInt("persist.sys.sf.native_mode", 0) != 1;
     }
 
+    boolean hasHdrSupport() {
+        return mHasHdrSupport && hasWideColorGamutSupport();
+    }
+
     void updateNonSystemOverlayWindowsVisibilityIfNeeded(WindowState win, boolean surfaceShown) {
         if (!win.hideNonSystemOverlayWindowsWhenVisible()
                 && !mHidingNonSystemOverlayWindows.contains(win)) {
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 97313f2..5272b66 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -120,7 +120,6 @@
 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.CONTENT_INSETS;
 import static com.android.server.wm.WindowStateProto.DESTROYING;
 import static com.android.server.wm.WindowStateProto.DISPLAY_ID;
 import static com.android.server.wm.WindowStateProto.FINISHED_SEAMLESS_ROTATION_FRAME;
@@ -131,20 +130,16 @@
 import static com.android.server.wm.WindowStateProto.IS_ON_SCREEN;
 import static com.android.server.wm.WindowStateProto.IS_READY_FOR_DISPLAY;
 import static com.android.server.wm.WindowStateProto.IS_VISIBLE;
-import static com.android.server.wm.WindowStateProto.OUTSETS;
-import static com.android.server.wm.WindowStateProto.OVERSCAN_INSETS;
 import static com.android.server.wm.WindowStateProto.PENDING_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;
 import static com.android.server.wm.WindowStateProto.REQUESTED_WIDTH;
-import static com.android.server.wm.WindowStateProto.STABLE_INSETS;
 import static com.android.server.wm.WindowStateProto.STACK_ID;
 import static com.android.server.wm.WindowStateProto.SURFACE_INSETS;
 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_INSETS;
 import static com.android.server.wm.WindowStateProto.WINDOW_CONTAINER;
 import static com.android.server.wm.WindowStateProto.WINDOW_FRAMES;
 
@@ -200,6 +195,7 @@
 import com.android.server.input.InputWindowHandle;
 import com.android.server.policy.WindowManagerPolicy;
 import com.android.server.wm.LocalAnimationAdapter.AnimationSpec;
+import com.android.server.wm.utils.InsetUtils;
 import com.android.server.wm.utils.WmDisplayCutout;
 
 import java.io.PrintWriter;
@@ -309,22 +305,6 @@
     private final MergedConfiguration mLastReportedConfiguration = new MergedConfiguration();
 
     /**
-     * Insets that determine the actually visible area.  These are in the application's
-     * coordinate space (without compatibility scale applied).
-     */
-    final Rect mVisibleInsets = new Rect();
-    private final Rect mLastVisibleInsets = new Rect();
-    private boolean mVisibleInsetsChanged;
-
-    /**
-     * Insets that are covered by system windows (such as the status bar) and
-     * transient docking windows (such as the IME).  These are in the application's
-     * coordinate space (without compatibility scale applied).
-     */
-    final Rect mContentInsets = new Rect();
-    final Rect mLastContentInsets = new Rect();
-
-    /**
      * The last content insets returned to the client in relayout. We use
      * these in the bounds animation to ensure we only observe inset changes
      * at the same time that a client resizes it's surface so that we may use
@@ -333,34 +313,6 @@
      */
     final Rect mLastRelayoutContentInsets = new Rect();
 
-    private boolean mContentInsetsChanged;
-
-    /**
-     * Insets that determine the area covered by the display overscan region.  These are in the
-     * application's coordinate space (without compatibility scale applied).
-     */
-    final Rect mOverscanInsets = new Rect();
-    private final Rect mLastOverscanInsets = new Rect();
-    private boolean mOverscanInsetsChanged;
-
-    /**
-     * Insets that determine the area covered by the stable system windows.  These are in the
-     * application's coordinate space (without compatibility scale applied).
-     */
-    final Rect mStableInsets = new Rect();
-    private final Rect mLastStableInsets = new Rect();
-    private boolean mStableInsetsChanged;
-
-    /**
-     * Outsets determine the area outside of the surface where we want to pretend that it's possible
-     * to draw anyway.
-     */
-    final Rect mOutsets = new Rect();
-    private final Rect mLastOutsets = new Rect();
-    private boolean mOutsetsChanged = false;
-
-    private boolean mDisplayCutoutChanged;
-
     /**
      * Set to true if we are waiting for this window to receive its
      * given internal insets before laying out other windows based on it.
@@ -399,11 +351,6 @@
     float mLastHScale=1, mLastVScale=1;
     final Matrix mTmpMatrix = new Matrix();
 
-    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();
-
     private final WindowFrames mWindowFrames = new WindowFrames();
 
     /**
@@ -602,6 +549,8 @@
      */
     private long mFrameNumber = -1;
 
+    private static final StringBuilder sTmpSB = new StringBuilder();
+
     /**
      * Compares two window sub-layers and returns -1 if the first is lesser than the second in terms
      * of z-order and 1 otherwise.
@@ -896,7 +845,7 @@
                 mWindowFrames.mContainingFrame.bottom =
                         mWindowFrames.mContainingFrame.top + frozen.height();
             }
-            final WindowState imeWin = mService.mInputMethodWindow;
+            final WindowState imeWin = mService.mRoot.getCurrentInputMethodWindow();
             // IME is up and obscuring this window. Adjust the window position so it is visible.
             if (imeWin != null && imeWin.isVisibleNow() && isInputMethodTarget()) {
                 if (inFreeformWindowingMode() && mWindowFrames.mContainingFrame.bottom
@@ -986,17 +935,7 @@
         applyGravityAndUpdateFrame(layoutContainingFrame, layoutDisplayFrame);
 
         // Calculate the outsets before the content frame gets shrinked to the window frame.
-        if (hasOutsets) {
-            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);
-        }
+        mWindowFrames.calculateOutsets(hasOutsets);
 
         // Make sure the content and visible frames are inside of the
         // final window frame.
@@ -1053,91 +992,35 @@
         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(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));
+            InsetUtils.insetsBetweenFrames(layoutContainingFrame, mWindowFrames.mOverscanFrame,
+                    mWindowFrames.mOverscanInsets);
         }
 
         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 = windowFrames.mDisplayCutout.calculateRelativeTo(
                     mWindowFrames.mDisplayFrame);
-            mTmpRect.set(mWindowFrames.mDisplayFrame);
-            mTmpRect.inset(c.getDisplayCutout().getSafeInsets());
-            mTmpRect.intersectUnchecked(mWindowFrames.mStableFrame);
-
-            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();
-            windowFrames.setDisplayCutout(WmDisplayCutout.NO_CUTOUT);
+            mWindowFrames.calculateDockedDividerInsets(c.getDisplayCutout().getSafeInsets());
         } 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
-                    && mWindowFrames.mFrame.right > mTmpRect.right;
-            boolean overrideBottomInset = !windowsAreFloating && !inFullscreenContainer
-                    && 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(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(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));
+            mWindowFrames.calculateInsets(windowsAreFloating, inFullscreenContainer, mTmpRect);
         }
 
-
         mWindowFrames.setDisplayCutout(
-                windowFrames.mDisplayCutout.calculateRelativeTo(windowFrames.mFrame));
+                windowFrames.mDisplayCutout.calculateRelativeTo(mWindowFrames.mFrame));
 
         // Offset the actual frame by the amount layout frame is off.
-        mWindowFrames.mFrame.offset(-layoutXDiff, -layoutYDiff);
-        mCompatFrame.offset(-layoutXDiff, -layoutYDiff);
-        mWindowFrames.mContentFrame.offset(-layoutXDiff, -layoutYDiff);
-        mWindowFrames.mVisibleFrame.offset(-layoutXDiff, -layoutYDiff);
-        mWindowFrames.mStableFrame.offset(-layoutXDiff, -layoutYDiff);
+        mWindowFrames.offsetFrames(-layoutXDiff, -layoutYDiff);
 
-        mCompatFrame.set(mWindowFrames.mFrame);
+        mWindowFrames.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
             // reported to the app in its coordinate space.
-            mOverscanInsets.scale(mInvGlobalScale);
-            mContentInsets.scale(mInvGlobalScale);
-            mVisibleInsets.scale(mInvGlobalScale);
-            mStableInsets.scale(mInvGlobalScale);
-            mOutsets.scale(mInvGlobalScale);
+            mWindowFrames.scaleInsets(mInvGlobalScale);
 
             // Also the scaled frame that we report to the app needs to be
             // adjusted to be in its coordinate space.
-            mCompatFrame.scale(mInvGlobalScale);
+            mWindowFrames.mCompatFrame.scale(mInvGlobalScale);
         }
 
         if (mIsWallpaper && (fw != mWindowFrames.mFrame.width()
@@ -1155,10 +1038,7 @@
                 + mRequestedWidth + ", mRequestedheight="
                 + mRequestedHeight + ") to" + " (pw=" + pw + ", ph=" + ph
                 + "): frame=" + mWindowFrames.mFrame.toShortString()
-                + " ci=" + mContentInsets.toShortString()
-                + " vi=" + mVisibleInsets.toShortString()
-                + " si=" + mStableInsets.toShortString()
-                + " of=" + mOutsets.toShortString());
+                + " " + mWindowFrames.getInsetsInfo());
     }
 
     // TODO: Look into whether this override is still necessary.
@@ -1218,6 +1098,14 @@
         return mWindowFrames.mDisplayCutout;
     }
 
+    void getCompatFrame(Rect outFrame) {
+        outFrame.set(mWindowFrames.mCompatFrame);
+    }
+
+    void getCompatFrameSize(Rect outFrame) {
+        outFrame.set(0, 0, mWindowFrames.mCompatFrame.width(), mWindowFrames.mCompatFrame.height());
+    }
+
     @Override
     public boolean getGivenInsetsPendingLw() {
         return mGivenInsetsPending;
@@ -1269,15 +1157,7 @@
     }
 
     boolean setReportResizeHints() {
-        mOverscanInsetsChanged |= !mLastOverscanInsets.equals(mOverscanInsets);
-        mContentInsetsChanged |= !mLastContentInsets.equals(mContentInsets);
-        mVisibleInsetsChanged |= !mLastVisibleInsets.equals(mVisibleInsets);
-        mStableInsetsChanged |= !mLastStableInsets.equals(mStableInsets);
-        mOutsetsChanged |= !mLastOutsets.equals(mOutsets);
-        mFrameSizeChanged |= mWindowFrames.didFrameSizeChange();
-        mDisplayCutoutChanged |= mWindowFrames.didDisplayCutoutChange();
-        return mOverscanInsetsChanged || mContentInsetsChanged || mVisibleInsetsChanged
-                || mOutsetsChanged || mFrameSizeChanged || mDisplayCutoutChanged;
+        return mWindowFrames.setReportResizeHints();
     }
 
     /**
@@ -1300,7 +1180,7 @@
             return;
         }
 
-        setReportResizeHints();
+        boolean didFrameInsetsChange = setReportResizeHints();
         boolean configChanged = isConfigChanged();
         if (DEBUG_CONFIGURATION && configChanged) {
             Slog.v(TAG_WM, "Win " + this + " config changed: " + getConfiguration());
@@ -1317,31 +1197,18 @@
         // variables, because mFrameSizeChanged only tracks the width and height changing.
         mWindowFrames.mLastFrame.set(mWindowFrames.mFrame);
 
-        if (mContentInsetsChanged
-                || mVisibleInsetsChanged
-                || mStableInsetsChanged
+        if (didFrameInsetsChange
                 || winAnimator.mSurfaceResized
-                || mOutsetsChanged
-                || mFrameSizeChanged
-                || mDisplayCutoutChanged
                 || configChanged
                 || dragResizingChanged
                 || mReportOrientationChanged) {
             if (DEBUG_RESIZE || DEBUG_ORIENTATION) {
                 Slog.v(TAG_WM, "Resize reasons for w=" + this + ": "
-                        + " contentInsetsChanged=" + mContentInsetsChanged
-                        + " " + mContentInsets.toShortString()
-                        + " visibleInsetsChanged=" + mVisibleInsetsChanged
-                        + " " + mVisibleInsets.toShortString()
-                        + " stableInsetsChanged=" + mStableInsetsChanged
-                        + " " + mStableInsets.toShortString()
-                        + " outsetsChanged=" + mOutsetsChanged
-                        + " " + mOutsets.toShortString()
+                        + " " + mWindowFrames.getInsetsChangedInfo()
                         + " surfaceResized=" + winAnimator.mSurfaceResized
                         + " configChanged=" + configChanged
                         + " dragResizingChanged=" + dragResizingChanged
-                        + " reportOrientationChanged=" + mReportOrientationChanged
-                        + " displayCutoutChanged=" + mDisplayCutoutChanged);
+                        + " reportOrientationChanged=" + mReportOrientationChanged);
             }
 
             // If it's a dead window left on screen, and the configuration changed, there is nothing
@@ -3014,7 +2881,7 @@
         Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "wm.reportResized_" + getWindowTag());
         try {
             if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG, "Reporting new frame to " + this
-                    + ": " + mCompatFrame);
+                    + ": " + mWindowFrames.mCompatFrame);
             final MergedConfiguration mergedConfiguration =
                     new MergedConfiguration(mService.mRoot.getConfiguration(),
                     getMergedOverrideConfiguration());
@@ -3025,11 +2892,11 @@
                 Slog.i(TAG, "Resizing " + this + " WITH DRAW PENDING");
 
             final Rect frame = mWindowFrames.mFrame;
-            final Rect overscanInsets = mLastOverscanInsets;
-            final Rect contentInsets = mLastContentInsets;
-            final Rect visibleInsets = mLastVisibleInsets;
-            final Rect stableInsets = mLastStableInsets;
-            final Rect outsets = mLastOutsets;
+            final Rect overscanInsets = mWindowFrames.mLastOverscanInsets;
+            final Rect contentInsets = mWindowFrames.mLastContentInsets;
+            final Rect visibleInsets = mWindowFrames.mLastVisibleInsets;
+            final Rect stableInsets = mWindowFrames.mLastStableInsets;
+            final Rect outsets = mWindowFrames.mLastOutsets;
             final boolean reportDraw = mWinAnimator.mDrawState == DRAW_PENDING;
             final boolean reportOrientation = mReportOrientationChanged;
             final int displayId = getDisplayId();
@@ -3060,13 +2927,7 @@
                 mService.mAccessibilityController.onSomeWindowResizedOrMovedLocked();
             }
 
-            mOverscanInsetsChanged = false;
-            mContentInsetsChanged = false;
-            mVisibleInsetsChanged = false;
-            mStableInsetsChanged = false;
-            mOutsetsChanged = false;
-            mFrameSizeChanged = false;
-            mDisplayCutoutChanged = false;
+            mWindowFrames.resetInsetsChanged();
             mWinAnimator.mSurfaceResized = false;
             mReportOrientationChanged = false;
         } catch (RemoteException e) {
@@ -3292,7 +3153,6 @@
         mAttrs.writeToProto(proto, ATTRIBUTES);
         mGivenContentInsets.writeToProto(proto, GIVEN_CONTENT_INSETS);
         mWindowFrames.writeToProto(proto, WINDOW_FRAMES);
-        mContentInsets.writeToProto(proto, CONTENT_INSETS);
         mAttrs.surfaceInsets.writeToProto(proto, SURFACE_INSETS);
         mSurfacePosition.writeToProto(proto, SURFACE_POSITION);
         mWinAnimator.writeToProto(proto, ANIMATOR);
@@ -3306,10 +3166,6 @@
         proto.write(SYSTEM_UI_VISIBILITY, mSystemUiVisibility);
         proto.write(HAS_SURFACE, mHasSurface);
         proto.write(IS_READY_FOR_DISPLAY, isReadyForDisplay());
-        mOverscanInsets.writeToProto(proto, OVERSCAN_INSETS);
-        mVisibleInsets.writeToProto(proto, VISIBLE_INSETS);
-        mStableInsets.writeToProto(proto, STABLE_INSETS);
-        mOutsets.writeToProto(proto, OUTSETS);
         proto.write(REMOVE_ON_EXIT, mRemoveOnExit);
         proto.write(DESTROYING, mDestroying);
         proto.write(REMOVED, mRemoved);
@@ -3336,183 +3192,150 @@
     @Override
     void dump(PrintWriter pw, String prefix, boolean dumpAll) {
         final TaskStack stack = getStack();
-        pw.print(prefix); pw.print("mDisplayId="); pw.print(getDisplayId());
-                if (stack != null) {
-                    pw.print(" stackId="); pw.print(stack.mStackId);
-                }
-                pw.print(" mSession="); pw.print(mSession);
-                pw.print(" mClient="); pw.println(mClient.asBinder());
-        pw.print(prefix); pw.print("mOwnerUid="); pw.print(mOwnerUid);
-                pw.print(" mShowToOwnerOnly="); pw.print(mShowToOwnerOnly);
-                pw.print(" package="); pw.print(mAttrs.packageName);
-                pw.print(" appop="); pw.println(AppOpsManager.opToName(mAppOp));
-        pw.print(prefix); pw.print("mAttrs="); pw.println(mAttrs.toString(prefix));
-        pw.print(prefix); pw.print("Requested w="); pw.print(mRequestedWidth);
-                pw.print(" h="); pw.print(mRequestedHeight);
-                pw.print(" mLayoutSeq="); pw.println(mLayoutSeq);
+        pw.print(prefix + "mDisplayId=" + getDisplayId());
+        if (stack != null) {
+            pw.print(" stackId=" + stack.mStackId);
+        }
+        pw.println(" mSession=" + mSession
+                + " mClient=" + mClient.asBinder());
+        pw.println(prefix + "mOwnerUid=" + mOwnerUid
+                + " mShowToOwnerOnly=" + mShowToOwnerOnly
+                + " package=" + mAttrs.packageName
+                + " appop=" + AppOpsManager.opToName(mAppOp));
+        pw.println(prefix + "mAttrs=" + mAttrs.toString(prefix));
+        pw.println(prefix + "Requested w=" + mRequestedWidth
+                + " h=" + mRequestedHeight
+                + " mLayoutSeq=" + mLayoutSeq);
         if (mRequestedWidth != mLastRequestedWidth || mRequestedHeight != mLastRequestedHeight) {
-            pw.print(prefix); pw.print("LastRequested w="); pw.print(mLastRequestedWidth);
-                    pw.print(" h="); pw.println(mLastRequestedHeight);
+            pw.println(prefix + "LastRequested w=" + mLastRequestedWidth
+                    + " h=" + mLastRequestedHeight);
         }
         if (mIsChildWindow || mLayoutAttached) {
-            pw.print(prefix); pw.print("mParentWindow="); pw.print(getParentWindow());
-                    pw.print(" mLayoutAttached="); pw.println(mLayoutAttached);
+            pw.println(prefix + "mParentWindow=" + getParentWindow()
+                    + " mLayoutAttached=" + mLayoutAttached);
         }
         if (mIsImWindow || mIsWallpaper || mIsFloatingLayer) {
-            pw.print(prefix); pw.print("mIsImWindow="); pw.print(mIsImWindow);
-                    pw.print(" mIsWallpaper="); pw.print(mIsWallpaper);
-                    pw.print(" mIsFloatingLayer="); pw.print(mIsFloatingLayer);
-                    pw.print(" mWallpaperVisible="); pw.println(mWallpaperVisible);
+            pw.println(prefix + "mIsImWindow=" + mIsImWindow
+                    + " mIsWallpaper=" + mIsWallpaper
+                    + " mIsFloatingLayer=" + mIsFloatingLayer
+                    + " mWallpaperVisible=" + mWallpaperVisible);
         }
         if (dumpAll) {
-            pw.print(prefix); pw.print("mBaseLayer="); pw.print(mBaseLayer);
-                    pw.print(" mSubLayer="); pw.print(mSubLayer);
-                    pw.print(" mAnimLayer="); pw.print(mLayer); pw.print("+");
-                    pw.print("="); pw.print(mWinAnimator.mAnimLayer);
-                    pw.print(" mLastLayer="); pw.println(mWinAnimator.mLastLayer);
+            pw.println(prefix + "mBaseLayer=" + mBaseLayer
+                    + " mSubLayer=" + mSubLayer
+                    + " mAnimLayer=" + mLayer + "=" + mWinAnimator.mAnimLayer
+                    + " mLastLayer=" + mWinAnimator.mLastLayer);
         }
         if (dumpAll) {
-            pw.print(prefix); pw.print("mToken="); pw.println(mToken);
+            pw.println(prefix + "mToken=" + mToken);
             if (mAppToken != null) {
-                pw.print(prefix); pw.print("mAppToken="); pw.println(mAppToken);
-                pw.print(prefix); pw.print(" isAnimatingWithSavedSurface()=");
-                pw.print(" mAppDied=");pw.print(mAppDied);
-                pw.print(prefix); pw.print("drawnStateEvaluated=");
-                        pw.print(getDrawnStateEvaluated());
-                pw.print(prefix); pw.print("mightAffectAllDrawn=");
-                        pw.println(mightAffectAllDrawn());
+                pw.println(prefix + "mAppToken=" + mAppToken);
+                pw.print(prefix + "mAppDied=" + mAppDied);
+                pw.print(prefix + "drawnStateEvaluated=" + getDrawnStateEvaluated());
+                pw.println(prefix + "mightAffectAllDrawn=" + mightAffectAllDrawn());
             }
-            pw.print(prefix); pw.print("mViewVisibility=0x");
-            pw.print(Integer.toHexString(mViewVisibility));
-            pw.print(" mHaveFrame="); pw.print(mHaveFrame);
-            pw.print(" mObscured="); pw.println(mObscured);
-            pw.print(prefix); pw.print("mSeq="); pw.print(mSeq);
-            pw.print(" mSystemUiVisibility=0x");
-            pw.println(Integer.toHexString(mSystemUiVisibility));
+            pw.println(prefix + "mViewVisibility=0x" + Integer.toHexString(mViewVisibility)
+                    + " mHaveFrame=" + mHaveFrame
+                    + " mObscured=" + mObscured);
+            pw.println(prefix + "mSeq=" + mSeq
+                    + " mSystemUiVisibility=0x" + Integer.toHexString(mSystemUiVisibility));
         }
         if (!mPolicyVisibility || !mPolicyVisibilityAfterAnim || !mAppOpVisibility
-                || isParentWindowHidden()|| mPermanentlyHidden || mForceHideNonSystemOverlayWindow
+                || isParentWindowHidden() || mPermanentlyHidden || mForceHideNonSystemOverlayWindow
                 || mHiddenWhileSuspended) {
-            pw.print(prefix); pw.print("mPolicyVisibility=");
-                    pw.print(mPolicyVisibility);
-                    pw.print(" mPolicyVisibilityAfterAnim=");
-                    pw.print(mPolicyVisibilityAfterAnim);
-                    pw.print(" mAppOpVisibility=");
-                    pw.print(mAppOpVisibility);
-                    pw.print(" parentHidden="); pw.print(isParentWindowHidden());
-                    pw.print(" mPermanentlyHidden="); pw.print(mPermanentlyHidden);
-                    pw.print(" mHiddenWhileSuspended="); pw.print(mHiddenWhileSuspended);
-                    pw.print(" mForceHideNonSystemOverlayWindow="); pw.println(
-                    mForceHideNonSystemOverlayWindow);
+            pw.println(prefix + "mPolicyVisibility=" + mPolicyVisibility
+                    + " mPolicyVisibilityAfterAnim=" + mPolicyVisibilityAfterAnim
+                    + " mAppOpVisibility=" + mAppOpVisibility
+                    + " parentHidden=" + isParentWindowHidden()
+                    + " mPermanentlyHidden=" + mPermanentlyHidden
+                    + " mHiddenWhileSuspended=" + mHiddenWhileSuspended
+                    + " mForceHideNonSystemOverlayWindow=" + mForceHideNonSystemOverlayWindow);
         }
         if (!mRelayoutCalled || mLayoutNeeded) {
-            pw.print(prefix); pw.print("mRelayoutCalled="); pw.print(mRelayoutCalled);
-                    pw.print(" mLayoutNeeded="); pw.println(mLayoutNeeded);
+            pw.println(prefix + "mRelayoutCalled=" + mRelayoutCalled
+                    + " mLayoutNeeded=" + mLayoutNeeded);
         }
         if (dumpAll) {
-            pw.print(prefix); pw.print("mGivenContentInsets=");
-                    mGivenContentInsets.printShortString(pw);
-                    pw.print(" mGivenVisibleInsets=");
-                    mGivenVisibleInsets.printShortString(pw);
-                    pw.println();
+            pw.println(prefix + "mGivenContentInsets=" + mGivenContentInsets.toShortString(sTmpSB)
+                    + " mGivenVisibleInsets=" + mGivenVisibleInsets.toShortString(sTmpSB));
             if (mTouchableInsets != 0 || mGivenInsetsPending) {
-                pw.print(prefix); pw.print("mTouchableInsets="); pw.print(mTouchableInsets);
-                        pw.print(" mGivenInsetsPending="); pw.println(mGivenInsetsPending);
+                pw.println(prefix + "mTouchableInsets=" + mTouchableInsets
+                        + " mGivenInsetsPending=" + mGivenInsetsPending);
                 Region region = new Region();
                 getTouchableRegion(region);
-                pw.print(prefix); pw.print("touchable region="); pw.println(region);
+                pw.println(prefix + "touchable region=" + region);
             }
-            pw.print(prefix); pw.print("mFullConfiguration="); pw.println(getConfiguration());
-            pw.print(prefix); pw.print("mLastReportedConfiguration=");
-                    pw.println(getLastReportedConfiguration());
+            pw.println(prefix + "mFullConfiguration=" + getConfiguration());
+            pw.println(prefix + "mLastReportedConfiguration=" + getLastReportedConfiguration());
         }
-        pw.print(prefix); pw.print("mHasSurface="); pw.print(mHasSurface);
-                pw.print(" isReadyForDisplay()="); pw.print(isReadyForDisplay());
-                pw.print(" mWindowRemovalAllowed="); pw.println(mWindowRemovalAllowed);
+        pw.println(prefix + "mHasSurface=" + mHasSurface
+                + " isReadyForDisplay()=" + isReadyForDisplay()
+                + " mWindowRemovalAllowed=" + mWindowRemovalAllowed);
         if (mEnforceSizeCompat) {
-            pw.print(prefix); pw.print("mCompatFrame="); mCompatFrame.printShortString(pw);
-                    pw.println();
+            pw.println(prefix + "mCompatFrame=" + mWindowFrames.mCompatFrame.toShortString(sTmpSB));
         }
         if (dumpAll) {
             mWindowFrames.dump(pw, prefix);
-            pw.print(prefix); pw.print("Cur insets: overscan=");
-                    mOverscanInsets.printShortString(pw);
-                    pw.print(" content="); mContentInsets.printShortString(pw);
-                    pw.print(" visible="); mVisibleInsets.printShortString(pw);
-                    pw.print(" stable="); mStableInsets.printShortString(pw);
-                    pw.print(" surface="); mAttrs.surfaceInsets.printShortString(pw);
-                    pw.print(" outsets="); mOutsets.printShortString(pw);
-            pw.print(prefix); pw.print("Lst insets: overscan=");
-                    mLastOverscanInsets.printShortString(pw);
-                    pw.print(" content="); mLastContentInsets.printShortString(pw);
-                    pw.print(" visible="); mLastVisibleInsets.printShortString(pw);
-                    pw.print(" stable="); mLastStableInsets.printShortString(pw);
-                    pw.print(" physical="); mLastOutsets.printShortString(pw);
-                    pw.print(" outset="); mLastOutsets.printShortString(pw);
-                    pw.println();
+            pw.println(prefix + " surface=" + mAttrs.surfaceInsets.toShortString(sTmpSB));
         }
         super.dump(pw, prefix, dumpAll);
-        pw.print(prefix); pw.print(mWinAnimator); pw.println(":");
+        pw.println(prefix + mWinAnimator + ":");
         mWinAnimator.dump(pw, prefix + "  ", dumpAll);
         if (mAnimatingExit || mRemoveOnExit || mDestroying || mRemoved) {
-            pw.print(prefix); pw.print("mAnimatingExit="); pw.print(mAnimatingExit);
-                    pw.print(" mRemoveOnExit="); pw.print(mRemoveOnExit);
-                    pw.print(" mDestroying="); pw.print(mDestroying);
-                    pw.print(" mRemoved="); pw.println(mRemoved);
+            pw.println(prefix + "mAnimatingExit=" + mAnimatingExit
+                    + " mRemoveOnExit=" + mRemoveOnExit
+                    + " mDestroying=" + mDestroying
+                    + " mRemoved=" + mRemoved);
         }
         if (getOrientationChanging() || mAppFreezing || mReportOrientationChanged) {
-            pw.print(prefix); pw.print("mOrientationChanging=");
-                    pw.print(mOrientationChanging);
-                    pw.print(" configOrientationChanging=");
-                    pw.print(getLastReportedConfiguration().orientation
-                            != getConfiguration().orientation);
-                    pw.print(" mAppFreezing="); pw.print(mAppFreezing);
-                    pw.print(" mReportOrientationChanged="); pw.println(mReportOrientationChanged);
+            pw.println(prefix + "mOrientationChanging=" + mOrientationChanging
+                    + " configOrientationChanging="
+                    + (getLastReportedConfiguration().orientation != getConfiguration().orientation)
+                    + " mAppFreezing=" + mAppFreezing
+                    + " mReportOrientationChanged=" + mReportOrientationChanged);
         }
         if (mLastFreezeDuration != 0) {
-            pw.print(prefix); pw.print("mLastFreezeDuration=");
-                    TimeUtils.formatDuration(mLastFreezeDuration, pw); pw.println();
+            pw.print(prefix + "mLastFreezeDuration=");
+            TimeUtils.formatDuration(mLastFreezeDuration, pw);
+            pw.println();
         }
-        pw.print(prefix); pw.print("mForceSeamlesslyRotate="); pw.print(mForceSeamlesslyRotate);
-        pw.print(" seamlesslyRotate: pending=");
+        pw.print(prefix + "mForceSeamlesslyRotate=" + mForceSeamlesslyRotate
+                + " seamlesslyRotate: pending=");
         if (mPendingSeamlessRotate != null) {
             mPendingSeamlessRotate.dump(pw);
         } else {
             pw.print("null");
         }
-        pw.print(" finishedFrameNumber="); pw.print(mFinishSeamlessRotateFrameNumber);
-        pw.println();
+        pw.println(" finishedFrameNumber=" + mFinishSeamlessRotateFrameNumber);
 
         if (mHScale != 1 || mVScale != 1) {
-            pw.print(prefix); pw.print("mHScale="); pw.print(mHScale);
-                    pw.print(" mVScale="); pw.println(mVScale);
+            pw.println(prefix + "mHScale=" + mHScale
+                    + " mVScale=" + mVScale);
         }
         if (mWallpaperX != -1 || mWallpaperY != -1) {
-            pw.print(prefix); pw.print("mWallpaperX="); pw.print(mWallpaperX);
-                    pw.print(" mWallpaperY="); pw.println(mWallpaperY);
+            pw.println(prefix + "mWallpaperX=" + mWallpaperX
+                    + " mWallpaperY=" + mWallpaperY);
         }
         if (mWallpaperXStep != -1 || mWallpaperYStep != -1) {
-            pw.print(prefix); pw.print("mWallpaperXStep="); pw.print(mWallpaperXStep);
-                    pw.print(" mWallpaperYStep="); pw.println(mWallpaperYStep);
+            pw.println(prefix + "mWallpaperXStep=" + mWallpaperXStep
+                    + " mWallpaperYStep=" + mWallpaperYStep);
         }
         if (mWallpaperDisplayOffsetX != Integer.MIN_VALUE
                 || mWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
-            pw.print(prefix); pw.print("mWallpaperDisplayOffsetX=");
-                    pw.print(mWallpaperDisplayOffsetX);
-                    pw.print(" mWallpaperDisplayOffsetY=");
-                    pw.println(mWallpaperDisplayOffsetY);
+            pw.println(prefix + "mWallpaperDisplayOffsetX=" + mWallpaperDisplayOffsetX
+                    + " mWallpaperDisplayOffsetY=" + mWallpaperDisplayOffsetY);
         }
         if (mDrawLock != null) {
-            pw.print(prefix); pw.println("mDrawLock=" + mDrawLock);
+            pw.println(prefix + "mDrawLock=" + mDrawLock);
         }
         if (isDragResizing()) {
-            pw.print(prefix); pw.println("isDragResizing=" + isDragResizing());
+            pw.println(prefix + "isDragResizing=" + isDragResizing());
         }
         if (computeDragResizing()) {
-            pw.print(prefix); pw.println("computeDragResizing=" + computeDragResizing());
+            pw.println(prefix + "computeDragResizing=" + computeDragResizing());
         }
-        pw.print(prefix); pw.println("isOnScreen=" + isOnScreen());
-        pw.print(prefix); pw.println("isVisible=" + isVisible());
+        pw.println(prefix + "isOnScreen=" + isOnScreen());
+        pw.println(prefix + "isVisible=" + isVisible());
     }
 
     @Override
@@ -3553,7 +3376,7 @@
         }
     }
 
-    void applyGravityAndUpdateFrame(Rect containingFrame, Rect displayFrame) {
+    private void applyGravityAndUpdateFrame(Rect containingFrame, Rect displayFrame) {
         final int pw = containingFrame.width();
         final int ph = containingFrame.height();
         final Task task = getTask();
@@ -3631,10 +3454,10 @@
 
         // 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(mWindowFrames.mFrame);
+        mWindowFrames.mCompatFrame.set(mWindowFrames.mFrame);
         if (mEnforceSizeCompat) {
             // See comparable block in computeFrameLw.
-            mCompatFrame.scale(mInvGlobalScale);
+            mWindowFrames.mCompatFrame.scale(mInvGlobalScale);
         }
     }
 
@@ -3911,6 +3734,8 @@
         windowInfo.focused = isFocused();
         Task task = getTask();
         windowInfo.inPictureInPicture = (task != null) && task.inPinnedWindowingMode();
+        windowInfo.hasFlagWatchOutsideTouch =
+                (mAttrs.flags & WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH) != 0;
 
         if (mIsChildWindow) {
             windowInfo.parentToken = getParentWindow().mClient.asBinder();
@@ -4344,13 +4169,15 @@
             // On a different display there is no system decor. Crop the window
             // by the screen boundaries.
             // TODO(multi-display)
-            policyCrop.set(0, 0, mCompatFrame.width(), mCompatFrame.height());
-            policyCrop.intersect(-mCompatFrame.left, -mCompatFrame.top,
-                    displayInfo.logicalWidth - mCompatFrame.left,
-                    displayInfo.logicalHeight - mCompatFrame.top);
+            policyCrop.set(0, 0, mWindowFrames.mCompatFrame.width(),
+                    mWindowFrames.mCompatFrame.height());
+            policyCrop.intersect(-mWindowFrames.mCompatFrame.left, -mWindowFrames.mCompatFrame.top,
+                    displayInfo.logicalWidth - mWindowFrames.mCompatFrame.left,
+                    displayInfo.logicalHeight - mWindowFrames.mCompatFrame.top);
         } else if (skipDecorCrop()) {
             // Windows without policy decor aren't cropped.
-            policyCrop.set(0, 0, mCompatFrame.width(), mCompatFrame.height());
+            policyCrop.set(0, 0, mWindowFrames.mCompatFrame.width(),
+                    mWindowFrames.mCompatFrame.height());
         } else {
             // Crop to the system decor specified by policy.
             calculateSystemDecorRect(policyCrop);
@@ -4508,12 +4335,7 @@
      * Updates the last inset values to the current ones.
      */
     void updateLastInsetValues() {
-        mLastOverscanInsets.set(mOverscanInsets);
-        mLastContentInsets.set(mContentInsets);
-        mLastVisibleInsets.set(mVisibleInsets);
-        mLastStableInsets.set(mStableInsets);
-        mLastOutsets.set(mOutsets);
-        mWindowFrames.mLastDisplayCutout = mWindowFrames.mDisplayCutout;
+        mWindowFrames.updateLastInsetValues();
     }
 
     void startAnimation(Animation anim) {
@@ -4902,6 +4724,44 @@
         }
     }
 
+    /**
+     * Copy the inset values over so they can be sent back to the client when a relayout occurs.
+     */
+    void getInsetsForRelayout(Rect outOverscanInsets, Rect outContentInsets, Rect outVisibleInsets,
+            Rect outStableInsets, Rect outOutsets) {
+        outOverscanInsets.set(mWindowFrames.mOverscanInsets);
+        outContentInsets.set(mWindowFrames.mContentInsets);
+        outVisibleInsets.set(mWindowFrames.mVisibleInsets);
+        outStableInsets.set(mWindowFrames.mStableInsets);
+        outOutsets.set(mWindowFrames.mOutsets);
+
+        mLastRelayoutContentInsets.set(mWindowFrames.mContentInsets);
+    }
+
+    void getContentInsets(Rect outContentInsets) {
+        outContentInsets.set(mWindowFrames.mContentInsets);
+    }
+
+    Rect getContentInsets() {
+        return mWindowFrames.mContentInsets;
+    }
+
+    void getStableInsets(Rect outStableInsets) {
+        outStableInsets.set(mWindowFrames.mStableInsets);
+    }
+
+    Rect getStableInsets() {
+        return mWindowFrames.mStableInsets;
+    }
+
+    void resetLastContentInsets() {
+        mWindowFrames.resetLastContentInsets();
+    }
+
+    Rect getVisibleInsets() {
+        return mWindowFrames.mVisibleInsets;
+    }
+
     private final class MoveAnimationSpec implements AnimationSpec {
 
         private final long mDuration;
@@ -4934,9 +4794,9 @@
 
         @Override
         public void dump(PrintWriter pw, String prefix) {
-            pw.print(prefix); pw.print("from="); pw.print(mFrom);
-            pw.print(" to="); pw.print(mTo);
-            pw.print(" duration="); pw.println(mDuration);
+            pw.println(prefix + "from=" + mFrom
+                    + " to=" + mTo
+                    + " duration=" + mDuration);
         }
 
         @Override
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index b158ae2..fec8039 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -24,6 +24,7 @@
 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
 import static android.view.WindowManager.TRANSIT_NONE;
+
 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
 import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_FREEFORM;
@@ -46,7 +47,6 @@
 import static com.android.server.wm.WindowStateAnimatorProto.SURFACE;
 import static com.android.server.wm.WindowStateAnimatorProto.SYSTEM_DECOR_RECT;
 import static com.android.server.wm.WindowSurfacePlacer.SET_ORIENTATION_CHANGE_COMPLETE;
-import static com.android.server.wm.utils.CoordinateTransforms.transformToRotation;
 
 import android.content.Context;
 import android.graphics.Matrix;
@@ -476,8 +476,7 @@
             flags |= SurfaceControl.SECURE;
         }
 
-        mTmpSize.set(0, 0, 0, 0);
-        calculateSurfaceBounds(w, attrs);
+        calculateSurfaceBounds(w, attrs, mTmpSize);
         final int width = mTmpSize.width();
         final int height = mTmpSize.height();
 
@@ -556,44 +555,38 @@
         return mSurfaceController;
     }
 
-    private void calculateSurfaceBounds(WindowState w, LayoutParams attrs) {
+    private void calculateSurfaceBounds(WindowState w, LayoutParams attrs, Rect outSize) {
+        outSize.setEmpty();
         if ((attrs.flags & FLAG_SCALED) != 0) {
             // For a scaled surface, we always want the requested size.
-            mTmpSize.right = mTmpSize.left + w.mRequestedWidth;
-            mTmpSize.bottom = mTmpSize.top + w.mRequestedHeight;
+            outSize.right = w.mRequestedWidth;
+            outSize.bottom = w.mRequestedHeight;
         } else {
             // When we're doing a drag-resizing, request a surface that's fullscreen size,
             // so that we don't need to reallocate during the process. This also prevents
             // buffer drops due to size mismatch.
             if (w.isDragResizing()) {
-                if (w.getResizeMode() == DRAG_RESIZE_MODE_FREEFORM) {
-                    mTmpSize.left = 0;
-                    mTmpSize.top = 0;
-                }
                 final DisplayInfo displayInfo = w.getDisplayInfo();
-                mTmpSize.right = mTmpSize.left + displayInfo.logicalWidth;
-                mTmpSize.bottom = mTmpSize.top + displayInfo.logicalHeight;
+                outSize.right = displayInfo.logicalWidth;
+                outSize.bottom = displayInfo.logicalHeight;
             } else {
-                mTmpSize.right = mTmpSize.left + w.mCompatFrame.width();
-                mTmpSize.bottom = mTmpSize.top + w.mCompatFrame.height();
+                w.getCompatFrameSize(outSize);
             }
         }
 
         // Something is wrong and SurfaceFlinger will not like this, try to revert to sane values.
         // This doesn't necessarily mean that there is an error in the system. The sizes might be
         // incorrect, because it is before the first layout or draw.
-        if (mTmpSize.width() < 1) {
-            mTmpSize.right = mTmpSize.left + 1;
+        if (outSize.width() < 1) {
+            outSize.right = 1;
         }
-        if (mTmpSize.height() < 1) {
-            mTmpSize.bottom = mTmpSize.top + 1;
+        if (outSize.height() < 1) {
+            outSize.bottom = 1;
         }
 
         // Adjust for surface insets.
-        mTmpSize.left -= attrs.surfaceInsets.left;
-        mTmpSize.top -= attrs.surfaceInsets.top;
-        mTmpSize.right += attrs.surfaceInsets.right;
-        mTmpSize.bottom += attrs.surfaceInsets.bottom;
+        outSize.inset(-attrs.surfaceInsets.left, -attrs.surfaceInsets.top,
+                -attrs.surfaceInsets.right, -attrs.surfaceInsets.bottom);
     }
 
     boolean hasSurface() {
@@ -870,8 +863,7 @@
         final LayoutParams attrs = mWin.getAttrs();
         final Task task = w.getTask();
 
-        mTmpSize.set(0, 0, 0, 0);
-        calculateSurfaceBounds(w, attrs);
+        calculateSurfaceBounds(w, attrs, mTmpSize);
 
         mExtraHScale = (float) 1.0;
         mExtraVScale = (float) 1.0;
@@ -1070,7 +1062,8 @@
         // comes in at the new size (normally position and crop are unfrozen).
         // setGeometryAppliesWithResizeInTransaction accomplishes this for us.
         if (wasForceScaled && !mForceScaleUntilResize) {
-            mSurfaceController.setGeometryAppliesWithResizeInTransaction(true);
+            mSurfaceController.deferTransactionUntil(mSurfaceController.getHandle(),
+                    mWin.getFrameNumber());
             mSurfaceController.forceScaleableInTransaction(false);
         }
 
diff --git a/services/core/jni/com_android_server_UsbDescriptorParser.cpp b/services/core/jni/com_android_server_UsbDescriptorParser.cpp
index 62bab07..d29d3fc 100644
--- a/services/core/jni/com_android_server_UsbDescriptorParser.cpp
+++ b/services/core/jni/com_android_server_UsbDescriptorParser.cpp
@@ -25,6 +25,7 @@
 #include <usbhost/usbhost.h>
 
 #define MAX_DESCRIPTORS_LENGTH 4096
+static const int USB_CONTROL_TRANSFER_TIMEOUT_MS = 200;
 
 // com.android.server.usb.descriptors
 extern "C" {
@@ -85,8 +86,9 @@
     jbyte* byteBuffer = NULL;
     size_t numUSC2Bytes = 0;
     int retVal =
-            usb_device_get_string_ucs2(device, stringId, 0 /*timeout*/,
-                                     (void**)&byteBuffer, &numUSC2Bytes);
+            usb_device_get_string_ucs2(device, stringId,
+                                       USB_CONTROL_TRANSFER_TIMEOUT_MS,
+                                       (void**)&byteBuffer, &numUSC2Bytes);
 
     jstring j_str = NULL;
 
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index 52f2d67..42ade38 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -210,7 +210,7 @@
             const sp<InputWindowHandle>& inputWindowHandle, bool monitor);
     status_t unregisterInputChannel(JNIEnv* env, const sp<InputChannel>& inputChannel);
 
-    void setInputWindows(JNIEnv* env, jobjectArray windowHandleObjArray);
+    void setInputWindows(JNIEnv* env, jobjectArray windowHandleObjArray, int32_t displayId);
     void setFocusedApplication(JNIEnv* env, jobject applicationHandleObj);
     void setInputDispatchMode(bool enabled, bool frozen);
     void setSystemUiVisibility(int32_t visibility);
@@ -230,11 +230,11 @@
     virtual sp<PointerControllerInterface> obtainPointerController(int32_t deviceId);
     virtual void notifyInputDevicesChanged(const Vector<InputDeviceInfo>& inputDevices);
     virtual sp<KeyCharacterMap> getKeyboardLayoutOverlay(const InputDeviceIdentifier& identifier);
-    virtual String8 getDeviceAlias(const InputDeviceIdentifier& identifier);
+    virtual std::string getDeviceAlias(const InputDeviceIdentifier& identifier);
     virtual TouchAffineTransformation getTouchAffineTransformation(JNIEnv *env,
             jfloatArray matrixArr);
     virtual TouchAffineTransformation getTouchAffineTransformation(
-            const String8& inputDeviceDescriptor, int32_t surfaceRotation);
+            const std::string& inputDeviceDescriptor, int32_t surfaceRotation);
 
     /* --- InputDispatcherPolicyInterface implementation --- */
 
@@ -480,7 +480,7 @@
         for (jsize i = 0; i < length; i++) {
             jstring item = jstring(env->GetObjectArrayElement(excludedDeviceNames, i));
             const char* deviceNameChars = env->GetStringUTFChars(item, NULL);
-            outConfig->excludedDeviceNames.add(String8(deviceNameChars));
+            outConfig->excludedDeviceNames.push_back(deviceNameChars);
             env->ReleaseStringUTFChars(item, deviceNameChars);
             env->DeleteLocalRef(item);
         }
@@ -606,7 +606,7 @@
     JNIEnv* env = jniEnv();
 
     sp<KeyCharacterMap> result;
-    ScopedLocalRef<jstring> descriptor(env, env->NewStringUTF(identifier.descriptor.string()));
+    ScopedLocalRef<jstring> descriptor(env, env->NewStringUTF(identifier.descriptor.c_str()));
     ScopedLocalRef<jobject> identifierObj(env, env->NewObject(gInputDeviceIdentifierInfo.clazz,
             gInputDeviceIdentifierInfo.constructor, descriptor.get(),
             identifier.vendor, identifier.product));
@@ -620,24 +620,24 @@
         ScopedUtfChars filenameChars(env, filenameObj.get());
         ScopedUtfChars contentsChars(env, contentsObj.get());
 
-        KeyCharacterMap::loadContents(String8(filenameChars.c_str()),
-                String8(contentsChars.c_str()), KeyCharacterMap::FORMAT_OVERLAY, &result);
+        KeyCharacterMap::loadContents(filenameChars.c_str(),
+                contentsChars.c_str(), KeyCharacterMap::FORMAT_OVERLAY, &result);
     }
     checkAndClearExceptionFromCallback(env, "getKeyboardLayoutOverlay");
     return result;
 }
 
-String8 NativeInputManager::getDeviceAlias(const InputDeviceIdentifier& identifier) {
+std::string NativeInputManager::getDeviceAlias(const InputDeviceIdentifier& identifier) {
     ATRACE_CALL();
     JNIEnv* env = jniEnv();
 
-    ScopedLocalRef<jstring> uniqueIdObj(env, env->NewStringUTF(identifier.uniqueId.string()));
+    ScopedLocalRef<jstring> uniqueIdObj(env, env->NewStringUTF(identifier.uniqueId.c_str()));
     ScopedLocalRef<jstring> aliasObj(env, jstring(env->CallObjectMethod(mServiceObj,
             gServiceClassInfo.getDeviceAlias, uniqueIdObj.get())));
-    String8 result;
+    std::string result;
     if (aliasObj.get()) {
         ScopedUtfChars aliasChars(env, aliasObj.get());
-        result.setTo(aliasChars.c_str());
+        result = aliasChars.c_str();
     }
     checkAndClearExceptionFromCallback(env, "getDeviceAlias");
     return result;
@@ -736,7 +736,8 @@
     }
 }
 
-void NativeInputManager::setInputWindows(JNIEnv* env, jobjectArray windowHandleObjArray) {
+void NativeInputManager::setInputWindows(JNIEnv* env, jobjectArray windowHandleObjArray,
+         int32_t displayId) {
     Vector<sp<InputWindowHandle> > windowHandles;
 
     if (windowHandleObjArray) {
@@ -756,7 +757,7 @@
         }
     }
 
-    mInputManager->getDispatcher()->setInputWindows(windowHandles);
+    mInputManager->getDispatcher()->setInputWindows(windowHandles, displayId);
 
     // Do this after the dispatcher has updated the window handle state.
     bool newPointerGesturesEnabled = true;
@@ -932,10 +933,10 @@
 }
 
 TouchAffineTransformation NativeInputManager::getTouchAffineTransformation(
-        const String8& inputDeviceDescriptor, int32_t surfaceRotation) {
+        const std::string& inputDeviceDescriptor, int32_t surfaceRotation) {
     JNIEnv* env = jniEnv();
 
-    ScopedLocalRef<jstring> descriptorObj(env, env->NewStringUTF(inputDeviceDescriptor.string()));
+    ScopedLocalRef<jstring> descriptorObj(env, env->NewStringUTF(inputDeviceDescriptor.c_str()));
 
     jobject cal = env->CallObjectMethod(mServiceObj,
             gServiceClassInfo.getTouchCalibrationForInputDevice, descriptorObj.get(),
@@ -1281,7 +1282,7 @@
     v.deviceWidth = deviceWidth;
     v.deviceHeight = deviceHeight;
     if (uniqueId != nullptr) {
-        v.uniqueId.setTo(ScopedUtfChars(env, uniqueId).c_str());
+        v.uniqueId = ScopedUtfChars(env, uniqueId).c_str();
     }
 
     im->setDisplayViewport(viewportType, v);
@@ -1446,10 +1447,10 @@
 }
 
 static void nativeSetInputWindows(JNIEnv* env, jclass /* clazz */,
-        jlong ptr, jobjectArray windowHandleObjArray) {
+        jlong ptr, jobjectArray windowHandleObjArray, jint displayId) {
     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
 
-    im->setInputWindows(env, windowHandleObjArray);
+    im->setInputWindows(env, windowHandleObjArray, displayId);
 }
 
 static void nativeSetFocusedApplication(JNIEnv* env, jclass /* clazz */,
@@ -1678,7 +1679,7 @@
             (void*) nativeInjectInputEvent },
     { "nativeToggleCapsLock", "(JI)V",
             (void*) nativeToggleCapsLock },
-    { "nativeSetInputWindows", "(J[Lcom/android/server/input/InputWindowHandle;)V",
+    { "nativeSetInputWindows", "(J[Lcom/android/server/input/InputWindowHandle;I)V",
             (void*) nativeSetInputWindows },
     { "nativeSetFocusedApplication", "(JLcom/android/server/input/InputApplicationHandle;)V",
             (void*) nativeSetFocusedApplication },
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index c131858..0ca0835 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -114,7 +114,6 @@
 import android.app.admin.SystemUpdateInfo;
 import android.app.admin.SystemUpdatePolicy;
 import android.app.backup.IBackupManager;
-import android.app.backup.ISelectBackupTransportCallback;
 import android.app.trust.TrustManager;
 import android.app.usage.UsageStatsManagerInternal;
 import android.content.BroadcastReceiver;
@@ -262,7 +261,6 @@
 import java.util.Map.Entry;
 import java.util.Objects;
 import java.util.Set;
-import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.function.Function;
@@ -377,6 +375,7 @@
     private static final Set<String> GLOBAL_SETTINGS_WHITELIST;
     private static final Set<String> GLOBAL_SETTINGS_DEPRECATED;
     private static final Set<String> SYSTEM_SETTINGS_WHITELIST;
+    private static final Set<Integer> DA_DISALLOWED_POLICIES;
     static {
         SECURE_SETTINGS_WHITELIST = new ArraySet<>();
         SECURE_SETTINGS_WHITELIST.add(Settings.Secure.DEFAULT_INPUT_METHOD);
@@ -408,6 +407,12 @@
         SYSTEM_SETTINGS_WHITELIST.add(Settings.System.SCREEN_BRIGHTNESS);
         SYSTEM_SETTINGS_WHITELIST.add(Settings.System.SCREEN_BRIGHTNESS_MODE);
         SYSTEM_SETTINGS_WHITELIST.add(Settings.System.SCREEN_OFF_TIMEOUT);
+
+        DA_DISALLOWED_POLICIES = new ArraySet<>();
+        DA_DISALLOWED_POLICIES.add(DeviceAdminInfo.USES_POLICY_DISABLE_CAMERA);
+        DA_DISALLOWED_POLICIES.add(DeviceAdminInfo.USES_POLICY_DISABLE_KEYGUARD_FEATURES);
+        DA_DISALLOWED_POLICIES.add(DeviceAdminInfo.USES_POLICY_EXPIRE_PASSWORD);
+        DA_DISALLOWED_POLICIES.add(DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
     }
 
     /**
@@ -888,7 +893,6 @@
         private static final String ATTR_LAST_NETWORK_LOGGING_NOTIFICATION = "last-notification";
         private static final String ATTR_NUM_NETWORK_LOGGING_NOTIFICATIONS = "num-notifications";
         private static final String TAG_IS_LOGOUT_ENABLED = "is_logout_enabled";
-        private static final String TAG_MANDATORY_BACKUP_TRANSPORT = "mandatory_backup_transport";
         private static final String TAG_START_USER_SESSION_MESSAGE = "start_user_session_message";
         private static final String TAG_END_USER_SESSION_MESSAGE = "end_user_session_message";
         private static final String TAG_METERED_DATA_DISABLED_PACKAGES
@@ -1009,10 +1013,6 @@
         // Default title of confirm credentials screen
         String organizationName = null;
 
-        // The component name of the backup transport which has to be used if backups are mandatory
-        // or null if backups are not mandatory.
-        ComponentName mandatoryBackupTransport = null;
-
         // Message for user switcher
         String startUserSessionMessage = null;
         String endUserSessionMessage = null;
@@ -1276,11 +1276,6 @@
                 out.attribute(null, ATTR_VALUE, Boolean.toString(isLogoutEnabled));
                 out.endTag(null, TAG_IS_LOGOUT_ENABLED);
             }
-            if (mandatoryBackupTransport != null) {
-                out.startTag(null, TAG_MANDATORY_BACKUP_TRANSPORT);
-                out.attribute(null, ATTR_VALUE, mandatoryBackupTransport.flattenToString());
-                out.endTag(null, TAG_MANDATORY_BACKUP_TRANSPORT);
-            }
             if (startUserSessionMessage != null) {
                 out.startTag(null, TAG_START_USER_SESSION_MESSAGE);
                 out.text(startUserSessionMessage);
@@ -1469,9 +1464,6 @@
                 } else if (TAG_IS_LOGOUT_ENABLED.equals(tag)) {
                     isLogoutEnabled = Boolean.parseBoolean(
                             parser.getAttributeValue(null, ATTR_VALUE));
-                } else if (TAG_MANDATORY_BACKUP_TRANSPORT.equals(tag)) {
-                    mandatoryBackupTransport = ComponentName.unflattenFromString(
-                            parser.getAttributeValue(null, ATTR_VALUE));
                 } else if (TAG_START_USER_SESSION_MESSAGE.equals(tag)) {
                     type = parser.next();
                     if (type == XmlPullParser.TEXT) {
@@ -2203,6 +2195,7 @@
      * @return the user password metrics, or {@code null} if none have been associated with
      * the user yet (for example, if the device has booted but not been unlocked).
      */
+    @GuardedBy("getLockObject()")
     PasswordMetrics getUserPasswordMetricsLocked(int userHandle) {
         return mUserPasswordMetrics.get(userHandle);
     }
@@ -2607,6 +2600,9 @@
             final int userId = UserHandle.getUserId(callingUid);
             final DevicePolicyData policy = getUserData(userId);
             ActiveAdmin admin = policy.mAdminMap.get(who);
+            final boolean isDeviceOwner = isDeviceOwner(admin.info.getComponent(), userId);
+            final boolean isProfileOwner = isProfileOwner(admin.info.getComponent(), userId);
+
             if (reqPolicy == DeviceAdminInfo.USES_POLICY_DEVICE_OWNER) {
                 throw new SecurityException("Admin " + admin.info.getComponent()
                          + " does not own the device");
@@ -2615,6 +2611,11 @@
                 throw new SecurityException("Admin " + admin.info.getComponent()
                         + " does not own the profile");
             }
+            if (DA_DISALLOWED_POLICIES.contains(reqPolicy) && !isDeviceOwner && !isProfileOwner) {
+                throw new SecurityException("Admin " + admin.info.getComponent()
+                        + " is not a device owner or profile owner, so may not use policy: "
+                        + admin.info.getTagForPolicy(reqPolicy));
+            }
             throw new SecurityException("Admin " + admin.info.getComponent()
                     + " did not specify uses-policy for: "
                     + admin.info.getTagForPolicy(reqPolicy));
@@ -2694,7 +2695,10 @@
             // DO always has the PO power.
             return ownsDevice || ownsProfile;
         } else {
-            return admin.info.usesPolicy(reqPolicy);
+            boolean allowedToUsePolicy = ownsDevice || ownsProfile
+                    || !DA_DISALLOWED_POLICIES.contains(reqPolicy)
+                    || getTargetSdk(admin.info.getPackageName(), userId) < Build.VERSION_CODES.Q;
+            return allowedToUsePolicy && admin.info.usesPolicy(reqPolicy);
         }
     }
 
@@ -3972,6 +3976,7 @@
      * be the correct one upon boot.
      * This should be called whenever the password or the admin policies have changed.
      */
+    @GuardedBy("getLockObject()")
     private void updatePasswordValidityCheckpointLocked(int userHandle, boolean parent) {
         final int credentialOwner = getCredentialOwner(userHandle, parent);
         DevicePolicyData policy = getUserData(credentialOwner);
@@ -10518,8 +10523,7 @@
         final int userId = UserHandle.getUserId(uid);
         Intent intent = null;
         if (DevicePolicyManager.POLICY_DISABLE_CAMERA.equals(restriction) ||
-                DevicePolicyManager.POLICY_DISABLE_SCREEN_CAPTURE.equals(restriction) ||
-                DevicePolicyManager.POLICY_MANDATORY_BACKUPS.equals(restriction)) {
+                DevicePolicyManager.POLICY_DISABLE_SCREEN_CAPTURE.equals(restriction)) {
             synchronized (getLockObject()) {
                 final DevicePolicyData policy = getUserData(userId);
                 final int N = policy.mAdminList.size();
@@ -10528,9 +10532,7 @@
                     if ((admin.disableCamera &&
                                 DevicePolicyManager.POLICY_DISABLE_CAMERA.equals(restriction)) ||
                         (admin.disableScreenCapture && DevicePolicyManager
-                                .POLICY_DISABLE_SCREEN_CAPTURE.equals(restriction)) ||
-                        (admin.mandatoryBackupTransport != null && DevicePolicyManager
-                                .POLICY_MANDATORY_BACKUPS.equals(restriction))) {
+                                .POLICY_DISABLE_SCREEN_CAPTURE.equals(restriction))) {
                         intent = createShowAdminSupportIntent(admin.info.getComponent(), userId);
                         break;
                     }
@@ -11940,12 +11942,7 @@
         }
         Preconditions.checkNotNull(admin);
         synchronized (getLockObject()) {
-            ActiveAdmin activeAdmin = getActiveAdminForCallerLocked(
-                    admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
-            if (!enabled) {
-                activeAdmin.mandatoryBackupTransport = null;
-                saveSettingsLocked(UserHandle.USER_SYSTEM);
-            }
+            getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
         }
 
         final long ident = mInjector.binderClearCallingIdentity();
@@ -11980,87 +11977,6 @@
     }
 
     @Override
-    public boolean setMandatoryBackupTransport(
-            ComponentName admin,
-            ComponentName backupTransportComponent) {
-        if (!mHasFeature) {
-            return false;
-        }
-        Preconditions.checkNotNull(admin);
-        enforceDeviceOwner(admin);
-
-        final int callingUid = mInjector.binderGetCallingUid();
-        final AtomicBoolean success = new AtomicBoolean(false);
-        final CountDownLatch countDownLatch = new CountDownLatch(1);
-        final ISelectBackupTransportCallback selectBackupTransportCallbackInternal =
-                new ISelectBackupTransportCallback.Stub() {
-                    public void onSuccess(String transportName) {
-                        saveMandatoryBackupTransport(admin, callingUid, backupTransportComponent);
-                        success.set(true);
-                        countDownLatch.countDown();
-                    }
-
-                    public void onFailure(int reason) {
-                        countDownLatch.countDown();
-                    }
-                };
-        final long identity = mInjector.binderClearCallingIdentity();
-        try {
-            IBackupManager ibm = mInjector.getIBackupManager();
-            if (ibm != null && backupTransportComponent != null) {
-                if (!ibm.isBackupServiceActive(UserHandle.USER_SYSTEM)) {
-                    ibm.setBackupServiceActive(UserHandle.USER_SYSTEM, true);
-                }
-                ibm.selectBackupTransportAsync(
-                        backupTransportComponent, selectBackupTransportCallbackInternal);
-                countDownLatch.await();
-                if (success.get()) {
-                    ibm.setBackupEnabled(true);
-                }
-            } else if (backupTransportComponent == null) {
-                saveMandatoryBackupTransport(admin, callingUid, backupTransportComponent);
-                success.set(true);
-            }
-        } catch (RemoteException e) {
-            throw new IllegalStateException("Failed to set mandatory backup transport.", e);
-        } catch (InterruptedException e) {
-            throw new IllegalStateException("Failed to set mandatory backup transport.", e);
-        } finally {
-            mInjector.binderRestoreCallingIdentity(identity);
-        }
-        return success.get();
-    }
-
-    private void saveMandatoryBackupTransport(
-            ComponentName admin, int callingUid, ComponentName backupTransportComponent) {
-        synchronized (getLockObject()) {
-            ActiveAdmin activeAdmin =
-                    getActiveAdminWithPolicyForUidLocked(
-                            admin,
-                            DeviceAdminInfo.USES_POLICY_DEVICE_OWNER,
-                            callingUid);
-            if (!Objects.equals(backupTransportComponent,
-                    activeAdmin.mandatoryBackupTransport)) {
-                activeAdmin.mandatoryBackupTransport =
-                        backupTransportComponent;
-                saveSettingsLocked(UserHandle.USER_SYSTEM);
-            }
-        }
-    }
-
-    @Override
-    public ComponentName getMandatoryBackupTransport() {
-        if (!mHasFeature) {
-            return null;
-        }
-        synchronized (getLockObject()) {
-            ActiveAdmin activeAdmin = getDeviceOwnerAdminLocked();
-            return activeAdmin == null ? null : activeAdmin.mandatoryBackupTransport;
-        }
-    }
-
-
-    @Override
     public boolean bindDeviceAdminServiceAsUser(
             @NonNull ComponentName admin, @NonNull IApplicationThread caller,
             @Nullable IBinder activtiyToken, @NonNull Intent serviceIntent,
@@ -12313,6 +12229,7 @@
     }
 
     /** Pauses security and network logging if there are unaffiliated users on the device */
+    @GuardedBy("getLockObject()")
     private void maybePauseDeviceWideLoggingLocked() {
         if (!areAllUsersAffiliatedWithDeviceLocked()) {
             Slog.i(LOG_TAG, "There are unaffiliated users, security and network logging will be "
@@ -12325,6 +12242,7 @@
     }
 
     /** Resumes security and network logging (if they are enabled) if all users are affiliated */
+    @GuardedBy("getLockObject()")
     private void maybeResumeDeviceWideLoggingLocked() {
         if (areAllUsersAffiliatedWithDeviceLocked()) {
             final long ident = mInjector.binderClearCallingIdentity();
@@ -12340,6 +12258,7 @@
     }
 
     /** Deletes any security and network logs that might have been collected so far */
+    @GuardedBy("getLockObject()")
     private void discardDeviceWideLogsLocked() {
         mSecurityLogMonitor.discardLogs();
         if (mNetworkLogger != null) {
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index ecc13b2..bb08345 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -82,6 +82,7 @@
 import com.android.server.biometrics.fingerprint.FingerprintService;
 import com.android.server.hdmi.HdmiControlService;
 import com.android.server.input.InputManagerService;
+import com.android.server.inputmethod.InputMethodManagerService;
 import com.android.server.job.JobSchedulerService;
 import com.android.server.lights.LightsService;
 import com.android.server.media.MediaResourceMonitorService;
@@ -743,10 +744,20 @@
             traceEnd();
         }
 
+        // Tracks and caches the device state.
+        traceBeginAndSlog("StartCachedDeviceStateService");
+        mSystemServiceManager.startService(CachedDeviceStateService.class);
+        traceEnd();
+
         // Tracks cpu time spent in binder calls
         traceBeginAndSlog("StartBinderCallsStatsService");
         mSystemServiceManager.startService(BinderCallsStatsService.LifeCycle.class);
         traceEnd();
+
+        // Tracks time spent in handling messages in handlers.
+        traceBeginAndSlog("StartLooperStatsService");
+        mSystemServiceManager.startService(LooperStatsService.Lifecycle.class);
+        traceEnd();
     }
 
     /**
@@ -774,6 +785,8 @@
 
         boolean disableSystemTextClassifier = SystemProperties.getBoolean(
                 "config.disable_systemtextclassifier", false);
+        boolean disableNetworkTime = SystemProperties.getBoolean("config.disable_networktime",
+                false);
         boolean disableCameraService = SystemProperties.getBoolean("config.disable_cameraservice",
                 false);
         boolean disableSlices = SystemProperties.getBoolean("config.disable_slices", false);
@@ -873,7 +886,8 @@
             }
 
             traceBeginAndSlog("StartAlarmManagerService");
-            mSystemServiceManager.startService(AlarmManagerService.class);
+            mSystemServiceManager.startService(new AlarmManagerService(context));
+
             traceEnd();
 
             traceBeginAndSlog("InitWatchdog");
@@ -1447,7 +1461,7 @@
                 traceEnd();
             }
 
-            if (!isWatch) {
+            if (!isWatch && !disableNetworkTime) {
                 traceBeginAndSlog("StartNetworkTimeUpdateService");
                 try {
                     if (useNewTimeServices) {
diff --git a/services/net/java/android/net/dhcp/DhcpLease.java b/services/net/java/android/net/dhcp/DhcpLease.java
index d2a15b3..6cdd2aa 100644
--- a/services/net/java/android/net/dhcp/DhcpLease.java
+++ b/services/net/java/android/net/dhcp/DhcpLease.java
@@ -130,9 +130,14 @@
         return HexDump.toHexString(bytes);
     }
 
+    static String inet4AddrToString(@Nullable Inet4Address addr) {
+        return (addr == null) ? "null" : addr.getHostAddress();
+    }
+
     @Override
     public String toString() {
         return String.format("clientId: %s, hwAddr: %s, netAddr: %s, expTime: %d, hostname: %s",
-                clientIdToString(mClientId), mHwAddr.toString(), mNetAddr, mExpTime, mHostname);
+                clientIdToString(mClientId), mHwAddr.toString(), inet4AddrToString(mNetAddr),
+                mExpTime, mHostname);
     }
 }
diff --git a/services/net/java/android/net/dhcp/DhcpLeaseRepository.java b/services/net/java/android/net/dhcp/DhcpLeaseRepository.java
index 9f77ed0..2dda421 100644
--- a/services/net/java/android/net/dhcp/DhcpLeaseRepository.java
+++ b/services/net/java/android/net/dhcp/DhcpLeaseRepository.java
@@ -20,6 +20,7 @@
 import static android.net.NetworkUtils.intToInet4AddressHTH;
 import static android.net.NetworkUtils.prefixLengthToV4NetmaskIntHTH;
 import static android.net.dhcp.DhcpLease.EXPIRATION_NEVER;
+import static android.net.dhcp.DhcpLease.inet4AddrToString;
 import static android.net.util.NetworkConstants.IPV4_ADDR_BITS;
 
 import static java.lang.Math.min;
@@ -98,6 +99,12 @@
         }
     }
 
+    static class InvalidSubnetException extends DhcpLeaseException {
+        InvalidSubnetException(String message) {
+            super(message);
+        }
+    }
+
     /**
      * Leases by IP address
      */
@@ -152,25 +159,17 @@
      * @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
+     * @throws InvalidSubnetException 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 {
+            @NonNull Inet4Address relayAddr, @Nullable Inet4Address reqAddr,
+            @Nullable String hostname) throws OutOfAddressesException, InvalidSubnetException {
         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");
-        }
+        checkValidRelayAddr(relayAddr);
 
         final DhcpLease currentLease = findByClient(clientId, hwAddr);
         final DhcpLease newLease;
@@ -188,7 +187,19 @@
         return newLease;
     }
 
-    private static boolean isIpAddrOutsidePrefix(IpPrefix prefix, Inet4Address addr) {
+    private void checkValidRelayAddr(@Nullable Inet4Address relayAddr)
+            throws InvalidSubnetException {
+        // 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 InvalidSubnetException("Lease requested by relay from outside of subnet");
+        }
+    }
+
+    private static boolean isIpAddrOutsidePrefix(@NonNull IpPrefix prefix,
+            @Nullable Inet4Address addr) {
         return addr != null && !addr.equals(Inet4Address.ANY) && !prefix.contains(addr);
     }
 
@@ -222,10 +233,12 @@
      */
     @NonNull
     public DhcpLease requestLease(@Nullable byte[] clientId, @NonNull MacAddress hwAddr,
-            @NonNull Inet4Address clientAddr, @Nullable Inet4Address reqAddr, boolean sidSet,
-            @Nullable String hostname) throws InvalidAddressException {
+            @NonNull Inet4Address clientAddr, @NonNull Inet4Address relayAddr,
+            @Nullable Inet4Address reqAddr, boolean sidSet, @Nullable String hostname)
+            throws InvalidAddressException, InvalidSubnetException {
         final long currentTime = mClock.elapsedRealtime();
         removeExpiredLeases(currentTime);
+        checkValidRelayAddr(relayAddr);
         final DhcpLease assignedLease = findByClient(clientId, hwAddr);
 
         final Inet4Address leaseAddr = reqAddr != null ? reqAddr : clientAddr;
@@ -252,7 +265,7 @@
         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);
+                assignedLease, inet4AddrToString(reqAddr), sidSet, lease);
         return lease;
     }
 
@@ -304,7 +317,7 @@
             @NonNull Inet4Address addr) {
         final DhcpLease currentLease = mCommittedLeases.getOrDefault(addr, null);
         if (currentLease == null) {
-            mLog.w("Could not release unknown lease for " + addr);
+            mLog.w("Could not release unknown lease for " + inet4AddrToString(addr));
             return false;
         }
         if (currentLease.matchesClient(clientId, hwAddr)) {
@@ -319,12 +332,13 @@
 
     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);
+            mLog.logf("Not marking %s as declined: already declined or not assignable",
+                    inet4AddrToString(addr));
             return;
         }
         final long expTime = mClock.elapsedRealtime() + mLeaseTimeMs;
         mDeclinedAddrs.put(addr, expTime);
-        mLog.logf("Marked %s as declined expiring %d", addr, expTime);
+        mLog.logf("Marked %s as declined expiring %d", inet4AddrToString(addr), expTime);
         maybeUpdateEarliestExpiration(expTime);
     }
 
@@ -515,7 +529,8 @@
         while (it.hasNext()) {
             final Inet4Address addr = it.next();
             it.remove();
-            mLog.logf("Out of addresses in address pool: dropped declined addr %s", addr);
+            mLog.logf("Out of addresses in address pool: dropped declined addr %s",
+                    inet4AddrToString(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.
diff --git a/services/net/java/android/net/dhcp/DhcpPacket.java b/services/net/java/android/net/dhcp/DhcpPacket.java
index 595a129..77a3e21 100644
--- a/services/net/java/android/net/dhcp/DhcpPacket.java
+++ b/services/net/java/android/net/dhcp/DhcpPacket.java
@@ -1281,12 +1281,12 @@
      */
     public static ByteBuffer buildAckPacket(int encap, int transactionId,
         boolean broadcast, Inet4Address serverIpAddr, Inet4Address relayIp, Inet4Address yourIp,
-        byte[] mac, Integer timeout, Inet4Address netMask, Inet4Address bcAddr,
-        List<Inet4Address> gateways, List<Inet4Address> dnsServers,
+        Inet4Address requestClientIp, byte[] mac, Integer timeout, Inet4Address netMask,
+        Inet4Address bcAddr, List<Inet4Address> gateways, List<Inet4Address> dnsServers,
         Inet4Address dhcpServerIdentifier, String domainName, boolean metered) {
         DhcpPacket pkt = new DhcpAckPacket(
-                transactionId, (short) 0, broadcast, serverIpAddr, relayIp,
-                INADDR_ANY /* clientIp */, yourIp, mac);
+                transactionId, (short) 0, broadcast, serverIpAddr, relayIp, requestClientIp, yourIp,
+                mac);
         pkt.mGateways = gateways;
         pkt.mDnsServers = dnsServers;
         pkt.mLeaseTime = timeout;
diff --git a/services/net/java/android/net/dhcp/DhcpServer.java b/services/net/java/android/net/dhcp/DhcpServer.java
index da8c8bb..2b3d577 100644
--- a/services/net/java/android/net/dhcp/DhcpServer.java
+++ b/services/net/java/android/net/dhcp/DhcpServer.java
@@ -269,6 +269,11 @@
         }
     }
 
+    private void logIgnoredPacketInvalidSubnet(DhcpLeaseRepository.InvalidSubnetException e) {
+        // Not an internal error: only logging exception message, not stacktrace
+        mLog.e("Ignored packet from invalid subnet: " + e.getMessage());
+    }
+
     private void processDiscover(@NonNull DhcpDiscoverPacket packet)
             throws MalformedPacketException {
         final DhcpLease lease;
@@ -279,8 +284,8 @@
         } catch (DhcpLeaseRepository.OutOfAddressesException e) {
             transmitNak(packet, "Out of addresses to offer");
             return;
-        } catch (DhcpLeaseRepository.InvalidAddressException e) {
-            transmitNak(packet, "Lease requested from an invalid subnet");
+        } catch (DhcpLeaseRepository.InvalidSubnetException e) {
+            logIgnoredPacketInvalidSubnet(e);
             return;
         }
 
@@ -294,16 +299,20 @@
         final MacAddress clientMac = getMacAddr(packet);
         try {
             lease = mLeaseRepo.requestLease(packet.getExplicitClientIdOrNull(), clientMac,
-                    packet.mClientIp, packet.mRequestedIp, sidSet, packet.mHostName);
+                    packet.mClientIp, packet.mRelayIp, packet.mRequestedIp, sidSet,
+                    packet.mHostName);
         } catch (DhcpLeaseRepository.InvalidAddressException e) {
             transmitNak(packet, "Invalid requested address");
             return;
+        } catch (DhcpLeaseRepository.InvalidSubnetException e) {
+            logIgnoredPacketInvalidSubnet(e);
+            return;
         }
 
         transmitAck(packet, lease, clientMac);
     }
 
-    private void processRelease(@Nullable DhcpReleasePacket packet)
+    private void processRelease(@NonNull DhcpReleasePacket packet)
             throws MalformedPacketException {
         final byte[] clientId = packet.getExplicitClientIdOrNull();
         final MacAddress macAddr = getMacAddr(packet);
@@ -367,7 +376,7 @@
         final int timeout = getLeaseTimeout(lease);
         final ByteBuffer ackPacket = DhcpPacket.buildAckPacket(ENCAP_BOOTP, request.mTransId,
                 broadcastFlag, mServingParams.getServerInet4Addr(), request.mRelayIp,
-                lease.getNetAddr(), request.mClientMac, timeout,
+                lease.getNetAddr(), request.mClientIp, request.mClientMac, timeout,
                 mServingParams.getPrefixMaskAsAddress(), mServingParams.getBroadcastAddress(),
                 new ArrayList<>(mServingParams.defaultRouters),
                 new ArrayList<>(mServingParams.dnsServers),
@@ -464,7 +473,7 @@
         }
     }
 
-    private static boolean isEmpty(@NonNull Inet4Address address) {
+    private static boolean isEmpty(@Nullable Inet4Address address) {
         return address == null || Inet4Address.ANY.equals(address);
     }
 
diff --git a/services/net/java/android/net/dns/ResolvUtil.java b/services/net/java/android/net/dns/ResolvUtil.java
deleted file mode 100644
index d9d4b96..0000000
--- a/services/net/java/android/net/dns/ResolvUtil.java
+++ /dev/null
@@ -1,81 +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.net.dns;
-
-import static android.system.OsConstants.AI_ADDRCONFIG;
-
-import android.net.Network;
-import android.net.NetworkUtils;
-import android.system.GaiException;
-import android.system.OsConstants;
-import android.system.StructAddrinfo;
-
-import libcore.io.Libcore;
-
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-
-
-/**
- * DNS resolution utility class.
- *
- * @hide
- */
-public class ResolvUtil {
-    // Non-portable DNS resolution flag.
-    private static final long NETID_USE_LOCAL_NAMESERVERS = 0x80000000L;
-
-    private ResolvUtil() {}
-
-    public static InetAddress[] blockingResolveAllLocally(Network network, String name)
-            throws UnknownHostException {
-        // Use AI_ADDRCONFIG by default
-        return blockingResolveAllLocally(network, name, AI_ADDRCONFIG);
-    }
-
-    public static InetAddress[] blockingResolveAllLocally(
-            Network network, String name, int aiFlags) throws UnknownHostException  {
-        final StructAddrinfo hints = new StructAddrinfo();
-        hints.ai_flags = aiFlags;
-        // Other hints identical to the default Inet6AddressImpl implementation
-        hints.ai_family = OsConstants.AF_UNSPEC;
-        hints.ai_socktype = OsConstants.SOCK_STREAM;
-
-        final Network networkForResolv = getNetworkWithUseLocalNameserversFlag(network);
-
-        try {
-            return Libcore.os.android_getaddrinfo(name, hints, (int) networkForResolv.netId);
-        } catch (GaiException gai) {
-            gai.rethrowAsUnknownHostException(name + ": TLS-bypass resolution failed");
-            return null;  // keep compiler quiet
-        }
-    }
-
-    public static Network getNetworkWithUseLocalNameserversFlag(Network network) {
-        final long netidForResolv = NETID_USE_LOCAL_NAMESERVERS | (long) network.netId;
-        return new Network((int) netidForResolv);
-    }
-
-    public static Network makeNetworkWithPrivateDnsBypass(Network network) {
-        return new Network(network) {
-            @Override
-            public InetAddress[] getAllByName(String host) throws UnknownHostException {
-                return blockingResolveAllLocally(network, host);
-            }
-        };
-    }
-}
diff --git a/services/net/java/android/net/ip/IpClient.java b/services/net/java/android/net/ip/IpClient.java
index 3cdef1e..0176dd4 100644
--- a/services/net/java/android/net/ip/IpClient.java
+++ b/services/net/java/android/net/ip/IpClient.java
@@ -228,6 +228,9 @@
     //       Encourages logging of any available arguments, and all call sites
     //       are necessarily logged identically.
     //
+    // NOTE: Log first because passed objects may or may not be thread-safe and
+    // once passed on to the callback they may be modified by another thread.
+    //
     // TODO: Find an lighter weight approach.
     private class LoggingCallbackWrapper extends Callback {
         private static final String PREFIX = "INVOKE ";
@@ -243,63 +246,63 @@
 
         @Override
         public void onPreDhcpAction() {
-            mCallback.onPreDhcpAction();
             log("onPreDhcpAction()");
+            mCallback.onPreDhcpAction();
         }
         @Override
         public void onPostDhcpAction() {
-            mCallback.onPostDhcpAction();
             log("onPostDhcpAction()");
+            mCallback.onPostDhcpAction();
         }
         @Override
         public void onNewDhcpResults(DhcpResults dhcpResults) {
-            mCallback.onNewDhcpResults(dhcpResults);
             log("onNewDhcpResults({" + dhcpResults + "})");
+            mCallback.onNewDhcpResults(dhcpResults);
         }
         @Override
         public void onProvisioningSuccess(LinkProperties newLp) {
-            mCallback.onProvisioningSuccess(newLp);
             log("onProvisioningSuccess({" + newLp + "})");
+            mCallback.onProvisioningSuccess(newLp);
         }
         @Override
         public void onProvisioningFailure(LinkProperties newLp) {
-            mCallback.onProvisioningFailure(newLp);
             log("onProvisioningFailure({" + newLp + "})");
+            mCallback.onProvisioningFailure(newLp);
         }
         @Override
         public void onLinkPropertiesChange(LinkProperties newLp) {
-            mCallback.onLinkPropertiesChange(newLp);
             log("onLinkPropertiesChange({" + newLp + "})");
+            mCallback.onLinkPropertiesChange(newLp);
         }
         @Override
         public void onReachabilityLost(String logMsg) {
-            mCallback.onReachabilityLost(logMsg);
             log("onReachabilityLost(" + logMsg + ")");
+            mCallback.onReachabilityLost(logMsg);
         }
         @Override
         public void onQuit() {
-            mCallback.onQuit();
             log("onQuit()");
+            mCallback.onQuit();
         }
         @Override
         public void installPacketFilter(byte[] filter) {
-            mCallback.installPacketFilter(filter);
             log("installPacketFilter(byte[" + filter.length + "])");
+            mCallback.installPacketFilter(filter);
         }
         @Override
         public void startReadPacketFilter() {
-            mCallback.startReadPacketFilter();
             log("startReadPacketFilter()");
+            mCallback.startReadPacketFilter();
         }
         @Override
         public void setFallbackMulticastFilter(boolean enabled) {
-            mCallback.setFallbackMulticastFilter(enabled);
             log("setFallbackMulticastFilter(" + enabled + ")");
+            mCallback.setFallbackMulticastFilter(enabled);
         }
         @Override
         public void setNeighborDiscoveryOffload(boolean enable) {
-            mCallback.setNeighborDiscoveryOffload(enable);
             log("setNeighborDiscoveryOffload(" + enable + ")");
+            mCallback.setNeighborDiscoveryOffload(enable);
         }
     }
 
@@ -1385,6 +1388,20 @@
 
     private boolean startIpReachabilityMonitor() {
         try {
+            // TODO: Fetch these parameters from settings, and install a
+            // settings observer to watch for update and re-program these
+            // parameters (Q: is this level of dynamic updatability really
+            // necessary or does reading from settings at startup suffice?).
+            final int NUM_SOLICITS = 5;
+            final int INTER_SOLICIT_INTERVAL_MS = 750;
+            setNeighborParameters(mDependencies.getNetd(), mInterfaceName,
+                    NUM_SOLICITS, INTER_SOLICIT_INTERVAL_MS);
+        } catch (Exception e) {
+            mLog.e("Failed to adjust neighbor parameters", e);
+            // Carry on using the system defaults (currently: 3, 1000);
+        }
+
+        try {
             mIpReachabilityMonitor = new IpReachabilityMonitor(
                     mContext,
                     mInterfaceParams,
@@ -1863,6 +1880,20 @@
         }
     }
 
+    private static void setNeighborParameters(
+            INetd netd, String ifName, int num_solicits, int inter_solicit_interval_ms)
+            throws RemoteException, IllegalArgumentException {
+        Preconditions.checkNotNull(netd);
+        Preconditions.checkArgument(!TextUtils.isEmpty(ifName));
+        Preconditions.checkArgument(num_solicits > 0);
+        Preconditions.checkArgument(inter_solicit_interval_ms > 0);
+
+        for (int family : new Integer[]{INetd.IPV4, INetd.IPV6}) {
+            netd.setProcSysNet(family, INetd.NEIGH, ifName, "retrans_time_ms", Integer.toString(inter_solicit_interval_ms));
+            netd.setProcSysNet(family, INetd.NEIGH, ifName, "ucast_solicit", Integer.toString(num_solicits));
+        }
+    }
+
     // TODO: extract out into CollectionUtils.
     static <T> boolean any(Iterable<T> coll, Predicate<T> fn) {
         for (T t : coll) {
diff --git a/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java b/services/net/java/android/net/ip/IpServer.java
similarity index 89%
rename from services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java
rename to services/net/java/android/net/ip/IpServer.java
index 5accb45..823c0a1 100644
--- a/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java
+++ b/services/net/java/android/net/ip/IpServer.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server.connectivity.tethering;
+package android.net.ip;
 
 import static android.net.NetworkUtils.numericToInetAddress;
 import static android.net.util.NetworkConstants.asByte;
@@ -31,11 +31,10 @@
 import android.net.RouteInfo;
 import android.net.dhcp.DhcpServer;
 import android.net.dhcp.DhcpServingParams;
-import android.net.ip.InterfaceController;
-import android.net.ip.RouterAdvertisementDaemon;
 import android.net.ip.RouterAdvertisementDaemon.RaParams;
 import android.net.util.InterfaceParams;
 import android.net.util.InterfaceSet;
+import android.net.util.NetdService;
 import android.net.util.SharedLog;
 import android.os.INetworkManagementService;
 import android.os.Looper;
@@ -67,7 +66,22 @@
  *
  * @hide
  */
-public class TetherInterfaceStateMachine extends StateMachine {
+public class IpServer extends StateMachine {
+    public static final int STATE_UNAVAILABLE = 0;
+    public static final int STATE_AVAILABLE   = 1;
+    public static final int STATE_TETHERED    = 2;
+    public static final int STATE_LOCAL_ONLY  = 3;
+
+    public static String getStateString(int state) {
+        switch (state) {
+            case STATE_UNAVAILABLE: return "UNAVAILABLE";
+            case STATE_AVAILABLE:   return "AVAILABLE";
+            case STATE_TETHERED:    return "TETHERED";
+            case STATE_LOCAL_ONLY:  return "LOCAL_ONLY";
+        }
+        return "UNKNOWN: " + state;
+    }
+
     private static final IpPrefix LINK_LOCAL_PREFIX = new IpPrefix("fe80::/64");
     private static final byte DOUG_ADAMS = (byte) 42;
 
@@ -83,15 +97,53 @@
     // TODO: have this configurable
     private static final int DHCP_LEASE_TIME_SECS = 3600;
 
-    private final static String TAG = "TetherInterfaceSM";
+    private final static String TAG = "IpServer";
     private final static boolean DBG = false;
     private final static boolean VDBG = false;
     private static final Class[] messageClasses = {
-            TetherInterfaceStateMachine.class
+            IpServer.class
     };
     private static final SparseArray<String> sMagicDecoderRing =
             MessageUtils.findMessageNames(messageClasses);
 
+    public static class Callback {
+        /**
+         * Notify that |who| has changed its tethering state.
+         *
+         * @param who the calling instance of IpServer
+         * @param state one of STATE_*
+         * @param lastError one of ConnectivityManager.TETHER_ERROR_*
+         */
+        public void updateInterfaceState(IpServer who, int state, int lastError) {}
+
+        /**
+         * Notify that |who| has new LinkProperties.
+         *
+         * @param who the calling instance of IpServer
+         * @param newLp the new LinkProperties to report
+         */
+        public void updateLinkProperties(IpServer who, LinkProperties newLp) {}
+    }
+
+    public static class Dependencies {
+        public RouterAdvertisementDaemon getRouterAdvertisementDaemon(InterfaceParams ifParams) {
+            return new RouterAdvertisementDaemon(ifParams);
+        }
+
+        public InterfaceParams getInterfaceParams(String ifName) {
+            return InterfaceParams.getByName(ifName);
+        }
+
+        public INetd getNetdService() {
+            return NetdService.getInstance();
+        }
+
+        public DhcpServer makeDhcpServer(Looper looper, InterfaceParams iface,
+                DhcpServingParams params, SharedLog log) {
+            return new DhcpServer(looper, iface, params, log);
+        }
+    }
+
     private static final int BASE_IFACE              = Protocol.BASE_TETHERING + 100;
     // request from the user that it wants to tether
     public static final int CMD_TETHER_REQUESTED            = BASE_IFACE + 2;
@@ -123,7 +175,7 @@
     private final INetworkManagementService mNMService;
     private final INetd mNetd;
     private final INetworkStatsService mStatsService;
-    private final IControlsTethering mTetherController;
+    private final Callback mCallback;
     private final InterfaceController mInterfaceCtrl;
 
     private final String mIfaceName;
@@ -131,7 +183,7 @@
     private final LinkProperties mLinkProperties;
     private final boolean mUsingLegacyDhcp;
 
-    private final TetheringDependencies mDeps;
+    private final Dependencies mDeps;
 
     private int mLastError;
     private int mServingMode;
@@ -148,17 +200,16 @@
     private DhcpServer mDhcpServer;
     private RaParams mLastRaParams;
 
-    public TetherInterfaceStateMachine(
+    public IpServer(
             String ifaceName, Looper looper, int interfaceType, SharedLog log,
             INetworkManagementService nMService, INetworkStatsService statsService,
-            IControlsTethering tetherController, boolean usingLegacyDhcp,
-            TetheringDependencies deps) {
+            Callback callback, boolean usingLegacyDhcp, Dependencies deps) {
         super(ifaceName, looper);
         mLog = log.forSubComponent(ifaceName);
         mNMService = nMService;
         mNetd = deps.getNetdService();
         mStatsService = statsService;
-        mTetherController = tetherController;
+        mCallback = callback;
         mInterfaceCtrl = new InterfaceController(ifaceName, nMService, mNetd, mLog);
         mIfaceName = ifaceName;
         mInterfaceType = interfaceType;
@@ -167,7 +218,7 @@
         mDeps = deps;
         resetLinkProperties();
         mLastError = ConnectivityManager.TETHER_ERROR_NO_ERROR;
-        mServingMode = IControlsTethering.STATE_AVAILABLE;
+        mServingMode = STATE_AVAILABLE;
 
         mInitialState = new InitialState();
         mLocalHotspotState = new LocalHotspotState();
@@ -379,6 +430,8 @@
             params.mtu = v6only.getMtu();
             params.hasDefaultRoute = v6only.hasIPv6DefaultRoute();
 
+            if (params.hasDefaultRoute) params.hopLimit = getHopLimit(v6only.getInterfaceName());
+
             for (LinkAddress linkAddr : v6only.getLinkAddresses()) {
                 if (linkAddr.getPrefixLength() != RFC7421_PREFIX_LENGTH) continue;
 
@@ -498,6 +551,20 @@
         }
     }
 
+    private byte getHopLimit(String upstreamIface) {
+        try {
+            int upstreamHopLimit = Integer.parseUnsignedInt(
+                    mNetd.getProcSysNet(INetd.IPV6, INetd.CONF, upstreamIface, "hop_limit"));
+            // Add one hop to account for this forwarding device
+            upstreamHopLimit++;
+            // Cap the hop limit to 255.
+            return (byte) Integer.min(upstreamHopLimit, 255);
+        } catch (Exception e) {
+            mLog.e("Failed to find upstream interface hop limit", e);
+        }
+        return RaParams.DEFAULT_HOPLIMIT;
+    }
+
     private void setRaParams(RaParams newParams) {
         if (mRaDaemon != null) {
             final RaParams deprecatedParams =
@@ -521,14 +588,12 @@
 
     private void sendInterfaceState(int newInterfaceState) {
         mServingMode = newInterfaceState;
-        mTetherController.updateInterfaceState(
-                TetherInterfaceStateMachine.this, newInterfaceState, mLastError);
+        mCallback.updateInterfaceState(this, newInterfaceState, mLastError);
         sendLinkProperties();
     }
 
     private void sendLinkProperties() {
-        mTetherController.updateLinkProperties(
-                TetherInterfaceStateMachine.this, new LinkProperties(mLinkProperties));
+        mCallback.updateLinkProperties(this, new LinkProperties(mLinkProperties));
     }
 
     private void resetLinkProperties() {
@@ -539,7 +604,7 @@
     class InitialState extends State {
         @Override
         public void enter() {
-            sendInterfaceState(IControlsTethering.STATE_AVAILABLE);
+            sendInterfaceState(STATE_AVAILABLE);
         }
 
         @Override
@@ -549,10 +614,10 @@
                 case CMD_TETHER_REQUESTED:
                     mLastError = ConnectivityManager.TETHER_ERROR_NO_ERROR;
                     switch (message.arg1) {
-                        case IControlsTethering.STATE_LOCAL_ONLY:
+                        case STATE_LOCAL_ONLY:
                             transitionTo(mLocalHotspotState);
                             break;
-                        case IControlsTethering.STATE_TETHERED:
+                        case STATE_TETHERED:
                             transitionTo(mTetheredState);
                             break;
                         default:
@@ -649,7 +714,7 @@
     // problematic because transitioning during a multi-state jump yields
     // a Log.wtf(). Ultimately, there should be only one ServingState,
     // and forwarding and NAT rules should be handled by a coordinating
-    // functional element outside of TetherInterfaceStateMachine.
+    // functional element outside of IpServer.
     class LocalHotspotState extends BaseServingState {
         @Override
         public void enter() {
@@ -659,7 +724,7 @@
             }
 
             if (DBG) Log.d(TAG, "Local hotspot " + mIfaceName);
-            sendInterfaceState(IControlsTethering.STATE_LOCAL_ONLY);
+            sendInterfaceState(STATE_LOCAL_ONLY);
         }
 
         @Override
@@ -685,7 +750,7 @@
     // problematic because transitioning during a multi-state jump yields
     // a Log.wtf(). Ultimately, there should be only one ServingState,
     // and forwarding and NAT rules should be handled by a coordinating
-    // functional element outside of TetherInterfaceStateMachine.
+    // functional element outside of IpServer.
     class TetheredState extends BaseServingState {
         @Override
         public void enter() {
@@ -695,7 +760,7 @@
             }
 
             if (DBG) Log.d(TAG, "Tethered " + mIfaceName);
-            sendInterfaceState(IControlsTethering.STATE_TETHERED);
+            sendInterfaceState(STATE_TETHERED);
         }
 
         @Override
@@ -817,7 +882,7 @@
         @Override
         public void enter() {
             mLastError = ConnectivityManager.TETHER_ERROR_NO_ERROR;
-            sendInterfaceState(IControlsTethering.STATE_UNAVAILABLE);
+            sendInterfaceState(STATE_UNAVAILABLE);
         }
     }
 
diff --git a/services/net/java/android/net/ip/RouterAdvertisementDaemon.java b/services/net/java/android/net/ip/RouterAdvertisementDaemon.java
index 8fbc01e..9d686ef 100644
--- a/services/net/java/android/net/ip/RouterAdvertisementDaemon.java
+++ b/services/net/java/android/net/ip/RouterAdvertisementDaemon.java
@@ -119,13 +119,23 @@
     private volatile UnicastResponder mUnicastResponder;
 
     public static class RaParams {
+        // Tethered traffic will have the hop limit properly decremented.
+        // Consequently, set the hoplimit greater by one than the upstream
+        // unicast hop limit.
+        //
+        // TODO: Dynamically pass down the IPV6_UNICAST_HOPS value from the
+        // upstream interface for more correct behaviour.
+        static final byte DEFAULT_HOPLIMIT = 65;
+
         public boolean hasDefaultRoute;
+        public byte hopLimit;
         public int mtu;
         public HashSet<IpPrefix> prefixes;
         public HashSet<Inet6Address> dnses;
 
         public RaParams() {
             hasDefaultRoute = false;
+            hopLimit = DEFAULT_HOPLIMIT;
             mtu = IPV6_MIN_MTU;
             prefixes = new HashSet<IpPrefix>();
             dnses = new HashSet<Inet6Address>();
@@ -133,6 +143,7 @@
 
         public RaParams(RaParams other) {
             hasDefaultRoute = other.hasDefaultRoute;
+            hopLimit = other.hopLimit;
             mtu = other.mtu;
             prefixes = (HashSet) other.prefixes.clone();
             dnses = (HashSet) other.dnses.clone();
@@ -273,10 +284,12 @@
         final ByteBuffer ra = ByteBuffer.wrap(mRA);
         ra.order(ByteOrder.BIG_ENDIAN);
 
+        final boolean haveRaParams = (mRaParams != null);
         boolean shouldSendRA = false;
 
         try {
-            putHeader(ra, mRaParams != null && mRaParams.hasDefaultRoute);
+            putHeader(ra, haveRaParams && mRaParams.hasDefaultRoute,
+                    haveRaParams ? mRaParams.hopLimit : RaParams.DEFAULT_HOPLIMIT);
             putSlla(ra, mInterface.macAddr.toByteArray());
             mRaLength = ra.position();
 
@@ -287,7 +300,7 @@
             //
             // putExpandedFlagsOption(ra);
 
-            if (mRaParams != null) {
+            if (haveRaParams) {
                 putMtu(ra, mRaParams.mtu);
                 mRaLength = ra.position();
 
@@ -348,7 +361,7 @@
     private static byte asByte(int value) { return (byte) value; }
     private static short asShort(int value) { return (short) value; }
 
-    private static void putHeader(ByteBuffer ra, boolean hasDefaultRoute) {
+    private static void putHeader(ByteBuffer ra, boolean hasDefaultRoute, byte hopLimit) {
         /**
             Router Advertisement Message Format
 
@@ -366,11 +379,10 @@
             |   Options ...
             +-+-+-+-+-+-+-+-+-+-+-+-
         */
-        final byte DEFAULT_HOPLIMIT = 64;
         ra.put(ICMPV6_ND_ROUTER_ADVERT)
           .put(asByte(0))
           .putShort(asShort(0))
-          .put(DEFAULT_HOPLIMIT)
+          .put(hopLimit)
           // RFC 4191 "high" preference, iff. advertising a default route.
           .put(hasDefaultRoute ? asByte(0x08) : asByte(0))
           .putShort(hasDefaultRoute ? asShort(DEFAULT_LIFETIME) : asShort(0))
diff --git a/services/robotests/Android.mk b/services/robotests/Android.mk
index 3d7fdbdd..8b59771 100644
--- a/services/robotests/Android.mk
+++ b/services/robotests/Android.mk
@@ -63,7 +63,9 @@
     $(call all-Iaidl-files-under, ../../core/java/android/app/backup) \
     ../../core/java/android/content/pm/PackageInfo.java \
     ../../core/java/android/app/IBackupAgent.aidl \
-    ../../core/java/android/util/KeyValueSettingObserver.java
+    ../../core/java/android/util/KeyValueSettingObserver.java \
+    ../../core/java/android/content/pm/PackageParser.java \
+    ../../core/java/android/content/pm/SigningInfo.java
 
 LOCAL_AIDL_INCLUDES := \
     $(call all-Iaidl-files-under, $(INTERNAL_BACKUP)) \
@@ -73,6 +75,7 @@
 LOCAL_STATIC_JAVA_LIBRARIES := \
     platform-robolectric-android-all-stubs \
     android-support-test \
+    guava \
     mockito-robolectric-prebuilt \
     platform-test-annotations \
     truth-prebuilt \
diff --git a/services/robotests/src/com/android/server/backup/BackupAgentTimeoutParametersTest.java b/services/robotests/src/com/android/server/backup/BackupAgentTimeoutParametersTest.java
index 801451e..0d2c221 100644
--- a/services/robotests/src/com/android/server/backup/BackupAgentTimeoutParametersTest.java
+++ b/services/robotests/src/com/android/server/backup/BackupAgentTimeoutParametersTest.java
@@ -16,6 +16,8 @@
 
 package com.android.server.backup;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import static org.junit.Assert.assertEquals;
 
 import android.content.ContentResolver;
@@ -51,7 +53,6 @@
 
         mContentResolver = context.getContentResolver();
         mParameters = new BackupAgentTimeoutParameters(new Handler(), mContentResolver);
-        mParameters.start();
     }
 
     /** Stop observing changes to the setting. */
@@ -61,8 +62,11 @@
     }
 
     /** Tests that timeout parameters are initialized with default values on creation. */
+    // TODO: Break down tests
     @Test
     public void testGetParameters_afterConstructorWithStart_returnsDefaultValues() {
+        mParameters.start();
+
         long kvBackupAgentTimeoutMillis = mParameters.getKvBackupAgentTimeoutMillis();
         long fullBackupAgentTimeoutMillis = mParameters.getFullBackupAgentTimeoutMillis();
         long sharedBackupAgentTimeoutMillis = mParameters.getSharedBackupAgentTimeoutMillis();
@@ -86,13 +90,33 @@
                 restoreAgentFinishedTimeoutMillis);
     }
 
+    @Test
+    public void testGetQuotaExceededTimeoutMillis_returnsDefaultValue() {
+        mParameters.start();
+
+        long timeout = mParameters.getQuotaExceededTimeoutMillis();
+
+        assertThat(timeout)
+                .isEqualTo(BackupAgentTimeoutParameters.DEFAULT_QUOTA_EXCEEDED_TIMEOUT_MILLIS);
+    }
+
+    @Test
+    public void testGetQuotaExceededTimeoutMillis_whenSettingSet_returnsSetValue() {
+        putStringAndNotify(
+                BackupAgentTimeoutParameters.SETTING_QUOTA_EXCEEDED_TIMEOUT_MILLIS + "=" + 1279);
+        mParameters.start();
+
+        long timeout = mParameters.getQuotaExceededTimeoutMillis();
+
+        assertThat(timeout).isEqualTo(1279);
+    }
+
     /**
      * Tests that timeout parameters are updated when we call start, even when a setting change
      * occurs while we are not observing.
      */
     @Test
     public void testGetParameters_withSettingChangeBeforeStart_updatesValues() {
-        mParameters.stop();
         long testTimeout = BackupAgentTimeoutParameters.DEFAULT_KV_BACKUP_AGENT_TIMEOUT_MILLIS * 2;
         final String setting =
                 BackupAgentTimeoutParameters.SETTING_KV_BACKUP_AGENT_TIMEOUT_MILLIS
@@ -112,6 +136,7 @@
      */
     @Test
     public void testGetParameters_withSettingChangeAfterStart_updatesValues() {
+        mParameters.start();
         long testTimeout = BackupAgentTimeoutParameters.DEFAULT_KV_BACKUP_AGENT_TIMEOUT_MILLIS * 2;
         final String setting =
                 BackupAgentTimeoutParameters.SETTING_KV_BACKUP_AGENT_TIMEOUT_MILLIS
diff --git a/services/robotests/src/com/android/server/backup/BackupManagerServiceTest.java b/services/robotests/src/com/android/server/backup/BackupManagerServiceTest.java
index 91a8857..57ebbfc 100644
--- a/services/robotests/src/com/android/server/backup/BackupManagerServiceTest.java
+++ b/services/robotests/src/com/android/server/backup/BackupManagerServiceTest.java
@@ -52,7 +52,6 @@
 import com.android.server.testing.FrameworkRobolectricTestRunner;
 import com.android.server.testing.SystemLoaderPackages;
 import com.android.server.testing.shadows.ShadowAppBackupUtils;
-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.ShadowKeyValueBackupTask;
@@ -73,10 +72,7 @@
 import org.robolectric.shadows.ShadowSettings;
 
 @RunWith(FrameworkRobolectricTestRunner.class)
-@Config(
-        manifest = Config.NONE,
-        sdk = 26,
-        shadows = {ShadowAppBackupUtils.class, ShadowBackupPolicyEnforcer.class})
+@Config(manifest = Config.NONE, sdk = 26, shadows = {ShadowAppBackupUtils.class})
 @SystemLoaderPackages({"com.android.server.backup"})
 @Presubmit
 public class BackupManagerServiceTest {
@@ -118,15 +114,12 @@
         mBaseStateDir = new File(cacheDir, "base_state");
         // Corresponds to /cache/backup_stage
         mDataDir = new File(cacheDir, "data");
-
-        ShadowBackupPolicyEnforcer.setMandatoryBackupTransport(null);
     }
 
     @After
     public void tearDown() throws Exception {
         mBackupThread.quit();
         ShadowAppBackupUtils.reset();
-        ShadowBackupPolicyEnforcer.setMandatoryBackupTransport(null);
     }
 
     /* Tests for destination string */
@@ -252,7 +245,6 @@
     private ComponentName mNewTransportComponent;
     private TransportData mNewTransport;
     private TransportMock mNewTransportMock;
-    private ComponentName mOldTransportComponent;
     private TransportData mOldTransport;
     private TransportMock mOldTransportMock;
 
@@ -260,7 +252,6 @@
         mNewTransport = backupTransport();
         mNewTransportComponent = mNewTransport.getTransportComponent();
         mOldTransport = d2dTransport();
-        mOldTransportComponent = mOldTransport.getTransportComponent();
         List<TransportMock> transportMocks =
                 setUpTransports(mTransportManager, mNewTransport, mOldTransport, localTransport());
         mNewTransportMock = transportMocks.get(0);
@@ -314,42 +305,6 @@
     }
 
     @Test
-    public void testSelectBackupTransportAsync_whenMandatoryTransport() throws Exception {
-        setUpForSelectTransport();
-        ShadowBackupPolicyEnforcer.setMandatoryBackupTransport(mNewTransportComponent);
-        mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
-        when(mTransportManager.registerAndSelectTransport(eq(mNewTransportComponent)))
-                .thenReturn(BackupManager.SUCCESS);
-        ISelectBackupTransportCallback callback = mock(ISelectBackupTransportCallback.class);
-        BackupManagerService backupManagerService = createInitializedBackupManagerService();
-
-        backupManagerService.selectBackupTransportAsync(mNewTransportComponent, callback);
-
-        mShadowBackupLooper.runToEndOfTasks();
-        assertThat(getSettingsTransport()).isEqualTo(mNewTransport.transportName);
-        verify(callback).onSuccess(eq(mNewTransport.transportName));
-        verify(mTransportManager)
-                .disposeOfTransportClient(eq(mNewTransportMock.transportClient), any());
-    }
-
-    @Test
-    public void testSelectBackupTransportAsync_whenOtherThanMandatoryTransport() throws Exception {
-        setUpForSelectTransport();
-        ShadowBackupPolicyEnforcer.setMandatoryBackupTransport(mOldTransportComponent);
-        mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
-        when(mTransportManager.registerAndSelectTransport(eq(mNewTransportComponent)))
-                .thenReturn(BackupManager.SUCCESS);
-        ISelectBackupTransportCallback callback = mock(ISelectBackupTransportCallback.class);
-        BackupManagerService backupManagerService = createInitializedBackupManagerService();
-
-        backupManagerService.selectBackupTransportAsync(mNewTransportComponent, callback);
-
-        mShadowBackupLooper.runToEndOfTasks();
-        assertThat(getSettingsTransport()).isNotEqualTo(mNewTransport.transportName);
-        verify(callback).onFailure(eq(BackupManager.ERROR_BACKUP_NOT_ALLOWED));
-    }
-
-    @Test
     public void testSelectBackupTransportAsync_whenRegistrationFails() throws Exception {
         setUpForSelectTransport();
         mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
diff --git a/services/robotests/src/com/android/server/backup/encryption/chunk/ChunkHashTest.java b/services/robotests/src/com/android/server/backup/encryption/chunk/ChunkHashTest.java
new file mode 100644
index 0000000..3b6e038
--- /dev/null
+++ b/services/robotests/src/com/android/server/backup/encryption/chunk/ChunkHashTest.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.backup.encryption.chunk;
+
+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 com.google.common.primitives.Bytes;
+import java.util.Arrays;
+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 ChunkHashTest {
+    private static final int HASH_LENGTH_BYTES = 256 / 8;
+    private static final byte[] TEST_HASH_1 = Arrays.copyOf(new byte[] {1}, HASH_LENGTH_BYTES);
+    private static final byte[] TEST_HASH_2 = Arrays.copyOf(new byte[] {2}, HASH_LENGTH_BYTES);
+
+    @Test
+    public void testGetHash_returnsHash() {
+        ChunkHash chunkHash = new ChunkHash(TEST_HASH_1);
+
+        byte[] hash = chunkHash.getHash();
+
+        assertThat(hash).asList().containsExactlyElementsIn(Bytes.asList(TEST_HASH_1)).inOrder();
+    }
+
+    @Test
+    public void testEquals() {
+        ChunkHash chunkHash1 = new ChunkHash(TEST_HASH_1);
+        ChunkHash equalChunkHash1 = new ChunkHash(TEST_HASH_1);
+        ChunkHash chunkHash2 = new ChunkHash(TEST_HASH_2);
+
+        assertThat(chunkHash1).isEqualTo(equalChunkHash1);
+        assertThat(chunkHash1).isNotEqualTo(chunkHash2);
+    }
+
+    @Test
+    public void testHashCode() {
+        ChunkHash chunkHash1 = new ChunkHash(TEST_HASH_1);
+        ChunkHash equalChunkHash1 = new ChunkHash(TEST_HASH_1);
+        ChunkHash chunkHash2 = new ChunkHash(TEST_HASH_2);
+
+        int hash1 = chunkHash1.hashCode();
+        int equalHash1 = equalChunkHash1.hashCode();
+        int hash2 = chunkHash2.hashCode();
+
+        assertThat(hash1).isEqualTo(equalHash1);
+        assertThat(hash1).isNotEqualTo(hash2);
+    }
+
+    @Test
+    public void testCompareTo_whenEqual_returnsZero() {
+        ChunkHash chunkHash = new ChunkHash(TEST_HASH_1);
+        ChunkHash equalChunkHash = new ChunkHash(TEST_HASH_1);
+
+        int result = chunkHash.compareTo(equalChunkHash);
+
+        assertThat(result).isEqualTo(0);
+    }
+
+    @Test
+    public void testCompareTo_whenArgumentGreater_returnsNegative() {
+        ChunkHash chunkHash1 = new ChunkHash(TEST_HASH_1);
+        ChunkHash chunkHash2 = new ChunkHash(TEST_HASH_2);
+
+        int result = chunkHash1.compareTo(chunkHash2);
+
+        assertThat(result).isLessThan(0);
+    }
+
+    @Test
+    public void testCompareTo_whenArgumentSmaller_returnsPositive() {
+        ChunkHash chunkHash1 = new ChunkHash(TEST_HASH_1);
+        ChunkHash chunkHash2 = new ChunkHash(TEST_HASH_2);
+
+        int result = chunkHash2.compareTo(chunkHash1);
+
+        assertThat(result).isGreaterThan(0);
+    }
+}
diff --git a/services/robotests/src/com/android/server/backup/fullbackup/AppMetadataBackupWriterTest.java b/services/robotests/src/com/android/server/backup/fullbackup/AppMetadataBackupWriterTest.java
new file mode 100644
index 0000000..112e1e3
--- /dev/null
+++ b/services/robotests/src/com/android/server/backup/fullbackup/AppMetadataBackupWriterTest.java
@@ -0,0 +1,495 @@
+package com.android.server.backup.fullbackup;
+
+import static com.android.server.backup.BackupManagerService.BACKUP_MANIFEST_FILENAME;
+import static com.android.server.backup.BackupManagerService.BACKUP_MANIFEST_VERSION;
+import static com.android.server.backup.BackupManagerService.BACKUP_METADATA_FILENAME;
+import static com.android.server.backup.BackupManagerService.BACKUP_METADATA_VERSION;
+import static com.android.server.backup.BackupManagerService.BACKUP_WIDGET_METADATA_TOKEN;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.robolectric.Shadows.shadowOf;
+import static org.testng.Assert.expectThrows;
+
+import android.annotation.Nullable;
+import android.app.Application;
+import android.app.backup.BackupDataInput;
+import android.app.backup.FullBackupDataOutput;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageParser.SigningDetails;
+import android.content.pm.Signature;
+import android.content.pm.SigningInfo;
+import android.os.Build;
+import android.os.Build.VERSION_CODES;
+import android.os.Environment;
+import android.os.ParcelFileDescriptor;
+import android.os.UserHandle;
+
+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 com.android.server.testing.shadows.ShadowFullBackup;
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.attribute.FileTime;
+
+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;
+import org.robolectric.shadows.ShadowApplicationPackageManager;
+import org.robolectric.shadows.ShadowEnvironment;
+
+@RunWith(FrameworkRobolectricTestRunner.class)
+@Config(
+        manifest = Config.NONE,
+        sdk = 26,
+        shadows = {
+            ShadowBackupDataInput.class,
+            ShadowBackupDataOutput.class,
+            ShadowEnvironment.class,
+            ShadowFullBackup.class,
+        })
+@SystemLoaderPackages({"com.android.server.backup", "android.app.backup"})
+@SystemLoaderClasses({PackageInfo.class, SigningInfo.class})
+public class AppMetadataBackupWriterTest {
+    private static final String TEST_PACKAGE = "com.test.package";
+    private static final String TEST_PACKAGE_INSTALLER = "com.test.package.installer";
+    private static final Long TEST_PACKAGE_VERSION_CODE = 100L;
+
+    private ShadowApplicationPackageManager mShadowPackageManager;
+    private File mFilesDir;
+    private File mBackupDataOutputFile;
+    private AppMetadataBackupWriter mBackupWriter;
+
+    @Before
+    public void setUp() throws Exception {
+        Application application = RuntimeEnvironment.application;
+
+        PackageManager packageManager = application.getPackageManager();
+        mShadowPackageManager = (ShadowApplicationPackageManager) shadowOf(packageManager);
+
+        mFilesDir = RuntimeEnvironment.application.getFilesDir();
+        mBackupDataOutputFile = new File(mFilesDir, "output");
+        mBackupDataOutputFile.createNewFile();
+        ParcelFileDescriptor pfd =
+                ParcelFileDescriptor.open(
+                        mBackupDataOutputFile, ParcelFileDescriptor.MODE_READ_WRITE);
+        FullBackupDataOutput output =
+                new FullBackupDataOutput(pfd, /* quota */ -1, /* transportFlags */ 0);
+        mBackupWriter = new AppMetadataBackupWriter(output, packageManager);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        mBackupDataOutputFile.delete();
+    }
+
+    /**
+     * The manifest format is:
+     *
+     * <pre>
+     *     BACKUP_MANIFEST_VERSION
+     *     package name
+     *     package version code
+     *     platform version code
+     *     installer package name (can be empty)
+     *     boolean (1 if archive includes .apk, otherwise 0)
+     *     # of signatures N
+     *     N* (signature byte array in ascii format per Signature.toCharsString())
+     * </pre>
+     */
+    @Test
+    public void testBackupManifest_withoutApkOrSignatures_writesCorrectData() throws Exception {
+        PackageInfo packageInfo =
+                createPackageInfo(TEST_PACKAGE, TEST_PACKAGE_INSTALLER, TEST_PACKAGE_VERSION_CODE);
+        File manifestFile = createFile(BACKUP_MANIFEST_FILENAME);
+
+        mBackupWriter.backupManifest(packageInfo, manifestFile, mFilesDir, /* withApk */ false);
+
+        byte[] manifestBytes = getWrittenBytes(mBackupDataOutputFile, /* includeTarHeader */ false);
+        String[] manifest = new String(manifestBytes, StandardCharsets.UTF_8).split("\n");
+        assertThat(manifest.length).isEqualTo(7);
+        assertThat(manifest[0]).isEqualTo(Integer.toString(BACKUP_MANIFEST_VERSION));
+        assertThat(manifest[1]).isEqualTo(TEST_PACKAGE);
+        assertThat(manifest[2]).isEqualTo(Long.toString(TEST_PACKAGE_VERSION_CODE));
+        assertThat(manifest[3]).isEqualTo(Integer.toString(Build.VERSION.SDK_INT));
+        assertThat(manifest[4]).isEqualTo(TEST_PACKAGE_INSTALLER);
+        assertThat(manifest[5]).isEqualTo("0"); // withApk
+        assertThat(manifest[6]).isEqualTo("0"); // signatures
+        manifestFile.delete();
+    }
+
+    /**
+     * The manifest format is:
+     *
+     * <pre>
+     *     BACKUP_MANIFEST_VERSION
+     *     package name
+     *     package version code
+     *     platform version code
+     *     installer package name (can be empty)
+     *     boolean (1 if archive includes .apk, otherwise 0)
+     *     # of signatures N
+     *     N* (signature byte array in ascii format per Signature.toCharsString())
+     * </pre>
+     */
+    @Test
+    public void testBackupManifest_withApk_writesApk() throws Exception {
+        PackageInfo packageInfo =
+                createPackageInfo(TEST_PACKAGE, TEST_PACKAGE_INSTALLER, TEST_PACKAGE_VERSION_CODE);
+        File manifestFile = createFile(BACKUP_MANIFEST_FILENAME);
+
+        mBackupWriter.backupManifest(packageInfo, manifestFile, mFilesDir, /* withApk */ true);
+
+        byte[] manifestBytes = getWrittenBytes(mBackupDataOutputFile, /* includeTarHeader */ false);
+        String[] manifest = new String(manifestBytes, StandardCharsets.UTF_8).split("\n");
+        assertThat(manifest.length).isEqualTo(7);
+        assertThat(manifest[5]).isEqualTo("1"); // withApk
+        manifestFile.delete();
+    }
+
+    /**
+     * The manifest format is:
+     *
+     * <pre>
+     *     BACKUP_MANIFEST_VERSION
+     *     package name
+     *     package version code
+     *     platform version code
+     *     installer package name (can be empty)
+     *     boolean (1 if archive includes .apk, otherwise 0)
+     *     # of signatures N
+     *     N* (signature byte array in ascii format per Signature.toCharsString())
+     * </pre>
+     */
+    @Test
+    public void testBackupManifest_withSignatures_writesCorrectSignatures() throws Exception {
+        PackageInfo packageInfo =
+                createPackageInfo(TEST_PACKAGE, TEST_PACKAGE_INSTALLER, TEST_PACKAGE_VERSION_CODE);
+        packageInfo.signingInfo =
+                new SigningInfo(
+                        new SigningDetails(
+                                new Signature[] {new Signature("1234"), new Signature("5678")},
+                                SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V3,
+                                null,
+                                null,
+                                null));
+        File manifestFile = createFile(BACKUP_MANIFEST_FILENAME);
+
+        mBackupWriter.backupManifest(packageInfo, manifestFile, mFilesDir, /* withApk */ false);
+
+        byte[] manifestBytes = getWrittenBytes(mBackupDataOutputFile, /* includeTarHeader */ false);
+        String[] manifest = new String(manifestBytes, StandardCharsets.UTF_8).split("\n");
+        assertThat(manifest.length).isEqualTo(9);
+        assertThat(manifest[6]).isEqualTo("2"); // # of signatures
+        assertThat(manifest[7]).isEqualTo("1234"); // first signature
+        assertThat(manifest[8]).isEqualTo("5678"); // second signature
+        manifestFile.delete();
+    }
+
+    /**
+     * The manifest format is:
+     *
+     * <pre>
+     *     BACKUP_MANIFEST_VERSION
+     *     package name
+     *     package version code
+     *     platform version code
+     *     installer package name (can be empty)
+     *     boolean (1 if archive includes .apk, otherwise 0)
+     *     # of signatures N
+     *     N* (signature byte array in ascii format per Signature.toCharsString())
+     * </pre>
+     */
+    @Config(sdk = VERSION_CODES.O)
+    @Test
+    public void testBackupManifest_whenApiO_writesCorrectApi() throws Exception {
+        PackageInfo packageInfo =
+                createPackageInfo(TEST_PACKAGE, TEST_PACKAGE_INSTALLER, TEST_PACKAGE_VERSION_CODE);
+        File manifestFile = createFile(BACKUP_MANIFEST_FILENAME);
+
+        mBackupWriter.backupManifest(packageInfo, manifestFile, mFilesDir, /* withApk */ false);
+
+        byte[] manifestBytes = getWrittenBytes(mBackupDataOutputFile, /* includeTarHeader */ false);
+        String[] manifest = new String(manifestBytes, StandardCharsets.UTF_8).split("\n");
+        assertThat(manifest.length).isEqualTo(7);
+        assertThat(manifest[3]).isEqualTo(Integer.toString(VERSION_CODES.O)); // platform version
+        manifestFile.delete();
+    }
+
+    /**
+     * The manifest format is:
+     *
+     * <pre>
+     *     BACKUP_MANIFEST_VERSION
+     *     package name
+     *     package version code
+     *     platform version code
+     *     installer package name (can be empty)
+     *     boolean (1 if archive includes .apk, otherwise 0)
+     *     # of signatures N
+     *     N* (signature byte array in ascii format per Signature.toCharsString())
+     * </pre>
+     */
+    @Test
+    public void testBackupManifest_withoutInstallerPackage_writesEmptyInstaller() throws Exception {
+        PackageInfo packageInfo = createPackageInfo(TEST_PACKAGE, null, TEST_PACKAGE_VERSION_CODE);
+        File manifestFile = createFile(BACKUP_MANIFEST_FILENAME);
+
+        mBackupWriter.backupManifest(packageInfo, manifestFile, mFilesDir, /* withApk */ false);
+
+        byte[] manifestBytes = getWrittenBytes(mBackupDataOutputFile, /* includeTarHeader */ false);
+        String[] manifest = new String(manifestBytes, StandardCharsets.UTF_8).split("\n");
+        assertThat(manifest.length).isEqualTo(7);
+        assertThat(manifest[4]).isEqualTo(""); // installer package name
+        manifestFile.delete();
+    }
+
+    @Test
+    public void testBackupManifest_whenRunPreviouslyWithSameData_producesSameBytesOnSecondRun()
+            throws Exception {
+        PackageInfo packageInfo =
+                createPackageInfo(TEST_PACKAGE, TEST_PACKAGE_INSTALLER, TEST_PACKAGE_VERSION_CODE);
+        File manifestFile = createFile(BACKUP_MANIFEST_FILENAME);
+        mBackupWriter.backupManifest(packageInfo, manifestFile, mFilesDir, /* withApk */ false);
+        byte[] firstRunBytes = getWrittenBytes(mBackupDataOutputFile, /* includeTarHeader */ true);
+        // Simulate modifying the manifest file to ensure that file metadata does not change the
+        // backup bytes produced.
+        modifyFileMetadata(manifestFile);
+
+        mBackupWriter.backupManifest(packageInfo, manifestFile, mFilesDir, /* withApk */ false);
+
+        byte[] secondRunBytes = getWrittenBytes(mBackupDataOutputFile, /* includeTarHeader */ true);
+        assertThat(firstRunBytes).isEqualTo(secondRunBytes);
+        manifestFile.delete();
+    }
+
+    /**
+     * The widget data format with metadata is:
+     *
+     * <pre>
+     *     BACKUP_METADATA_VERSION
+     *     package name
+     *     4 : Integer token identifying the widget data blob.
+     *     4 : Integer size of the widget data.
+     *     N : Raw bytes of the widget data.
+     * </pre>
+     */
+    @Test
+    public void testBackupWidget_writesCorrectData() throws Exception {
+        PackageInfo packageInfo =
+                createPackageInfo(TEST_PACKAGE, TEST_PACKAGE_INSTALLER, TEST_PACKAGE_VERSION_CODE);
+        File metadataFile = createFile(BACKUP_METADATA_FILENAME);
+        byte[] widgetBytes = "widget".getBytes();
+
+        mBackupWriter.backupWidget(packageInfo, metadataFile, mFilesDir, widgetBytes);
+
+        byte[] writtenBytes = getWrittenBytes(mBackupDataOutputFile, /* includeTarHeader */ false);
+        String[] widgetData = new String(writtenBytes, StandardCharsets.UTF_8).split("\n");
+        assertThat(widgetData.length).isEqualTo(3);
+        // Metadata header
+        assertThat(widgetData[0]).isEqualTo(Integer.toString(BACKUP_METADATA_VERSION));
+        assertThat(widgetData[1]).isEqualTo(packageInfo.packageName);
+        // Widget data
+        ByteArrayOutputStream expectedBytes = new ByteArrayOutputStream();
+        DataOutputStream stream = new DataOutputStream(expectedBytes);
+        stream.writeInt(BACKUP_WIDGET_METADATA_TOKEN);
+        stream.writeInt(widgetBytes.length);
+        stream.write(widgetBytes);
+        stream.flush();
+        assertThat(widgetData[2]).isEqualTo(expectedBytes.toString());
+        metadataFile.delete();
+    }
+
+    @Test
+    public void testBackupWidget_withNullWidgetData_throwsNullPointerException() throws Exception {
+        PackageInfo packageInfo =
+                createPackageInfo(TEST_PACKAGE, TEST_PACKAGE_INSTALLER, TEST_PACKAGE_VERSION_CODE);
+        File metadataFile = createFile(BACKUP_METADATA_FILENAME);
+
+        expectThrows(
+                NullPointerException.class,
+                () ->
+                        mBackupWriter.backupWidget(
+                                packageInfo, metadataFile, mFilesDir, /* widgetData */ null));
+
+        metadataFile.delete();
+    }
+
+    @Test
+    public void testBackupWidget_withEmptyWidgetData_throwsIllegalArgumentException()
+            throws Exception {
+        PackageInfo packageInfo =
+                createPackageInfo(TEST_PACKAGE, TEST_PACKAGE_INSTALLER, TEST_PACKAGE_VERSION_CODE);
+        File metadataFile = createFile(BACKUP_METADATA_FILENAME);
+
+        expectThrows(
+                IllegalArgumentException.class,
+                () ->
+                        mBackupWriter.backupWidget(
+                                packageInfo, metadataFile, mFilesDir, new byte[0]));
+
+        metadataFile.delete();
+    }
+
+    @Test
+    public void testBackupWidget_whenRunPreviouslyWithSameData_producesSameBytesOnSecondRun()
+            throws Exception {
+        PackageInfo packageInfo =
+                createPackageInfo(TEST_PACKAGE, TEST_PACKAGE_INSTALLER, TEST_PACKAGE_VERSION_CODE);
+        File metadataFile = createFile(BACKUP_METADATA_FILENAME);
+        byte[] widgetBytes = "widget".getBytes();
+        mBackupWriter.backupWidget(packageInfo, metadataFile, mFilesDir, widgetBytes);
+        byte[] firstRunBytes = getWrittenBytes(mBackupDataOutputFile, /* includeTarHeader */ true);
+        // Simulate modifying the metadata file to ensure that file metadata does not change the
+        // backup bytes produced.
+        modifyFileMetadata(metadataFile);
+
+        mBackupWriter.backupWidget(packageInfo, metadataFile, mFilesDir, widgetBytes);
+
+        byte[] secondRunBytes = getWrittenBytes(mBackupDataOutputFile, /* includeTarHeader */ true);
+        assertThat(firstRunBytes).isEqualTo(secondRunBytes);
+        metadataFile.delete();
+    }
+
+    @Test
+    public void testBackupApk_writesCorrectBytesToOutput() throws Exception {
+        PackageInfo packageInfo =
+                createPackageInfo(TEST_PACKAGE, TEST_PACKAGE_INSTALLER, TEST_PACKAGE_VERSION_CODE);
+        byte[] apkBytes = "apk".getBytes();
+        File apkFile = createApkFileAndWrite(apkBytes);
+        packageInfo.applicationInfo = new ApplicationInfo();
+        packageInfo.applicationInfo.sourceDir = apkFile.getPath();
+
+        mBackupWriter.backupApk(packageInfo);
+
+        byte[] writtenBytes = getWrittenBytes(mBackupDataOutputFile, /* includeTarHeader */ false);
+        assertThat(writtenBytes).isEqualTo(apkBytes);
+        apkFile.delete();
+    }
+
+    @Test
+    public void testBackupObb_withObbData_writesCorrectBytesToOutput() throws Exception {
+        PackageInfo packageInfo =
+                createPackageInfo(TEST_PACKAGE, TEST_PACKAGE_INSTALLER, TEST_PACKAGE_VERSION_CODE);
+        File obbDir = createObbDirForPackage(packageInfo.packageName);
+        byte[] obbBytes = "obb".getBytes();
+        File obbFile = createObbFileAndWrite(obbDir, obbBytes);
+
+        mBackupWriter.backupObb(packageInfo);
+
+        byte[] writtenBytes = getWrittenBytes(mBackupDataOutputFile, /* includeTarHeader */ false);
+        assertThat(writtenBytes).isEqualTo(obbBytes);
+        obbFile.delete();
+    }
+
+    @Test
+    public void testBackupObb_withNoObbData_doesNotWriteBytesToOutput() throws Exception {
+        PackageInfo packageInfo =
+                createPackageInfo(TEST_PACKAGE, TEST_PACKAGE_INSTALLER, TEST_PACKAGE_VERSION_CODE);
+        File obbDir = createObbDirForPackage(packageInfo.packageName);
+        // No obb file created.
+
+        mBackupWriter.backupObb(packageInfo);
+
+        assertThat(mBackupDataOutputFile.length()).isEqualTo(0);
+    }
+
+    /**
+     * Creates a test package and registers it with the package manager. Also sets the installer
+     * package name if not {@code null}.
+     */
+    private PackageInfo createPackageInfo(
+            String packageName, @Nullable String installerPackageName, long versionCode) {
+        PackageInfo packageInfo = new PackageInfo();
+        packageInfo.packageName = packageName;
+        packageInfo.setLongVersionCode(versionCode);
+        mShadowPackageManager.addPackage(packageInfo);
+        if (installerPackageName != null) {
+            mShadowPackageManager.setInstallerPackageName(packageName, installerPackageName);
+        }
+        return packageInfo;
+    }
+
+    /**
+     * Reads backup data written to the {@code file} by {@link ShadowBackupDataOutput}. Uses {@link
+     * ShadowBackupDataInput} to parse the data. Follows the format used by {@link
+     * ShadowFullBackup#backupToTar(String, String, String, String, String, FullBackupDataOutput)}.
+     *
+     * @param includeTarHeader If {@code true}, returns the TAR header and data bytes combined.
+     *     Otherwise, only returns the data bytes.
+     */
+    private byte[] getWrittenBytes(File file, boolean includeTarHeader) throws IOException {
+        BackupDataInput input = new BackupDataInput(new FileInputStream(file).getFD());
+        input.readNextHeader();
+        int dataSize = input.getDataSize();
+
+        byte[] bytes;
+        if (includeTarHeader) {
+            bytes = new byte[dataSize + 512];
+            input.readEntityData(bytes, 0, dataSize + 512);
+        } else {
+            input.readEntityData(new byte[512], 0, 512); // skip TAR header
+            bytes = new byte[dataSize];
+            input.readEntityData(bytes, 0, dataSize);
+        }
+
+        return bytes;
+    }
+
+    private File createFile(String fileName) throws IOException {
+        File file = new File(mFilesDir, fileName);
+        file.createNewFile();
+        return file;
+    }
+
+    /**
+     * Sets the last modified time of the {@code file} to the current time to edit the file's
+     * metadata.
+     */
+    private void modifyFileMetadata(File file) throws IOException {
+        Files.setLastModifiedTime(file.toPath(), FileTime.fromMillis(System.currentTimeMillis()));
+    }
+
+    private File createApkFileAndWrite(byte[] data) throws IOException {
+        File apkFile = new File(mFilesDir, "apk");
+        apkFile.createNewFile();
+        Files.write(apkFile.toPath(), data);
+        return apkFile;
+    }
+
+    /** Creates an .obb file in the input directory. */
+    private File createObbFileAndWrite(File obbDir, byte[] data) throws IOException {
+        File obbFile = new File(obbDir, "obb");
+        obbFile.createNewFile();
+        Files.write(obbFile.toPath(), data);
+        return obbFile;
+    }
+
+    /**
+     * Creates a package specific obb data directory since the backup method checks for obb data
+     * there. See {@link Environment#buildExternalStorageAppObbDirs(String)}.
+     */
+    private File createObbDirForPackage(String packageName) {
+        ShadowEnvironment.addExternalDir("test");
+        Environment.UserEnvironment userEnv =
+                new Environment.UserEnvironment(UserHandle.USER_SYSTEM);
+        File obbDir =
+                new File(
+                        userEnv.getExternalDirs()[0],
+                        Environment.DIR_ANDROID + "/obb/" + packageName);
+        obbDir.mkdirs();
+        return obbDir;
+    }
+}
diff --git a/services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupReporterTest.java b/services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupReporterTest.java
new file mode 100644
index 0000000..21b90f1
--- /dev/null
+++ b/services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupReporterTest.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.backup.keyvalue;
+
+import static com.android.server.backup.keyvalue.KeyValueBackupReporter.TAG;
+import static com.android.server.backup.testing.TestUtils.assertLogcat;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.backup.IBackupManagerMonitor;
+import android.app.backup.IBackupObserver;
+import android.platform.test.annotations.Presubmit;
+import android.util.Log;
+
+import com.android.server.backup.BackupManagerService;
+import com.android.server.backup.remote.RemoteResult;
+import com.android.server.testing.FrameworkRobolectricTestRunner;
+import com.android.server.testing.SystemLoaderPackages;
+import com.android.server.testing.shadows.ShadowEventLog;
+import com.android.server.testing.shadows.ShadowSlog;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowLog;
+
+import java.lang.reflect.Field;
+
+@RunWith(FrameworkRobolectricTestRunner.class)
+@Config(
+        manifest = Config.NONE,
+        sdk = 26,
+        shadows = {ShadowEventLog.class, ShadowSlog.class})
+@SystemLoaderPackages({"com.android.server.backup"})
+@Presubmit
+public class KeyValueBackupReporterTest {
+    @Mock private BackupManagerService mBackupManagerService;
+    @Mock private IBackupObserver mObserver;
+    @Mock private IBackupManagerMonitor mMonitor;
+
+    private KeyValueBackupReporter mReporter;
+
+    @Before
+    public void setUp() throws Exception {
+        mReporter = new KeyValueBackupReporter(mBackupManagerService, mObserver, mMonitor);
+    }
+
+    @Test
+    public void testOnNewThread_logsCorrectly() throws Exception {
+        KeyValueBackupReporter.onNewThread("foo");
+
+        assertLogcat(TAG, Log.DEBUG);
+    }
+
+    @Test
+    public void testGetMonitor_returnsMonitor() throws Exception {
+        IBackupManagerMonitor monitor = mReporter.getMonitor();
+
+        assertThat(monitor).isEqualTo(mMonitor);
+    }
+
+    @Test
+    public void testGetObserver_returnsObserver() throws Exception {
+        IBackupObserver observer = mReporter.getObserver();
+
+        assertThat(observer).isEqualTo(mObserver);
+    }
+
+    @Test
+    public void testOnRevertTask_logsCorrectly() throws Exception {
+        setMoreDebug(true);
+
+        mReporter.onRevertTask();
+
+        assertLogcat(TAG, Log.INFO);
+    }
+
+    @Test
+    public void testOnRemoteCallReturned_logsCorrectly() throws Exception {
+        setMoreDebug(true);
+
+        mReporter.onRemoteCallReturned(RemoteResult.of(3), "onFoo()");
+
+        assertLogcat(TAG, Log.VERBOSE);
+        ShadowLog.LogItem log = ShadowLog.getLogsForTag(TAG).get(0);
+        assertThat(log.msg).contains("onFoo()");
+        assertThat(log.msg).contains("3");
+    }
+
+    /**
+     * HACK: We actually want {@link KeyValueBackupReporter#MORE_DEBUG} to be a constant to be able
+     * to strip those lines at build time. So, we have to do this to test :(
+     */
+    private static void setMoreDebug(boolean value)
+            throws NoSuchFieldException, IllegalAccessException {
+        if (KeyValueBackupReporter.MORE_DEBUG == value) {
+            return;
+        }
+        Field moreDebugField = KeyValueBackupReporter.class.getDeclaredField("MORE_DEBUG");
+        moreDebugField.setAccessible(true);
+        moreDebugField.set(null, value);
+    }
+}
diff --git a/services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java b/services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
index 9d6b8d5..b4bc9d1 100644
--- a/services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
+++ b/services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
@@ -36,7 +36,9 @@
 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.isFileNonEmpty;
 import static com.android.server.backup.testing.Utils.oneTimeIterable;
+import static com.android.server.backup.testing.Utils.transferStreamedData;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -60,6 +62,8 @@
 import static org.mockito.Mockito.when;
 import static org.robolectric.Shadows.shadowOf;
 import static org.robolectric.shadow.api.Shadow.extract;
+import static org.testng.Assert.fail;
+import static org.testng.Assert.expectThrows;
 
 import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
 import static java.util.Collections.emptyList;
@@ -104,13 +108,12 @@
 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.remote.RemoteCall;
 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;
@@ -121,6 +124,7 @@
 
 import com.google.common.truth.IterableSubject;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -184,6 +188,7 @@
     private ShadowLooper mShadowBackupLooper;
     private Handler mBackupHandler;
     private PowerManager.WakeLock mWakeLock;
+    private KeyValueBackupReporter mReporter;
     private ShadowPackageManager mShadowPackageManager;
     private FakeIBackupManager mBackupManager;
     private File mBaseStateDir;
@@ -220,7 +225,6 @@
         mShadowPackageManager = shadowOf(packageManager);
 
         mWakeLock = createBackupWakeLock(mApplication);
-
         mBackupManager = spy(FakeIBackupManager.class);
 
         // Needed to be able to use a real BMS instead of a mock
@@ -244,15 +248,19 @@
         mBackupHandler = mBackupManagerService.getBackupHandler();
         mShadowBackupLooper = shadowOf(mBackupHandler.getLooper());
         ShadowEventLog.setUp();
+        mReporter = spy(new KeyValueBackupReporter(mBackupManagerService, mObserver, mMonitor));
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        ShadowBackupDataInput.reset();
     }
 
     @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);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, true);
 
         runTask(task);
 
@@ -266,9 +274,7 @@
     public void testRunTask_whenQueueEmpty_releasesWakeLock() throws Exception {
         TransportMock transportMock = setUpInitializedTransport(mTransport);
         when(mBackupManagerService.getCurrentToken()).thenReturn(0L);
-        KeyValueBackupTask task =
-                createKeyValueBackupTask(
-                        transportMock.transportClient, mTransport.transportDirName, true);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, true);
 
         runTask(task);
 
@@ -279,9 +285,7 @@
     public void testRunTask_whenQueueEmpty_doesNotProduceData() throws Exception {
         TransportMock transportMock = setUpTransport(mTransport);
         when(mBackupManagerService.getCurrentToken()).thenReturn(0L);
-        KeyValueBackupTask task =
-                createKeyValueBackupTask(
-                        transportMock.transportClient, mTransport.transportDirName, true);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, true);
 
         runTask(task);
 
@@ -293,9 +297,7 @@
     public void testRunTask_whenQueueEmpty_doesNotCallTransport() throws Exception {
         TransportMock transportMock = setUpInitializedTransport(mTransport);
         when(mBackupManagerService.getCurrentToken()).thenReturn(0L);
-        KeyValueBackupTask task =
-                createKeyValueBackupTask(
-                        transportMock.transportClient, mTransport.transportDirName, true);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, true);
 
         runTask(task);
 
@@ -308,9 +310,7 @@
     public void testRunTask_whenQueueEmpty_notifiesCorrectly() throws Exception {
         TransportMock transportMock = setUpInitializedTransport(mTransport);
         when(mBackupManagerService.getCurrentToken()).thenReturn(0L);
-        KeyValueBackupTask task =
-                createKeyValueBackupTask(
-                        transportMock.transportClient, mTransport.transportDirName, true);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, true);
 
         runTask(task);
 
@@ -322,9 +322,7 @@
     @Test
     public void testRunTask_whenQueueEmpty_doesNotChangeStateFiles() throws Exception {
         TransportMock transportMock = setUpInitializedTransport(mTransport);
-        KeyValueBackupTask task =
-                createKeyValueBackupTask(
-                        transportMock.transportClient, mTransport.transportDirName, true);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, true);
         Files.write(getStateFile(mTransport, PM_PACKAGE), "pmState".getBytes());
         Files.write(getStateFile(mTransport, PACKAGE_1), "packageState".getBytes());
 
@@ -340,9 +338,7 @@
     public void testRunTask_whenOnePackageAndTransportUnavailable() throws Exception {
         TransportMock transportMock = setUpInitializedTransport(mTransport.unavailable());
         setUpAgentWithData(PACKAGE_1);
-        KeyValueBackupTask task =
-                createKeyValueBackupTask(
-                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
 
         runTask(task);
 
@@ -355,9 +351,7 @@
     public void testRunTask_whenOnePackage_logsBackupStartEvent() throws Exception {
         TransportMock transportMock = setUpInitializedTransport(mTransport);
         setUpAgentWithData(PACKAGE_1);
-        KeyValueBackupTask task =
-                createKeyValueBackupTask(
-                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
 
         runTask(task);
 
@@ -368,9 +362,7 @@
     public void testRunTask_whenOnePackage_releasesWakeLock() throws Exception {
         TransportMock transportMock = setUpInitializedTransport(mTransport);
         setUpAgentWithData(PACKAGE_1);
-        KeyValueBackupTask task =
-                createKeyValueBackupTask(
-                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
 
         runTask(task);
 
@@ -384,9 +376,7 @@
         mBackupManagerService.setCurrentToken(0L);
         when(transportMock.transport.getCurrentRestoreSet()).thenReturn(1234L);
         setUpAgentWithData(PACKAGE_1);
-        KeyValueBackupTask task =
-                createKeyValueBackupTask(
-                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
 
         runTask(task);
 
@@ -403,12 +393,7 @@
             throws Exception {
         TransportMock transportMock = setUpInitializedTransport(mTransport);
         AgentMock agentMock = setUpAgentWithData(PACKAGE_1);
-        KeyValueBackupTask task =
-                createKeyValueBackupTask(
-                        transportMock.transportClient,
-                        mTransport.transportDirName,
-                        false,
-                        PACKAGE_1);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, false, PACKAGE_1);
         Files.write(getStateFile(mTransport, PACKAGE_1), "oldState".getBytes());
 
         runTask(task);
@@ -421,12 +406,7 @@
             throws Exception {
         TransportMock transportMock = setUpInitializedTransport(mTransport);
         AgentMock agentMock = setUpAgentWithData(PACKAGE_1);
-        KeyValueBackupTask task =
-                createKeyValueBackupTask(
-                        transportMock.transportClient,
-                        mTransport.transportDirName,
-                        true,
-                        PACKAGE_1);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, true, PACKAGE_1);
         Files.write(getStateFile(mTransport, PACKAGE_1), "oldState".getBytes());
 
         runTask(task);
@@ -440,12 +420,7 @@
         setUpAgentWithData(PACKAGE_1);
         PackageManagerBackupAgent pmAgent = spy(createPmAgent());
         when(mBackupManagerService.makeMetadataAgent()).thenReturn(forward(pmAgent));
-        KeyValueBackupTask task =
-                createKeyValueBackupTask(
-                        transportMock.transportClient,
-                        mTransport.transportDirName,
-                        true,
-                        PACKAGE_1);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, true, PACKAGE_1);
 
         runTask(task);
 
@@ -459,12 +434,7 @@
         PackageManagerBackupAgent pmAgent = spy(createPmAgent());
         when(mBackupManagerService.makeMetadataAgent()).thenReturn(forward(pmAgent));
         KeyValueBackupTask task =
-                createKeyValueBackupTask(
-                        transportMock.transportClient,
-                        mTransport.transportDirName,
-                        true,
-                        PACKAGE_1,
-                        PM_PACKAGE);
+                createKeyValueBackupTask(transportMock, true, PACKAGE_1, PM_PACKAGE);
 
         runTask(task);
 
@@ -477,12 +447,7 @@
         setUpAgentWithData(PACKAGE_1);
         PackageManagerBackupAgent pmAgent = spy(createPmAgent());
         when(mBackupManagerService.makeMetadataAgent()).thenReturn(forward(pmAgent));
-        KeyValueBackupTask task =
-                createKeyValueBackupTask(
-                        transportMock.transportClient,
-                        mTransport.transportDirName,
-                        false,
-                        PACKAGE_1);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, false, PACKAGE_1);
 
         runTask(task);
 
@@ -495,9 +460,7 @@
         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);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
         deletePmStateFile();
         Files.write(getStateFile(mTransport, PACKAGE_2), "package2State".getBytes());
 
@@ -516,9 +479,7 @@
             throws Exception {
         TransportMock transportMock = setUpTransport(mTransport);
         setUpAgentsWithData(PACKAGE_1, PACKAGE_2);
-        KeyValueBackupTask task =
-                createKeyValueBackupTask(
-                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
         createPmStateFile();
         Files.write(getStateFile(mTransport, PACKAGE_2), "package2State".getBytes());
 
@@ -535,9 +496,7 @@
         when(transportMock.transport.initializeDevice())
                 .thenReturn(BackupTransport.TRANSPORT_ERROR);
         AgentMock agentMock = setUpAgentWithData(PACKAGE_1);
-        KeyValueBackupTask task =
-                createKeyValueBackupTask(
-                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
         deletePmStateFile();
 
         runTask(task);
@@ -556,9 +515,7 @@
         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);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
         deletePmStateFile();
 
         runTask(task);
@@ -575,9 +532,7 @@
     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);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
 
         runTask(task);
 
@@ -594,9 +549,7 @@
         TransportMock transportMock = setUpInitializedTransport(mTransport);
         PackageData packageData = fullBackupPackage(1);
         AgentMock agentMock = setUpAgentWithData(packageData);
-        KeyValueBackupTask task =
-                createKeyValueBackupTask(
-                        transportMock.transportClient, mTransport.transportDirName, packageData);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, packageData);
 
         runTask(task);
 
@@ -611,9 +564,7 @@
     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);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
 
         runTask(task);
 
@@ -627,9 +578,7 @@
     public void testRunTask_whenPackageUnknown() throws Exception {
         TransportMock transportMock = setUpInitializedTransport(mTransport);
         // Not calling setUpAgent()
-        KeyValueBackupTask task =
-                createKeyValueBackupTask(
-                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
 
         runTask(task);
 
@@ -655,9 +604,7 @@
                                     argThat(workSource -> workSource.get(0) == PACKAGE_1.uid));
                     verify(mBackupManagerService, never()).setWorkSource(null);
                 });
-        KeyValueBackupTask task =
-                createKeyValueBackupTask(
-                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
 
         runTask(task);
 
@@ -675,9 +622,7 @@
     public void testRunTask_whenAgentUnavailable() throws Exception {
         TransportMock transportMock = setUpInitializedTransport(mTransport);
         setUpAgent(PACKAGE_1.unavailable());
-        KeyValueBackupTask task =
-                createKeyValueBackupTask(
-                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
 
         runTask(task);
 
@@ -693,9 +638,7 @@
         doThrow(SecurityException.class)
                 .when(mBackupManagerService)
                 .bindToAgentSynchronous(argThat(applicationInfo(PACKAGE_1)), anyInt());
-        KeyValueBackupTask task =
-                createKeyValueBackupTask(
-                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
 
         runTask(task);
 
@@ -710,9 +653,7 @@
         when(transportMock.transport.getBackupQuota(PACKAGE_1.packageName, false))
                 .thenThrow(DeadObjectException.class);
         setUpAgent(PACKAGE_1);
-        KeyValueBackupTask task =
-                createKeyValueBackupTask(
-                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
 
         runTask(task);
 
@@ -727,9 +668,7 @@
         when(transportMock.transport.getBackupQuota(PACKAGE_1.packageName, false))
                 .thenThrow(DeadObjectException.class);
         setUpAgent(PACKAGE_1);
-        KeyValueBackupTask task =
-                createKeyValueBackupTask(
-                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
 
         runTask(task);
 
@@ -743,9 +682,7 @@
         when(transportMock.transport.getBackupQuota(PACKAGE_1.packageName, false))
                 .thenThrow(DeadObjectException.class);
         setUpAgent(PACKAGE_1);
-        KeyValueBackupTask task =
-                createKeyValueBackupTask(
-                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
         Files.write(getStateFile(mTransport, PACKAGE_1), "packageState".getBytes());
 
         runTask(task);
@@ -757,31 +694,26 @@
     }
 
     @Test
-    public void testRunTask_whenTransportGetBackupQuotaThrows_revertsOperation() throws Exception {
+    public void testRunTask_whenTransportGetBackupQuotaThrows_revertsTask() 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);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
 
         runTask(task);
 
-        verify(transportMock.transport).requestBackupTime();
-        assertBackupPendingFor(PACKAGE_1);
-        assertThat(KeyValueBackupJob.isScheduled()).isTrue();
+        assertTaskReverted(transportMock, PACKAGE_1);
     }
 
     /**
-     * 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.
+     * For local agents the exception is thrown in our stack, before {@link RemoteCall} has a chance
+     * to complete cleanly.
      */
+    // TODO: When RemoteCall spins up a new thread the assertions on this method should be the same
+    // as the methods below (non-local call).
     @Test
-    public void testRunTask_whenLocalAgentOnBackupThrows() throws Exception {
+    public void testRunTask_whenLocalAgentOnBackupThrows_setsNullWorkSource() throws Exception {
         TransportMock transportMock = setUpInitializedTransport(mTransport);
         AgentMock agentMock = setUpAgent(PACKAGE_1);
         agentOnBackupDo(
@@ -789,31 +721,129 @@
                 (oldState, dataOutput, newState) -> {
                     throw new RuntimeException();
                 });
-        KeyValueBackupTask task =
-                createKeyValueBackupTask(
-                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
 
         runTask(task);
 
         verify(mBackupManagerService).setWorkSource(null);
+    }
+
+    @Test
+    public void testRunTask_whenLocalAgentOnBackupThrows_reportsCorrectly() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        AgentMock agentMock = setUpAgent(PACKAGE_1);
+        agentOnBackupDo(
+                agentMock,
+                (oldState, dataOutput, newState) -> {
+                    throw new RuntimeException();
+                });
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
+
+        runTask(task);
+
         verify(mObserver).onResult(PACKAGE_1.packageName, ERROR_AGENT_FAILURE);
         verify(mObserver).backupFinished(SUCCESS);
+        verify(mReporter)
+                .onCallAgentDoBackupError(
+                        eq(PACKAGE_1.packageName), eq(true), any(RuntimeException.class));
         assertEventLogged(
                 EventLogTags.BACKUP_AGENT_FAILURE,
                 PACKAGE_1.packageName,
                 new RuntimeException().toString());
+    }
+
+    @Test
+    public void testRunTask_whenLocalAgentOnBackupThrows_doesNotUpdateBookkeping()
+            throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        AgentMock agentMock = setUpAgent(PACKAGE_1);
+        agentOnBackupDo(
+                agentMock,
+                (oldState, dataOutput, newState) -> {
+                    throw new RuntimeException();
+                });
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
+
+        runTask(task);
+
         assertBackupPendingFor(PACKAGE_1);
     }
 
     @Test
+    public void testRunTask_whenAgentOnBackupThrows_reportsCorrectly() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        AgentMock agentMock = setUpAgent(PACKAGE_1);
+        remoteAgentOnBackupThrows(
+                agentMock,
+                (oldState, dataOutput, newState) -> {
+                    throw new RuntimeException();
+                });
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
+
+        runTask(task);
+
+        verify(mReporter).onAgentResultError(argThat(packageInfo(PACKAGE_1)));
+    }
+
+    @Test
+    public void testRunTask_whenAgentOnBackupThrows_updatesBookkeeping() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        AgentMock agentMock = setUpAgent(PACKAGE_1);
+        remoteAgentOnBackupThrows(
+                agentMock,
+                (oldState, dataOutput, newState) -> {
+                    throw new RuntimeException();
+                });
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
+
+        runTask(task);
+
+        assertBackupNotPendingFor(PACKAGE_1);
+    }
+
+    @Test
+    public void testRunTask_whenAgentOnBackupThrows_doesNotCallTransport() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        AgentMock agentMock = setUpAgent(PACKAGE_1);
+        remoteAgentOnBackupThrows(
+                agentMock,
+                (oldState, dataOutput, newState) -> {
+                    throw new RuntimeException();
+                });
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
+
+        runTask(task);
+
+        verify(transportMock.transport, never())
+                .performBackup(argThat(packageInfo(PACKAGE_1)), any(), anyInt());
+    }
+
+    @Test
+    public void testRunTask_whenAgentOnBackupThrows_updatesFilesAndCleansUp() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        AgentMock agentMock = setUpAgent(PACKAGE_1);
+        remoteAgentOnBackupThrows(
+                agentMock,
+                (oldState, dataOutput, newState) -> {
+                    throw new RuntimeException();
+                });
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
+        Files.write(getStateFile(mTransport, PACKAGE_1), "oldState".getBytes());
+
+        runTask(task);
+
+        assertThat(Files.readAllBytes(getStateFile(mTransport, PACKAGE_1)))
+                .isEqualTo("oldState".getBytes());
+        assertCleansUpFilesAndAgent(mTransport, 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);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
 
         runTask(task);
 
@@ -825,9 +855,7 @@
     public void testRunTask_whenTransportDoesNotProvidesFlags() throws Exception {
         TransportMock transportMock = setUpInitializedTransport(mTransport);
         AgentMock agentMock = setUpAgent(PACKAGE_1);
-        KeyValueBackupTask task =
-                createKeyValueBackupTask(
-                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
 
         runTask(task);
 
@@ -843,12 +871,7 @@
         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);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1, PACKAGE_2);
 
         runTask(task);
 
@@ -860,9 +883,7 @@
     public void testRunTask_whenTransportChangeFlagsAfterTaskCreation() throws Exception {
         TransportMock transportMock = setUpInitializedTransport(mTransport);
         AgentMock agentMock = setUpAgent(PACKAGE_1);
-        KeyValueBackupTask task =
-                createKeyValueBackupTask(
-                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
         int flags = BackupAgent.FLAG_CLIENT_SIDE_ENCRYPTION_ENABLED;
         when(transportMock.transport.getTransportFlags()).thenReturn(flags);
 
@@ -883,9 +904,7 @@
                     writeData(dataOutput, prohibitedChar + "key", "data".getBytes());
                     writeState(newState, "newState".getBytes());
                 });
-        KeyValueBackupTask task =
-                createKeyValueBackupTask(
-                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
 
         runTask(task);
 
@@ -894,7 +913,7 @@
     }
 
     @Test
-    public void testRunTask_whenAgentUsesProhibitedKey_updatesAndCleansUpFiles() throws Exception {
+    public void testRunTask_whenAgentUsesProhibitedKey_updatesFilesAndCleansUp() throws Exception {
         TransportMock transportMock = setUpInitializedTransport(mTransport);
         AgentMock agentMock = setUpAgent(PACKAGE_1);
         agentOnBackupDo(
@@ -904,17 +923,14 @@
                     writeData(dataOutput, prohibitedChar + "key", "data".getBytes());
                     writeState(newState, "newState".getBytes());
                 });
-        KeyValueBackupTask task =
-                createKeyValueBackupTask(
-                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, 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();
+        assertCleansUpFilesAndAgent(mTransport, PACKAGE_1);
     }
 
     @Test
@@ -928,9 +944,7 @@
                     writeData(dataOutput, prohibitedChar + "key", "data".getBytes());
                     writeState(newState, "newState".getBytes());
                 });
-        KeyValueBackupTask task =
-                createKeyValueBackupTask(
-                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
         Files.write(getStateFile(mTransport, PACKAGE_1), "oldState".getBytes());
 
         runTask(task);
@@ -950,9 +964,7 @@
                     writeData(dataOutput, prohibitedChar + "key", "data".getBytes());
                     writeState(newState, "newState".getBytes());
                 });
-        KeyValueBackupTask task =
-                createKeyValueBackupTask(
-                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
         Files.write(getStateFile(mTransport, PACKAGE_1), "oldState".getBytes());
 
         runTask(task);
@@ -973,9 +985,7 @@
                     writeData(dataOutput, prohibitedChar + "key", "data".getBytes());
                     writeState(newState, "newState".getBytes());
                 });
-        KeyValueBackupTask task =
-                createKeyValueBackupTask(
-                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
         Files.write(getStateFile(mTransport, PACKAGE_1), "oldState".getBytes());
 
         runTask(task);
@@ -1003,12 +1013,7 @@
                     writeData(dataOutput, "key", "data".getBytes());
                     writeState(newState, "newState".getBytes());
                 });
-        KeyValueBackupTask task =
-                createKeyValueBackupTask(
-                        transportMock.transportClient,
-                        mTransport.transportDirName,
-                        PACKAGE_1,
-                        PACKAGE_2);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1, PACKAGE_2);
 
         runTask(task);
 
@@ -1028,9 +1033,7 @@
                 (oldState, dataOutput, newState) -> {
                     // No-op
                 });
-        KeyValueBackupTask task =
-                createKeyValueBackupTask(
-                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
 
         runTask(task);
 
@@ -1047,9 +1050,7 @@
                 (oldState, dataOutput, newState) -> {
                     // No-op
                 });
-        KeyValueBackupTask task =
-                createKeyValueBackupTask(
-                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
 
         runTask(task);
 
@@ -1066,9 +1067,7 @@
                 (oldState, dataOutput, newState) -> {
                     // No-op
                 });
-        KeyValueBackupTask task =
-                createKeyValueBackupTask(
-                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
 
         runTask(task);
 
@@ -1085,9 +1084,7 @@
                 (oldState, dataOutput, newState) -> {
                     // No-op
                 });
-        KeyValueBackupTask task =
-                createKeyValueBackupTask(
-                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
 
         runTask(task);
 
@@ -1095,7 +1092,7 @@
     }
 
     @Test
-    public void testRunTask_whenAgentDoesNotWriteData_updatesAndCleansUpFiles() throws Exception {
+    public void testRunTask_whenAgentDoesNotWriteData_updatesFilesAndCleansUp() throws Exception {
         TransportMock transportMock = setUpInitializedTransport(mTransport);
         AgentMock agentMock = setUpAgent(PACKAGE_1);
         agentOnBackupDo(
@@ -1103,15 +1100,12 @@
                 (oldState, dataOutput, newState) -> {
                     // No-op
                 });
-        KeyValueBackupTask task =
-                createKeyValueBackupTask(
-                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, 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();
+        assertCleansUpFilesAndAgent(mTransport, PACKAGE_1);
     }
 
     @Test
@@ -1130,9 +1124,7 @@
                     writeData(dataOutput, "key2", "data2".getBytes());
                     writeState(newState, "newState".getBytes());
                 });
-        KeyValueBackupTask task =
-                createKeyValueBackupTask(
-                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
 
         runTask(task);
 
@@ -1155,9 +1147,7 @@
                         argThat(packageInfo(PACKAGE_1)), any(), anyInt()))
                 .thenReturn(BackupTransport.TRANSPORT_OK);
         setUpAgentWithData(PACKAGE_1);
-        KeyValueBackupTask task =
-                createKeyValueBackupTask(
-                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
 
         runTask(task);
 
@@ -1166,7 +1156,7 @@
     }
 
     @Test
-    public void testRunTask_whenFinishBackupSucceeds_updatesAndCleansUpFiles() throws Exception {
+    public void testRunTask_whenFinishBackupSucceeds_updatesFilesAndCleansUp() throws Exception {
         TransportMock transportMock = setUpInitializedTransport(mTransport);
         when(transportMock.transport.finishBackup()).thenReturn(BackupTransport.TRANSPORT_OK);
         AgentMock agentMock = setUpAgent(PACKAGE_1);
@@ -1176,16 +1166,13 @@
                     writeData(dataOutput, "key", "data".getBytes());
                     writeState(newState, "newState".getBytes());
                 });
-        KeyValueBackupTask task =
-                createKeyValueBackupTask(
-                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, 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();
+        assertCleansUpFilesAndAgent(mTransport, PACKAGE_1);
     }
 
     @Test
@@ -1196,9 +1183,7 @@
         when(transportMock.transport.performBackup(
                         argThat(packageInfo(PACKAGE_1)), any(), anyInt()))
                 .then(copyBackupDataTo(backupData));
-        KeyValueBackupTask task =
-                createKeyValueBackupTask(
-                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
 
         runTask(task);
 
@@ -1210,9 +1195,7 @@
     public void testRunTask_whenFinishBackupSucceeds_notifiesCorrectly() throws Exception {
         TransportMock transportMock = setUpInitializedTransport(mTransport);
         setUpAgentWithData(PACKAGE_1);
-        KeyValueBackupTask task =
-                createKeyValueBackupTask(
-                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
 
         runTask(task);
 
@@ -1226,9 +1209,7 @@
     public void testRunTask_whenFinishBackupSucceeds_updatesBookkeeping() throws Exception {
         TransportMock transportMock = setUpInitializedTransport(mTransport);
         setUpAgentWithData(PACKAGE_1);
-        KeyValueBackupTask task =
-                createKeyValueBackupTask(
-                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
 
         runTask(task);
 
@@ -1242,9 +1223,7 @@
                         argThat(packageInfo(PACKAGE_1)), any(), anyInt()))
                 .thenReturn(BackupTransport.TRANSPORT_PACKAGE_REJECTED);
         setUpAgentWithData(PACKAGE_1);
-        KeyValueBackupTask task =
-                createKeyValueBackupTask(
-                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
 
         runTask(task);
 
@@ -1253,23 +1232,20 @@
     }
 
     @Test
-    public void testRunTask_whenTransportRejectsPackage_updatesAndCleansUpFiles() throws Exception {
+    public void testRunTask_whenTransportRejectsPackage_updatesFilesAndCleansUp() 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);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, 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();
+        assertCleansUpFilesAndAgent(mTransport, PACKAGE_1);
     }
 
     @Test
@@ -1279,9 +1255,7 @@
                         argThat(packageInfo(PACKAGE_1)), any(), anyInt()))
                 .thenReturn(BackupTransport.TRANSPORT_PACKAGE_REJECTED);
         setUpAgentWithData(PACKAGE_1);
-        KeyValueBackupTask task =
-                createKeyValueBackupTask(
-                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
 
         runTask(task);
 
@@ -1296,9 +1270,7 @@
                         argThat(packageInfo(PACKAGE_1)), any(), anyInt()))
                 .thenReturn(BackupTransport.TRANSPORT_PACKAGE_REJECTED);
         setUpAgentWithData(PACKAGE_1);
-        KeyValueBackupTask task =
-                createKeyValueBackupTask(
-                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
 
         runTask(task);
 
@@ -1314,9 +1286,7 @@
                         argThat(packageInfo(PACKAGE_1)), any(), anyInt()))
                 .thenReturn(BackupTransport.TRANSPORT_PACKAGE_REJECTED);
         setUpAgentWithData(PACKAGE_1);
-        KeyValueBackupTask task =
-                createKeyValueBackupTask(
-                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
 
         runTask(task);
 
@@ -1333,12 +1303,7 @@
                         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);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1, PACKAGE_2);
 
         runTask(task);
 
@@ -1357,12 +1322,7 @@
                         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);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1, PACKAGE_2);
 
         runTask(task);
 
@@ -1372,7 +1332,8 @@
     }
 
     @Test
-    public void testRunTask_whenTransportReturnsQuotaExceeded() throws Exception {
+    public void testRunTask_whenTransportReturnsQuotaExceeded_callsAgentOnQuotaExceeded()
+            throws Exception {
         TransportMock transportMock = setUpInitializedTransport(mTransport);
         when(transportMock.transport.getBackupQuota(PACKAGE_1.packageName, false))
                 .thenReturn(1234L);
@@ -1380,19 +1341,206 @@
                         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);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
+
+        runTask(task);
+
+        InOrder inOrder = inOrder(agentMock.agent, mBackupManagerService);
+        inOrder.verify(agentMock.agent).onQuotaExceeded(anyLong(), eq(1234L));
+        inOrder.verify(mBackupManagerService).unbindAgent(argThat(applicationInfo(PACKAGE_1)));
+    }
+
+    @Test
+    public void testRunTask_whenTransportReturnsQuotaExceeded_updatesBookkeeping()
+            throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        when(transportMock.transport.performBackup(
+                        argThat(packageInfo(PACKAGE_1)), any(), anyInt()))
+                .thenReturn(BackupTransport.TRANSPORT_QUOTA_EXCEEDED);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
+
+        runTask(task);
+
+        assertBackupNotPendingFor(PACKAGE_1);
+    }
+
+    @Test
+    public void testRunTask_whenTransportReturnsQuotaExceeded_notifiesAndLogs() 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, 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_whenTransportReturnsQuotaExceeded_cleansUpFiles() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        when(transportMock.transport.performBackup(
+                        argThat(packageInfo(PACKAGE_1)), any(), anyInt()))
+                .thenReturn(BackupTransport.TRANSPORT_QUOTA_EXCEEDED);
+        setUpAgentWithData(PACKAGE_1);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
+
+        runTask(task);
+
+        assertCleansUpFilesAndAgent(mTransport, PACKAGE_1);
+    }
+
+    @Test
+    public void testRunTask_whenTransportReturnsNotInitialized_cleansUpFiles() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        when(transportMock.transport.performBackup(
+                        argThat(packageInfo(PACKAGE_1)), any(), anyInt()))
+                .thenReturn(BackupTransport.TRANSPORT_NOT_INITIALIZED);
+        setUpAgentWithData(PACKAGE_1);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
+
+        runTask(task);
+
+        assertThat(isFileNonEmpty(getStateFile(mTransport, PACKAGE_1))).isFalse();
+        assertCleansUpFilesAndAgent(mTransport, PACKAGE_1);
+    }
+
+    @Test
+    public void testRunTask_whenTransportReturnsNotInitialized_reportsCorrectly() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        when(transportMock.transport.performBackup(
+                        argThat(packageInfo(PACKAGE_1)), any(), anyInt()))
+                .thenReturn(BackupTransport.TRANSPORT_NOT_INITIALIZED);
+        setUpAgentWithData(PACKAGE_1);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
+
+        runTask(task);
+
+        verify(mReporter).onPackageBackupTransportFailure(PACKAGE_1.packageName);
+        verify(mReporter).onTransportNotInitialized();
+        verify(mReporter).onBackupFinished(BackupManager.ERROR_TRANSPORT_ABORTED);
+    }
+
+    @Test
+    public void testRunTask_whenTransportReturnsNotInitializedForPm_reportsCorrectly()
+            throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        when(transportMock.transport.performBackup(
+                        argThat(packageInfo(PM_PACKAGE)), any(), anyInt()))
+                .thenReturn(BackupTransport.TRANSPORT_NOT_INITIALIZED);
+        setUpAgentWithData(PACKAGE_1);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
+
+        runTask(task);
+
+        verify(mReporter).onPackageBackupTransportFailure(PM_PACKAGE.packageName);
+        verify(mReporter).onTransportNotInitialized();
+        verify(mReporter).onBackupFinished(BackupManager.ERROR_TRANSPORT_ABORTED);
+    }
+
+    @Test
+    public void testRunTask_whenTransportReturnsNotInitialized_doesNotCallSecondAgent()
+            throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        when(transportMock.transport.performBackup(
+                        argThat(packageInfo(PACKAGE_1)), any(), anyInt()))
+                .thenReturn(BackupTransport.TRANSPORT_NOT_INITIALIZED);
+        setUpAgentWithData(PACKAGE_1);
+        AgentMock agentMock = setUpAgentWithData(PACKAGE_2);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1, PACKAGE_2);
+
+        runTask(task);
+
+        verify(agentMock.agent, never()).onBackup(any(), any(), any());
+    }
+
+    @Test
+    public void testRunTask_whenTransportReturnsNotInitialized_revertsTask() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        when(transportMock.transport.performBackup(
+                        argThat(packageInfo(PACKAGE_1)), any(), anyInt()))
+                .thenReturn(BackupTransport.TRANSPORT_NOT_INITIALIZED);
+        setUpAgentWithData(PACKAGE_1);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
+
+        runTask(task);
+
+        assertTaskReverted(transportMock, PACKAGE_1);
+    }
+
+    @Test
+    public void testRunTask_whenTransportReturnsNotInitialized_triggersTransportInitialization()
+            throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        when(transportMock.transport.performBackup(
+                        argThat(packageInfo(PACKAGE_1)), any(), anyInt()))
+                .thenReturn(BackupTransport.TRANSPORT_NOT_INITIALIZED);
+        setUpAgentWithData(PACKAGE_1);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
+
+        runTask(task);
+
+        assertThat(mBackupManagerService.getPendingInits()).contains(mTransport.transportName);
+        verify(mBackupManagerService).backupNow();
+    }
+
+    @Test
+    public void testRunTask_whenTransportReturnsNotInitialized_cleansUpPmStateFile()
+            throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        when(transportMock.transport.performBackup(
+                        argThat(packageInfo(PACKAGE_1)), any(), anyInt()))
+                .thenReturn(BackupTransport.TRANSPORT_NOT_INITIALIZED);
+        setUpAgentWithData(PACKAGE_1);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
+        Files.write(getStateFile(mTransport, PM_PACKAGE), "pmState".getBytes());
+
+        runTask(task);
+
+        assertThat(Files.exists(getStateFile(mTransport, PM_PACKAGE))).isFalse();
+    }
+
+    @Test
+    public void testRunTask_whenTransportReturnsNotInitializedForPm_cleansUpPmStateFile()
+            throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        when(transportMock.transport.performBackup(
+                        argThat(packageInfo(PM_PACKAGE)), any(), anyInt()))
+                .thenReturn(BackupTransport.TRANSPORT_NOT_INITIALIZED);
+        setUpAgentWithData(PACKAGE_1);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
+        Files.write(getStateFile(mTransport, PM_PACKAGE), "pmState".getBytes());
+
+        runTask(task);
+
+        assertThat(Files.exists(getStateFile(mTransport, PM_PACKAGE))).isFalse();
+    }
+
+    @Test
+    public void
+            testRunTask_whenTransportReturnsNotInitializedAndThrowsWhenQueryingName_reportsCorrectly()
+                    throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        when(transportMock.transport.performBackup(any(), any(), anyInt()))
+                .thenReturn(BackupTransport.TRANSPORT_NOT_INITIALIZED);
+        // First one is in startTask(), second is the one we want.
+        when(transportMock.transport.name())
+                .thenReturn(mTransport.transportName)
+                .thenThrow(DeadObjectException.class);
+        setUpAgentWithData(PACKAGE_1);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
+
+        runTask(task);
+
+        verify(mReporter).onPendingInitializeTransportError(any(DeadObjectException.class));
+        verify(mReporter).onBackupFinished(ERROR_TRANSPORT_ABORTED);
     }
 
     @Test
@@ -1403,12 +1551,7 @@
                         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);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, true, PACKAGE_1);
         // Delete to be non-incremental
         Files.deleteIfExists(getStateFile(mTransport, PACKAGE_1));
 
@@ -1451,12 +1594,7 @@
                         writeState(newState, "stateForNonIncremental".getBytes());
                     }
                 });
-        KeyValueBackupTask task =
-                createKeyValueBackupTask(
-                        transportMock.transportClient,
-                        mTransport.transportDirName,
-                        false,
-                        PACKAGE_1);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, false, PACKAGE_1);
         // Write state to be incremental
         Files.write(getStateFile(mTransport, PACKAGE_1), "oldState".getBytes());
 
@@ -1490,9 +1628,7 @@
                         argThat(packageInfo(PACKAGE_1)), any(), anyInt()))
                 .thenReturn(BackupTransport.TRANSPORT_ERROR);
         setUpAgentWithData(PACKAGE_1);
-        KeyValueBackupTask task =
-                createKeyValueBackupTask(
-                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
 
         runTask(task);
 
@@ -1508,9 +1644,7 @@
                         argThat(packageInfo(PACKAGE_1)), any(), anyInt()))
                 .thenReturn(BackupTransport.TRANSPORT_ERROR);
         setUpAgentWithData(PACKAGE_1);
-        KeyValueBackupTask task =
-                createKeyValueBackupTask(
-                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
 
         runTask(task);
 
@@ -1518,42 +1652,34 @@
     }
 
     @Test
-    public void testRunTask_whenTransportReturnsError_revertsOperation() throws Exception {
+    public void testRunTask_whenTransportReturnsError_revertsTask() 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);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
 
         runTask(task);
 
-        verify(transportMock.transport).requestBackupTime();
-        assertBackupPendingFor(PACKAGE_1);
-        assertThat(KeyValueBackupJob.isScheduled()).isTrue();
+        assertTaskReverted(transportMock, PACKAGE_1);
     }
 
     @Test
-    public void testRunTask_whenTransportReturnsError_updatesAndCleansUpFiles() throws Exception {
+    public void testRunTask_whenTransportReturnsError_updatesFilesAndCleansUp() 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);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, 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();
+        assertCleansUpFilesAndAgent(mTransport, PACKAGE_1);
     }
 
     @Test
@@ -1562,9 +1688,7 @@
         when(transportMock.transport.getBackupQuota(PM_PACKAGE.packageName, false))
                 .thenThrow(DeadObjectException.class);
         setUpAgentWithData(PACKAGE_1);
-        KeyValueBackupTask task =
-                createKeyValueBackupTask(
-                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
 
         runTask(task);
 
@@ -1581,9 +1705,7 @@
         TransportMock transportMock = setUpInitializedTransport(mTransport);
         PackageManagerBackupAgent pmAgent = createThrowingPmAgent(new RuntimeException());
         when(mBackupManagerService.makeMetadataAgent()).thenReturn(pmAgent);
-        KeyValueBackupTask task =
-                createKeyValueBackupTask(
-                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
 
         runTask(task);
 
@@ -1599,26 +1721,71 @@
     public void testRunTask_whenBackupRunning_doesNotThrow() throws Exception {
         TransportMock transportMock = setUpInitializedTransport(mTransport);
         when(mBackupManagerService.isBackupOperationInProgress()).thenReturn(true);
-        KeyValueBackupTask task =
-                createKeyValueBackupTask(
-                        transportMock.transportClient, mTransport.transportDirName);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock);
 
         runTask(task);
     }
 
     @Test
+    public void testRunTask_whenReadingBackupDataThrows_reportsCorrectly() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        setUpAgentWithData(PACKAGE_1);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
+        // We don't validate PM's data, so it will only throw in PACKAGE_1
+        ShadowBackupDataInput.throwInNextHeaderRead();
+
+        runTask(task);
+
+        verify(mReporter).onReadAgentDataError(eq(PACKAGE_1.packageName), any());
+    }
+
+    @Test
+    public void testRunTask_whenReadingBackupDataThrows_doesNotCallTransport() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        setUpAgentWithData(PACKAGE_1);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
+        ShadowBackupDataInput.throwInNextHeaderRead();
+
+        runTask(task);
+
+        verify(transportMock.transport, never())
+                .performBackup(argThat(packageInfo(PACKAGE_1)), any(), anyInt());
+    }
+
+    @Test
+    public void testRunTask_whenReadingBackupDataThrows_doesNotCallSecondAgent() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        setUpAgentWithData(PACKAGE_1);
+        AgentMock agentMock = setUpAgentWithData(PACKAGE_2);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1, PACKAGE_2);
+        ShadowBackupDataInput.throwInNextHeaderRead();
+
+        runTask(task);
+
+        verify(agentMock.agent, never()).onBackup(any(), any(), any());
+    }
+
+    @Test
+    public void testRunTask_whenReadingBackupDataThrows_cleansUpAndRevertsTask() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        setUpAgentsWithData(PACKAGE_1, PACKAGE_2);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1, PACKAGE_2);
+        ShadowBackupDataInput.throwInNextHeaderRead();
+
+        runTask(task);
+
+        assertCleansUpFiles(mTransport, PACKAGE_2);
+        assertTaskReverted(transportMock, PACKAGE_1, PACKAGE_2);
+    }
+
+    @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);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1, PACKAGE_2);
         agentOnBackupDo(
                 agentMock,
                 (oldState, dataOutput, newState) -> {
@@ -1641,9 +1808,7 @@
             throws Exception {
         TransportMock transportMock = setUpInitializedTransport(mTransport);
         AgentMock agentMock = setUpAgent(PACKAGE_1);
-        KeyValueBackupTask task =
-                createKeyValueBackupTask(
-                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
         agentOnBackupDo(
                 agentMock,
                 (oldState, dataOutput, newState) -> {
@@ -1667,9 +1832,7 @@
             throws Exception {
         TransportMock transportMock = setUpInitializedTransport(mTransport);
         setUpAgentWithData(PACKAGE_1);
-        KeyValueBackupTask task =
-                createKeyValueBackupTask(
-                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
         when(transportMock.transport.performBackup(
                         argThat(packageInfo(PACKAGE_1)), any(), anyInt()))
                 .thenAnswer(
@@ -1695,12 +1858,7 @@
         TransportMock transportMock = setUpInitializedTransport(mTransport);
         setUpAgentWithData(PACKAGE_1);
         AgentMock agentMock = setUpAgent(PACKAGE_2);
-        KeyValueBackupTask task =
-                createKeyValueBackupTask(
-                        transportMock.transportClient,
-                        mTransport.transportDirName,
-                        PACKAGE_1,
-                        PACKAGE_2);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1, PACKAGE_2);
         agentOnBackupDo(
                 agentMock,
                 (oldState, dataOutput, newState) -> {
@@ -1727,12 +1885,7 @@
                     throws Exception {
         TransportMock transportMock = setUpInitializedTransport(mTransport);
         setUpAgentsWithData(PACKAGE_1, PACKAGE_2);
-        KeyValueBackupTask task =
-                createKeyValueBackupTask(
-                        transportMock.transportClient,
-                        mTransport.transportDirName,
-                        PACKAGE_1,
-                        PACKAGE_2);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1, PACKAGE_2);
         when(transportMock.transport.performBackup(
                         argThat(packageInfo(PACKAGE_1)), any(), anyInt()))
                 .thenAnswer(
@@ -1757,9 +1910,7 @@
     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);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
         task.markCancel();
 
         runTask(task);
@@ -1773,9 +1924,7 @@
     public void testWaitCancel_afterCancelledTaskFinished_returns() throws Exception {
         TransportMock transportMock = setUpInitializedTransport(mTransport);
         setUpAgentWithData(PACKAGE_1);
-        KeyValueBackupTask task =
-                createKeyValueBackupTask(
-                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
         task.markCancel();
         runTask(task);
 
@@ -1783,13 +1932,12 @@
     }
 
     @Test
-    public void testWaitCancel_whenMarkCancelDuringAgentOnBackup_unregistersTask() throws Exception {
+    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);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
         agentOnBackupDo(
                 agentMock,
                 (oldState, dataOutput, newState) -> {
@@ -1816,14 +1964,35 @@
     public void testMarkCancel_afterTaskFinished_returns() throws Exception {
         TransportMock transportMock = setUpInitializedTransport(mTransport);
         setUpAgentWithData(PACKAGE_1);
-        KeyValueBackupTask task =
-                createKeyValueBackupTask(
-                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
         runTask(task);
 
         task.markCancel();
     }
 
+    @Test
+    public void testHandleCancel_callsMarkCancelAndWaitCancel() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        setUpAgentWithData(PACKAGE_1);
+        KeyValueBackupTask task = spy(createKeyValueBackupTask(transportMock, PACKAGE_1));
+        doNothing().when(task).waitCancel();
+
+        task.handleCancel(true);
+
+        InOrder inOrder = inOrder(task);
+        inOrder.verify(task).markCancel();
+        inOrder.verify(task).waitCancel();
+    }
+
+    @Test
+    public void testHandleCancel_whenCancelAllFalse_throws() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        setUpAgentWithData(PACKAGE_1);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
+
+        expectThrows(IllegalArgumentException.class, () -> task.handleCancel(false));
+    }
+
     private void runTask(KeyValueBackupTask task) {
         // Pretend we are not on the main-thread to prevent RemoteCall from complaining
         mShadowMainLooper.setCurrentThread(false);
@@ -1997,15 +2166,12 @@
     }
 
     private KeyValueBackupTask createKeyValueBackupTask(
-            TransportClient transportClient, String transportDirName, PackageData... packages) {
-        return createKeyValueBackupTask(transportClient, transportDirName, false, packages);
+            TransportMock transportMock, PackageData... packages) {
+        return createKeyValueBackupTask(transportMock, false, packages);
     }
 
     private KeyValueBackupTask createKeyValueBackupTask(
-            TransportClient transportClient,
-            String transportDirName,
-            boolean nonIncremental,
-            PackageData... packages) {
+            TransportMock transportMock, boolean nonIncremental, PackageData... packages) {
         List<String> queue =
                 Stream.of(packages).map(packageData -> packageData.packageName).collect(toList());
         mBackupManagerService.getPendingBackups().clear();
@@ -2015,12 +2181,11 @@
         KeyValueBackupTask task =
                 new KeyValueBackupTask(
                         mBackupManagerService,
-                        transportClient,
-                        transportDirName,
+                        transportMock.transportClient,
+                        transportMock.transportData.transportDirName,
                         queue,
                         mOldJournal,
-                        mObserver,
-                        mMonitor,
+                        mReporter,
                         mListener,
                         emptyList(),
                         /* userInitiated */ false,
@@ -2121,6 +2286,10 @@
      * Implements {@code function} for {@link BackupAgent#onBackup(ParcelFileDescriptor,
      * BackupDataOutput, ParcelFileDescriptor)} of {@code agentMock} and populates {@link
      * AgentMock#oldState}.
+     *
+     * <p>Note that for throwing agents this will simulate a local agent (the exception will be
+     * thrown in our stack), use {@link #remoteAgentOnBackupThrows(AgentMock, BackupAgentOnBackup)}
+     * if you want to simulate a remote agent.
      */
     private static void agentOnBackupDo(AgentMock agentMock, BackupAgentOnBackup function)
             throws Exception {
@@ -2129,7 +2298,7 @@
                                 (oldState, dataOutput, newState) -> {
                                     ByteArrayOutputStream outputStream =
                                             new ByteArrayOutputStream();
-                                    Utils.transferStreamedData(
+                                    transferStreamedData(
                                             new FileInputStream(oldState.getFileDescriptor()),
                                             outputStream);
                                     agentMock.oldState = outputStream.toByteArray();
@@ -2141,6 +2310,33 @@
     }
 
     /**
+     * Use this method to simulate a remote agent throwing. We catch the exception thrown, thus
+     * simulating a one-way call. It also populates {@link AgentMock#oldState}.
+     *
+     * @param agentMock The Agent mock.
+     * @param function A function that throws, otherwise the test will fail.
+     */
+    // TODO: Remove when RemoteCall spins up a dedicated thread for calls
+    private static void remoteAgentOnBackupThrows(AgentMock agentMock, BackupAgentOnBackup function)
+            throws Exception {
+        agentOnBackupDo(agentMock, function);
+        doAnswer(
+                        invocation -> {
+                            try {
+                                invocation.callRealMethod();
+                                fail("Agent method expected to throw");
+                            } catch (RuntimeException e) {
+                                // This silences the exception just like a one-way call would, the
+                                // normal completion via IBackupCallback binder still happens, check
+                                // finally() block of IBackupAgent.doBackup().
+                            }
+                            return null;
+                        })
+                .when(agentMock.agentBinder)
+                .doBackup(any(), any(), any(), anyLong(), any(), anyInt());
+    }
+
+    /**
      * 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}.
@@ -2180,18 +2376,31 @@
         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 assertTaskReverted(TransportMock transportMock, PackageData... packages)
+            throws RemoteException, IOException {
+        verify(transportMock.transport).requestBackupTime();
+        assertBackupPendingFor(packages);
+        assertThat(KeyValueBackupJob.isScheduled()).isTrue();
     }
 
-    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 assertBackupPendingFor(PackageData... packages) throws IOException {
+        for (PackageData packageData : packages) {
+            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... packages) throws IOException {
+        for (PackageData packageData : packages) {
+            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)
@@ -2204,6 +2413,16 @@
         assertThat(data1).isEqualTo(value);
     }
 
+    private void assertCleansUpFilesAndAgent(TransportData transport, PackageData packageData) {
+        assertCleansUpFiles(transport, packageData);
+        verify(mBackupManagerService).unbindAgent(argThat(applicationInfo(packageData)));
+    }
+
+    private void assertCleansUpFiles(TransportData transport, PackageData packageData) {
+        assertThat(Files.exists(getTemporaryStateFile(transport, packageData))).isFalse();
+        assertThat(Files.exists(getStagingFile(packageData))).isFalse();
+    }
+
     /**
      * Put conditions that should *always* be true after task execution.
      *
diff --git a/services/robotests/src/com/android/server/backup/remote/FutureBackupCallbackTest.java b/services/robotests/src/com/android/server/backup/remote/FutureBackupCallbackTest.java
index aec207d..f3621e2 100644
--- a/services/robotests/src/com/android/server/backup/remote/FutureBackupCallbackTest.java
+++ b/services/robotests/src/com/android/server/backup/remote/FutureBackupCallbackTest.java
@@ -41,6 +41,6 @@
 
         callback.operationComplete(7);
 
-        assertThat(future.get()).isEqualTo(RemoteResult.successful(7));
+        assertThat(future.get()).isEqualTo(RemoteResult.of(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
index 55db616..1d92bed 100644
--- a/services/robotests/src/com/android/server/backup/remote/RemoteCallTest.java
+++ b/services/robotests/src/com/android/server/backup/remote/RemoteCallTest.java
@@ -161,7 +161,7 @@
     }
 
     @Test
-    public void testCall_whenCallbackIsCalledBeforeTimeOut_returnsSuccess() throws Exception {
+    public void testCall_whenCallbackIsCalledBeforeTimeOut_returnsResult() throws Exception {
         ConditionVariable scheduled = new ConditionVariable(false);
         RemoteCall remoteCall =
                 new RemoteCall(
@@ -176,11 +176,11 @@
 
         scheduled.block();
         runToEndOfTasks(Looper.getMainLooper());
-        assertThat(result.get()).isEqualTo(RemoteResult.successful(3));
+        assertThat(result.get()).isEqualTo(RemoteResult.of(3));
     }
 
     @Test
-    public void testCall_whenCallbackIsCalledBeforeCancel_returnsSuccess() throws Exception {
+    public void testCall_whenCallbackIsCalledBeforeCancel_returnsResult() throws Exception {
         CompletableFuture<IBackupCallback> callbackFuture = new CompletableFuture<>();
         RemoteCall remoteCall = new RemoteCall(callbackFuture::complete, 1000);
 
@@ -191,7 +191,7 @@
         IBackupCallback callback = callbackFuture.get();
         callback.operationComplete(3);
         remoteCall.cancel();
-        assertThat(result.get()).isEqualTo(RemoteResult.successful(3));
+        assertThat(result.get()).isEqualTo(RemoteResult.of(3));
     }
 
     @Test
@@ -222,6 +222,37 @@
         assertThat(result.get()).isEqualTo(RemoteResult.FAILED_CANCELLED);
     }
 
+    @Test
+    public void testExecute_whenCallbackIsCalledBeforeTimeout_returnsResult() throws Exception {
+        RemoteResult result =
+                runInWorkerThread(
+                        () -> RemoteCall.execute(callback -> callback.operationComplete(3), 1000));
+
+        assertThat(result.get()).isEqualTo(3);
+    }
+
+    @Test
+    public void testExecute_whenTimesOutBeforeCallback_returnsTimeOut() throws Exception {
+        ConditionVariable scheduled = new ConditionVariable(false);
+
+        Future<RemoteResult> result =
+                runInWorkerThreadAsync(
+                        () ->
+                                RemoteCall.execute(
+                                        callback -> {
+                                            postDelayed(
+                                                    Handler.getMain(),
+                                                    () -> callback.operationComplete(0),
+                                                    1000);
+                                            scheduled.open();
+                                        },
+                                        500));
+
+        scheduled.block();
+        runToEndOfTasks(Looper.getMainLooper());
+        assertThat(result.get()).isEqualTo(RemoteResult.FAILED_TIMED_OUT);
+    }
+
     private static <T> Future<T> runInWorkerThreadAsync(Callable<T> supplier) {
         CompletableFuture<T> future = new CompletableFuture<>();
         new Thread(() -> future.complete(uncheck(supplier)), "test-worker-thread").start();
diff --git a/services/robotests/src/com/android/server/backup/remote/RemoteResultTest.java b/services/robotests/src/com/android/server/backup/remote/RemoteResultTest.java
index f1c4f27..7f6fd57 100644
--- a/services/robotests/src/com/android/server/backup/remote/RemoteResultTest.java
+++ b/services/robotests/src/com/android/server/backup/remote/RemoteResultTest.java
@@ -35,28 +35,38 @@
 @Presubmit
 public class RemoteResultTest {
     @Test
-    public void testSucceeded_whenSuccessfulResult_returnsTrue() {
-        RemoteResult result = RemoteResult.successful(3);
+    public void testIsPresent_whenNonFailedResult_returnsTrue() {
+        RemoteResult result = RemoteResult.of(3);
 
-        boolean succeeded = result.succeeded();
+        boolean isPresent = result.isPresent();
 
-        assertThat(succeeded).isTrue();
+        assertThat(isPresent).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();
+    public void testIsPresent_whenTimeOutResult_returnsFalse() {
+        boolean timeOutIsPresent = RemoteResult.FAILED_TIMED_OUT.isPresent();
 
-        assertThat(timeOutSucceeded).isFalse();
-        assertThat(cancelledSucceeded).isFalse();
-        assertThat(threadInterruptedSucceeded).isFalse();
+        assertThat(timeOutIsPresent).isFalse();
+    }
+
+    @Test
+    public void testIsPresent_whenCancelledResult_returnsFalse() {
+        boolean cancelledIsPresent = RemoteResult.FAILED_CANCELLED.isPresent();
+
+        assertThat(cancelledIsPresent).isFalse();
+    }
+
+    @Test
+    public void testIsPresent_whenThreadInterruptedResult_returnsFalse() {
+        boolean threadInterruptedIsPresent = RemoteResult.FAILED_THREAD_INTERRUPTED.isPresent();
+
+        assertThat(threadInterruptedIsPresent).isFalse();
     }
 
     @Test
     public void testGet_whenSuccessfulResult_returnsValue() {
-        RemoteResult result = RemoteResult.successful(7);
+        RemoteResult result = RemoteResult.of(7);
 
         long value = result.get();
 
@@ -72,7 +82,7 @@
 
     @Test
     public void testToString() {
-        assertThat(RemoteResult.successful(3).toString()).isEqualTo("RemoteResult{3}");
+        assertThat(RemoteResult.of(3).toString()).isEqualTo("RemoteResult{3}");
         assertThat(RemoteResult.FAILED_TIMED_OUT.toString())
                 .isEqualTo("RemoteResult{FAILED_TIMED_OUT}");
         assertThat(RemoteResult.FAILED_CANCELLED.toString())
@@ -83,14 +93,14 @@
 
     @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)))
+        assertThat(RemoteResult.of(3).equals(RemoteResult.of(3))).isTrue();
+        assertThat(RemoteResult.of(3).equals(RemoteResult.of(7))).isFalse();
+        assertThat(RemoteResult.of(-1).equals(RemoteResult.of(1))).isFalse();
+        assertThat(RemoteResult.of(Long.MAX_VALUE).equals(RemoteResult.of(-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.of(3).equals(RemoteResult.FAILED_TIMED_OUT)).isFalse();
+        assertThat(RemoteResult.of(3).equals("3")).isFalse();
+        assertThat(RemoteResult.of(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();
     }
@@ -98,9 +108,9 @@
     /** @see Object#hashCode() */
     @Test
     public void testHashCode() {
-        RemoteResult result3 = RemoteResult.successful(3);
+        RemoteResult result3 = RemoteResult.of(3);
         assertThat(result3.hashCode()).isEqualTo(result3.hashCode());
-        assertThat(result3.hashCode()).isEqualTo(RemoteResult.successful(3).hashCode());
+        assertThat(result3.hashCode()).isEqualTo(RemoteResult.of(3).hashCode());
         assertThat(RemoteResult.FAILED_TIMED_OUT.hashCode())
                 .isEqualTo(RemoteResult.FAILED_TIMED_OUT.hashCode());
         assertThat(RemoteResult.FAILED_CANCELLED.hashCode())
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 df4d457..2f54513 100644
--- a/services/robotests/src/com/android/server/backup/testing/TestUtils.java
+++ b/services/robotests/src/com/android/server/backup/testing/TestUtils.java
@@ -20,6 +20,8 @@
 
 import static org.robolectric.Shadows.shadowOf;
 
+import static java.util.stream.Collectors.toSet;
+
 import android.os.Looper;
 import android.os.Message;
 import android.os.MessageQueue;
@@ -36,6 +38,7 @@
 import java.util.concurrent.TimeoutException;
 import java.util.function.Predicate;
 import java.util.function.Supplier;
+import java.util.stream.IntStream;
 
 public class TestUtils {
     private static final long TIMEOUT_MS = 3000;
@@ -87,20 +90,45 @@
         ShadowSystemClock.setCurrentTimeMillis(shadowLooper.getScheduler().getCurrentTime());
     }
 
-    /** Reset logcat with {@link ShadowLog#reset()} before the test case. */
+    /**
+     * Reset logcat with {@link ShadowLog#reset()} before the test case if you do anything that uses
+     * logcat before that.
+     */
     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 if you do anything that uses
+     * logcat before that.
+     */
     public static void assertLogcatAtLeast(String tag, int level) {
         assertThat(ShadowLog.getLogsForTag(tag).stream().anyMatch(logItem -> logItem.type >= level))
                 .named("Any log >= " + level)
                 .isTrue();
     }
 
+    /**
+     * Verifies that logcat has produced log items as specified per level in {@code logs} (with
+     * repetition).
+     *
+     * <p>So, if you call {@code assertLogcat(TAG, Log.ERROR, Log.ERROR)}, you assert that there are
+     * exactly 2 log items, each with level ERROR.
+     *
+     * <p>Reset logcat with {@link ShadowLog#reset()} before the test case if you do anything
+     * that uses logcat before that.
+     */
+    public static void assertLogcat(String tag, int... logs) {
+        assertThat(
+                        ShadowLog.getLogsForTag(tag).stream()
+                                .map(logItem -> logItem.type)
+                                .collect(toSet()))
+                .named("Log items (specified per level)")
+                .containsExactly(IntStream.of(logs).boxed().toArray());
+    }
+
     public static void assertLogcatContains(String tag, Predicate<ShadowLog.LogItem> predicate) {
         assertThat(ShadowLog.getLogsForTag(tag).stream().anyMatch(predicate)).isTrue();
     }
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 6625443..f6ed630 100644
--- a/services/robotests/src/com/android/server/backup/testing/TransportTestUtils.java
+++ b/services/robotests/src/com/android/server/backup/testing/TransportTestUtils.java
@@ -164,18 +164,18 @@
                 when(transportClientMock.connectOrThrow(any())).thenReturn(transportMock);
                 when(transportClientMock.connect(any())).thenReturn(transportMock);
 
-                return new TransportMock(transportClientMock, transportMock);
+                return new TransportMock(transport, transportClientMock, transportMock);
             } else {
                 // Transport registered but unavailable
                 when(transportClientMock.connectOrThrow(any()))
                         .thenThrow(TransportNotAvailableException.class);
                 when(transportClientMock.connect(any())).thenReturn(null);
 
-                return new TransportMock(transportClientMock, null);
+                return new TransportMock(transport, transportClientMock, null);
             }
         } else {
             // Transport not registered
-            return new TransportMock(null, null);
+            return new TransportMock(transport, null, null);
         }
     }
 
@@ -196,11 +196,15 @@
     }
 
     public static class TransportMock {
+        public final TransportData transportData;
         @Nullable public final TransportClient transportClient;
         @Nullable public final IBackupTransport transport;
 
         private TransportMock(
-                @Nullable TransportClient transportClient, @Nullable IBackupTransport transport) {
+                TransportData transportData,
+                @Nullable TransportClient transportClient,
+                @Nullable IBackupTransport transport) {
+            this.transportData = transportData;
             this.transportClient = transportClient;
             this.transport = transport;
         }
diff --git a/services/robotests/src/com/android/server/backup/testing/Utils.java b/services/robotests/src/com/android/server/backup/testing/Utils.java
index bd8b4ef..b0e00a2 100644
--- a/services/robotests/src/com/android/server/backup/testing/Utils.java
+++ b/services/robotests/src/com/android/server/backup/testing/Utils.java
@@ -19,6 +19,8 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
 import java.util.Iterator;
 
 public class Utils {
@@ -41,5 +43,9 @@
         return () -> iterator;
     }
 
+    public static boolean isFileNonEmpty(Path path) throws IOException {
+        return Files.exists(path) && Files.size(path) > 0;
+    }
+
     private Utils() {}
 }
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 bc47dd5..4901828 100644
--- a/services/robotests/src/com/android/server/testing/shadows/ShadowBackupDataInput.java
+++ b/services/robotests/src/com/android/server/testing/shadows/ShadowBackupDataInput.java
@@ -20,6 +20,7 @@
 
 import org.robolectric.annotation.Implementation;
 import org.robolectric.annotation.Implements;
+import org.robolectric.annotation.Resetter;
 
 import java.io.EOFException;
 import java.io.FileDescriptor;
@@ -33,6 +34,17 @@
  */
 @Implements(BackupDataInput.class)
 public class ShadowBackupDataInput {
+    private static boolean sReadNextHeaderThrow = false;
+
+    public static void throwInNextHeaderRead() {
+        sReadNextHeaderThrow = true;
+    }
+
+    @Resetter
+    public static void reset() {
+        sReadNextHeaderThrow = false;
+    }
+
     private FileDescriptor mFileDescriptor;
     private ObjectInputStream mInput;
     private int mSize;
@@ -46,6 +58,10 @@
 
     @Implementation
     public boolean readNextHeader() throws IOException {
+        if (sReadNextHeaderThrow) {
+            sReadNextHeaderThrow = false;
+            throw new IOException("Fake exception");
+        }
         mHeaderReady = false;
         try {
             ensureInput();
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 ca04008..5812c3c 100644
--- a/services/robotests/src/com/android/server/testing/shadows/ShadowBackupDataOutput.java
+++ b/services/robotests/src/com/android/server/testing/shadows/ShadowBackupDataOutput.java
@@ -55,6 +55,11 @@
         return mTransportFlags;
     }
 
+    public ObjectOutputStream getOutputStream() {
+        ensureOutput();
+        return mOutput;
+    }
+
     @Implementation
     public int writeEntityHeader(String key, int dataSize) throws IOException {
         ensureOutput();
diff --git a/services/robotests/src/com/android/server/testing/shadows/ShadowBackupPolicyEnforcer.java b/services/robotests/src/com/android/server/testing/shadows/ShadowBackupPolicyEnforcer.java
deleted file mode 100644
index e76b9d1..0000000
--- a/services/robotests/src/com/android/server/testing/shadows/ShadowBackupPolicyEnforcer.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.android.server.testing.shadows;
-
-import android.annotation.Nullable;
-import android.content.ComponentName;
-
-import com.android.server.backup.BackupPolicyEnforcer;
-
-import org.robolectric.annotation.Implementation;
-import org.robolectric.annotation.Implements;
-
-@Implements(BackupPolicyEnforcer.class)
-public class ShadowBackupPolicyEnforcer {
-    @Nullable private static ComponentName sMandatoryBackupTransport;
-
-    public static void setMandatoryBackupTransport(
-            @Nullable ComponentName backupTransportComponent) {
-        sMandatoryBackupTransport = backupTransportComponent;
-    }
-
-    @Implementation
-    @Nullable
-    public ComponentName getMandatoryBackupTransport() {
-        return sMandatoryBackupTransport;
-    }
-}
diff --git a/services/robotests/src/com/android/server/testing/shadows/ShadowFullBackup.java b/services/robotests/src/com/android/server/testing/shadows/ShadowFullBackup.java
new file mode 100644
index 0000000..3c913e3
--- /dev/null
+++ b/services/robotests/src/com/android/server/testing/shadows/ShadowFullBackup.java
@@ -0,0 +1,70 @@
+package com.android.server.testing.shadows;
+
+import android.app.backup.BackupDataOutput;
+import android.app.backup.FullBackup;
+import android.app.backup.FullBackupDataOutput;
+
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+import org.robolectric.shadow.api.Shadow;
+
+import java.io.IOException;
+import java.io.ObjectOutputStream;
+import java.nio.ByteBuffer;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+/**
+ * Shadow for {@link FullBackup}. Used to emulate the native method {@link
+ * FullBackup#backupToTar(String, String, String, String, String, FullBackupDataOutput)}. Relies on
+ * the shadow {@link ShadowBackupDataOutput}, which must be included in tests that use this shadow.
+ */
+@Implements(FullBackup.class)
+public class ShadowFullBackup {
+    /**
+     * Reads data from the specified file at {@code path} and writes it to the {@code output}. Does
+     * not match the native implementation, and only partially simulates TAR format. Used solely for
+     * passing backup data for testing purposes.
+     *
+     * <p>Note: Only handles the {@code path} denoting a file and not a directory like the real
+     * implementation.
+     */
+    @Implementation
+    public static int backupToTar(
+            String packageName,
+            String domain,
+            String linkdomain,
+            String rootpath,
+            String path,
+            FullBackupDataOutput output) {
+        BackupDataOutput backupDataOutput = output.getData();
+        try {
+            Path file = Paths.get(path);
+            byte[] data = Files.readAllBytes(file);
+            backupDataOutput.writeEntityHeader("key", data.length);
+
+            // Partially simulate TAR header (not all fields included). We use a 512 byte block for
+            // the header to follow the TAR convention and to have a consistent size block to help
+            // with separating the header from the data.
+            ByteBuffer tarBlock = ByteBuffer.wrap(new byte[512]);
+            String tarPath = "apps/" + packageName + (domain == null ? "" : "/" + domain) + path;
+            tarBlock.put(tarPath.getBytes()); // file path
+            tarBlock.putInt(0x1ff); // file mode
+            tarBlock.putLong(Files.size(file)); // file size
+            tarBlock.putLong(Files.getLastModifiedTime(file).toMillis()); // last modified time
+            tarBlock.putInt(0); // file type
+
+            // Write TAR header directly to the BackupDataOutput's output stream.
+            ShadowBackupDataOutput shadowBackupDataOutput = Shadow.extract(backupDataOutput);
+            ObjectOutputStream outputStream = shadowBackupDataOutput.getOutputStream();
+            outputStream.write(tarBlock.array());
+            outputStream.flush();
+
+            backupDataOutput.writeEntityData(data, data.length);
+        } catch (IOException e) {
+            throw new AssertionError(e);
+        }
+        return 0;
+    }
+}
diff --git a/services/robotests/src/com/android/server/testing/shadows/ShadowKeyValueBackupTask.java b/services/robotests/src/com/android/server/testing/shadows/ShadowKeyValueBackupTask.java
index aeda2dc..b7db56b 100644
--- a/services/robotests/src/com/android/server/testing/shadows/ShadowKeyValueBackupTask.java
+++ b/services/robotests/src/com/android/server/testing/shadows/ShadowKeyValueBackupTask.java
@@ -17,12 +17,11 @@
 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.KeyValueBackupReporter;
 import com.android.server.backup.keyvalue.KeyValueBackupTask;
 import com.android.server.backup.transport.TransportClient;
 
@@ -57,12 +56,11 @@
     public void __constructor__(
             BackupManagerService backupManagerService,
             TransportClient transportClient,
-            String dirName,
+            String transportDirName,
             List<String> queue,
-            @Nullable DataChangedJournal journal,
-            IBackupObserver observer,
-            IBackupManagerMonitor monitor,
-            @Nullable OnTaskFinishedListener listener,
+            @Nullable DataChangedJournal dataChangedJournal,
+            KeyValueBackupReporter reporter,
+            OnTaskFinishedListener listener,
             List<String> pendingFullBackups,
             boolean userInitiated,
             boolean nonIncremental) {
diff --git a/services/tests/mockingservicestests/Android.mk b/services/tests/mockingservicestests/Android.mk
new file mode 100644
index 0000000..8c02833
--- /dev/null
+++ b/services/tests/mockingservicestests/Android.mk
@@ -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.
+
+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 := \
+    frameworks-base-testutils \
+    services.core \
+    androidx-test \
+    mockito-target-extended-minus-junit4 \
+    platform-test-annotations \
+    ShortcutManagerTestUtils \
+    truth-prebuilt \
+
+LOCAL_JAVA_LIBRARIES := android.test.mock android.test.base android.test.runner
+
+LOCAL_JNI_SHARED_LIBRARIES := \
+    libdexmakerjvmtiagent \
+    libstaticjvmtiagent \
+
+LOCAL_CERTIFICATE := platform
+LOCAL_PACKAGE_NAME := FrameworksMockingServicesTests
+LOCAL_PRIVATE_PLATFORM_APIS := true
+LOCAL_COMPATIBILITY_SUITE := device-tests
+
+LOCAL_PROGUARD_ENABLED := disabled
+
+include $(BUILD_PACKAGE)
diff --git a/core/tests/webkit/AndroidManifest.xml b/services/tests/mockingservicestests/AndroidManifest.xml
similarity index 61%
copy from core/tests/webkit/AndroidManifest.xml
copy to services/tests/mockingservicestests/AndroidManifest.xml
index 42accdf..c9aa631 100644
--- a/core/tests/webkit/AndroidManifest.xml
+++ b/services/tests/mockingservicestests/AndroidManifest.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 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.
@@ -15,16 +15,17 @@
 -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-          package="com.android.webkit.tests"
-          android:sharedUserId="android.uid.system">
+        package="com.android.frameworks.mockingservicestests">
 
-    <application>
+    <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
+
+    <application android:testOnly="true"
+                 android:debuggable="true">
         <uses-library android:name="android.test.runner" />
     </application>
 
     <instrumentation
-            android:name="android.support.test.runner.AndroidJUnitRunner"
-            android:targetPackage="com.android.webkit.tests"
-            android:label="Frameworks WebView Loader Tests" />
-
+        android:name="androidx.test.runner.AndroidJUnitRunner"
+        android:targetPackage="com.android.frameworks.mockingservicestests"
+        android:label="Frameworks Mocking Services Tests" />
 </manifest>
diff --git a/core/tests/webkit/AndroidTest.xml b/services/tests/mockingservicestests/AndroidTest.xml
similarity index 64%
copy from core/tests/webkit/AndroidTest.xml
copy to services/tests/mockingservicestests/AndroidTest.xml
index 4c50b7d..7782d57 100644
--- a/core/tests/webkit/AndroidTest.xml
+++ b/services/tests/mockingservicestests/AndroidTest.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 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.
@@ -13,18 +13,21 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<configuration description="Runs Frameworks WebView Loading Tests.">
+<configuration description="Runs Frameworks Services 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="test-file-name" value="WebViewLoadingTests.apk" />
-        <option name="test-file-name" value="WebViewLoadingOnDiskTestApk.apk" />
-        <option name="test-file-name" value="WebViewLoadingFromApkTestApk.apk" />
         <option name="cleanup-apks" value="true" />
-        <option name="alt-dir" value="out" />
+        <option name="install-arg" value="-t" />
+        <option name="test-file-name" value="FrameworksMockingServicesTests.apk" />
     </target_preparer>
 
+    <option name="test-tag" value="FrameworksMockingServicesTests" />
+
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
-        <option name="package" value="com.android.webkit.tests" />
+        <option name="package" value="com.android.frameworks.mockingservicestests" />
+        <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
+        <option name="hidden-api-checks" value="false"/>
     </test>
 </configuration>
diff --git a/services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java
new file mode 100644
index 0000000..de3d285
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java
@@ -0,0 +1,374 @@
+/*
+ * 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;
+
+import static android.app.AlarmManager.ELAPSED_REALTIME_WAKEUP;
+import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_ACTIVE;
+import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_FREQUENT;
+import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_RARE;
+import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_WORKING_SET;
+
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.timeout;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.isNull;
+
+import android.app.ActivityManager;
+import android.app.AlarmManager;
+import android.app.IActivityManager;
+import android.app.IUidObserver;
+import android.app.PendingIntent;
+import android.app.usage.UsageStatsManagerInternal;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.PowerManager;
+import android.os.SystemClock;
+import android.os.UserHandle;
+import android.util.Log;
+
+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.Answers;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoSession;
+
+import javax.annotation.concurrent.GuardedBy;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class AlarmManagerServiceTest {
+    private static final String TAG = AlarmManagerServiceTest.class.getSimpleName();
+    private static final String TEST_CALLING_PACKAGE = "com.android.framework.test-package";
+    private static final int SYSTEM_UI_UID = 123456789;
+    private static final int TEST_CALLING_UID = 12345;
+    private static final long DEFAULT_TIMEOUT = 5_000;
+
+    private AlarmManagerService mService;
+    @Mock
+    private IActivityManager mIActivityManager;
+    @Mock
+    private UsageStatsManagerInternal mUsageStatsManagerInternal;
+    @Mock
+    private AppStateTracker mAppStateTracker;
+    @Mock
+    private AlarmManagerService.ClockReceiver mClockReceiver;
+    @Mock
+    private PowerManager.WakeLock mWakeLock;
+
+    private MockitoSession mMockingSession;
+    private Injector mInjector;
+    private volatile long mNowElapsedTest;
+    @GuardedBy("mTestTimer")
+    private TestTimer mTestTimer = new TestTimer();
+
+    static class TestTimer {
+        private long mElapsed;
+        boolean mExpired;
+
+        synchronized long getElapsed() {
+            return mElapsed;
+        }
+
+        synchronized void set(long millisElapsed) {
+            mElapsed = millisElapsed;
+        }
+
+        synchronized long expire() {
+            mExpired = true;
+            notify();
+            return mElapsed;
+        }
+    }
+
+    public class Injector extends AlarmManagerService.Injector {
+        Injector(Context context) {
+            super(context);
+        }
+
+        @Override
+        void init() {
+            // Do nothing.
+        }
+
+        @Override
+        int waitForAlarm() {
+            synchronized (mTestTimer) {
+                if (!mTestTimer.mExpired) {
+                    try {
+                        mTestTimer.wait();
+                    } catch (InterruptedException ie) {
+                        Log.e(TAG, "Wait interrupted!", ie);
+                        return 0;
+                    }
+                }
+                mTestTimer.mExpired = false;
+            }
+            return AlarmManagerService.IS_WAKEUP_MASK; // Doesn't matter, just evaluate.
+        }
+
+        @Override
+        void setKernelTimezone(int minutesWest) {
+            // Do nothing.
+        }
+
+        @Override
+        void setAlarm(int type, long millis) {
+            mTestTimer.set(millis);
+        }
+
+        @Override
+        void setKernelTime(long millis) {
+        }
+
+        @Override
+        int getSystemUiUid() {
+            return SYSTEM_UI_UID;
+        }
+
+        @Override
+        boolean isAlarmDriverPresent() {
+            // Pretend the driver is present, so code does not fall back to handler
+            return true;
+        }
+
+        @Override
+        long getElapsedRealtime() {
+            return mNowElapsedTest;
+        }
+
+        @Override
+        AlarmManagerService.ClockReceiver getClockReceiver(AlarmManagerService service) {
+            return mClockReceiver;
+        }
+
+        @Override
+        PowerManager.WakeLock getAlarmWakeLock() {
+            return mWakeLock;
+        }
+    }
+
+    @Before
+    public final void setUp() throws Exception {
+        mMockingSession = mockitoSession()
+                .initMocks(this)
+                .mockStatic(ActivityManager.class, Answers.CALLS_REAL_METHODS)
+                .mockStatic(LocalServices.class)
+                .mockStatic(Looper.class, Answers.CALLS_REAL_METHODS)
+                .startMocking();
+        doReturn(mIActivityManager).when(ActivityManager::getService);
+        doReturn(mAppStateTracker).when(() -> LocalServices.getService(AppStateTracker.class));
+        doReturn(null)
+                .when(() -> LocalServices.getService(DeviceIdleController.LocalService.class));
+        doReturn(mUsageStatsManagerInternal).when(
+                () -> LocalServices.getService(UsageStatsManagerInternal.class));
+        when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE),
+                eq(UserHandle.getUserId(TEST_CALLING_UID)), anyLong()))
+                .thenReturn(STANDBY_BUCKET_ACTIVE);
+        doReturn(Looper.getMainLooper()).when(Looper::myLooper);
+
+        final Context context = InstrumentationRegistry.getTargetContext();
+        mInjector = spy(new Injector(context));
+        mService = new AlarmManagerService(context, mInjector);
+        spyOn(mService);
+        doNothing().when(mService).publishBinderService(any(), any());
+        mService.onStart();
+        mService.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY);
+        mService.mConstants.MIN_FUTURITY = 0;
+
+        assertEquals(mService.mSystemUiUid, SYSTEM_UI_UID);
+        assertEquals(mService.mClockReceiver, mClockReceiver);
+        assertEquals(mService.mWakeLock, mWakeLock);
+        verify(mIActivityManager).registerUidObserver(any(IUidObserver.class), anyInt(), anyInt(),
+                isNull());
+    }
+
+    private void setTestAlarm(int type, long triggerTime, PendingIntent operation) {
+        mService.setImpl(type, triggerTime, AlarmManager.WINDOW_EXACT, 0,
+                operation, null, "test", AlarmManager.FLAG_STANDALONE, null, null,
+                TEST_CALLING_UID, TEST_CALLING_PACKAGE);
+    }
+
+    private PendingIntent getNewMockPendingIntent() {
+        final PendingIntent mockPi = mock(PendingIntent.class, Answers.RETURNS_DEEP_STUBS);
+        when(mockPi.getCreatorUid()).thenReturn(TEST_CALLING_UID);
+        when(mockPi.getCreatorPackage()).thenReturn(TEST_CALLING_PACKAGE);
+        return mockPi;
+    }
+
+    @Test
+    public void testSingleAlarmSet() {
+        final long triggerTime = mNowElapsedTest + 5000;
+        final PendingIntent alarmPi = getNewMockPendingIntent();
+        setTestAlarm(ELAPSED_REALTIME_WAKEUP, triggerTime, alarmPi);
+        verify(mInjector).setAlarm(ELAPSED_REALTIME_WAKEUP, triggerTime);
+        assertEquals(triggerTime, mTestTimer.getElapsed());
+    }
+
+    @Test
+    public void testSingleAlarmExpiration() throws Exception {
+        final long triggerTime = mNowElapsedTest + 5000;
+        final PendingIntent alarmPi = getNewMockPendingIntent();
+        setTestAlarm(ELAPSED_REALTIME_WAKEUP, triggerTime, alarmPi);
+
+        mNowElapsedTest = mTestTimer.expire();
+
+        final ArgumentCaptor<PendingIntent.OnFinished> onFinishedCaptor =
+                ArgumentCaptor.forClass(PendingIntent.OnFinished.class);
+        verify(alarmPi, timeout(DEFAULT_TIMEOUT)).send(any(Context.class), eq(0),
+                any(Intent.class), onFinishedCaptor.capture(), any(Handler.class), isNull(), any());
+        verify(mWakeLock, timeout(DEFAULT_TIMEOUT)).acquire();
+        onFinishedCaptor.getValue().onSendFinished(alarmPi, null, 0, null, null);
+        verify(mWakeLock, timeout(DEFAULT_TIMEOUT)).release();
+    }
+
+    @Test
+    public void testMinFuturity() {
+        mService.mConstants.MIN_FUTURITY = 10;
+        final long triggerTime = mNowElapsedTest + 1;
+        final long expectedTriggerTime = mNowElapsedTest + mService.mConstants.MIN_FUTURITY;
+        setTestAlarm(ELAPSED_REALTIME_WAKEUP, triggerTime, getNewMockPendingIntent());
+        verify(mInjector).setAlarm(ELAPSED_REALTIME_WAKEUP, expectedTriggerTime);
+    }
+
+    @Test
+    public void testEarliestAlarmSet() {
+        final PendingIntent pi6 = getNewMockPendingIntent();
+        final PendingIntent pi8 = getNewMockPendingIntent();
+        final PendingIntent pi9 = getNewMockPendingIntent();
+
+        setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 8, pi8);
+        assertEquals(mNowElapsedTest + 8, mTestTimer.getElapsed());
+
+        setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 9, pi9);
+        assertEquals(mNowElapsedTest + 8, mTestTimer.getElapsed());
+
+        setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 6, pi6);
+        assertEquals(mNowElapsedTest + 6, mTestTimer.getElapsed());
+
+        mService.removeLocked(pi6, null);
+        assertEquals(mNowElapsedTest + 8, mTestTimer.getElapsed());
+
+        mService.removeLocked(pi8, null);
+        assertEquals(mNowElapsedTest + 9, mTestTimer.getElapsed());
+    }
+
+    @Test
+    public void testStandbyBucketDelay_workingSet() throws Exception {
+        setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 5, getNewMockPendingIntent());
+        setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 6, getNewMockPendingIntent());
+        assertEquals(mNowElapsedTest + 5, mTestTimer.getElapsed());
+
+        when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), anyInt(),
+                anyLong())).thenReturn(STANDBY_BUCKET_WORKING_SET);
+        mNowElapsedTest = mTestTimer.expire();
+        verify(mUsageStatsManagerInternal, timeout(DEFAULT_TIMEOUT).atLeastOnce())
+                .getAppStandbyBucket(eq(TEST_CALLING_PACKAGE),
+                        eq(UserHandle.getUserId(TEST_CALLING_UID)), anyLong());
+        final long expectedNextTrigger = mNowElapsedTest
+                + mService.getMinDelayForBucketLocked(STANDBY_BUCKET_WORKING_SET);
+        assertTrue("Incorrect next alarm trigger. Expected " + expectedNextTrigger + " found: "
+                + mTestTimer.getElapsed(), pollingCheck(DEFAULT_TIMEOUT,
+                () -> (mTestTimer.getElapsed() == expectedNextTrigger)));
+    }
+
+    @Test
+    public void testStandbyBucketDelay_frequent() {
+        setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 5, getNewMockPendingIntent());
+        setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 6, getNewMockPendingIntent());
+        assertEquals(mNowElapsedTest + 5, mTestTimer.getElapsed());
+
+        when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), anyInt(),
+                anyLong())).thenReturn(STANDBY_BUCKET_FREQUENT);
+        mNowElapsedTest = mTestTimer.expire();
+        verify(mUsageStatsManagerInternal, timeout(DEFAULT_TIMEOUT).atLeastOnce())
+                .getAppStandbyBucket(eq(TEST_CALLING_PACKAGE),
+                        eq(UserHandle.getUserId(TEST_CALLING_UID)), anyLong());
+        final long expectedNextTrigger = mNowElapsedTest
+                + mService.getMinDelayForBucketLocked(STANDBY_BUCKET_FREQUENT);
+        assertTrue("Incorrect next alarm trigger. Expected " + expectedNextTrigger + " found: "
+                + mTestTimer.getElapsed(), pollingCheck(DEFAULT_TIMEOUT,
+                () -> (mTestTimer.getElapsed() == expectedNextTrigger)));
+    }
+
+    @Test
+    public void testStandbyBucketDelay_rare() {
+        setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 5, getNewMockPendingIntent());
+        setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 6, getNewMockPendingIntent());
+        assertEquals(mNowElapsedTest + 5, mTestTimer.getElapsed());
+
+        when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), anyInt(),
+                anyLong())).thenReturn(STANDBY_BUCKET_RARE);
+        mNowElapsedTest = mTestTimer.expire();
+        verify(mUsageStatsManagerInternal, timeout(DEFAULT_TIMEOUT).atLeastOnce())
+                .getAppStandbyBucket(eq(TEST_CALLING_PACKAGE),
+                        eq(UserHandle.getUserId(TEST_CALLING_UID)), anyLong());
+        final long expectedNextTrigger = mNowElapsedTest
+                + mService.getMinDelayForBucketLocked(STANDBY_BUCKET_RARE);
+        assertTrue("Incorrect next alarm trigger. Expected " + expectedNextTrigger + " found: "
+                + mTestTimer.getElapsed(), pollingCheck(DEFAULT_TIMEOUT,
+                () -> (mTestTimer.getElapsed() == expectedNextTrigger)));
+    }
+
+    @After
+    public void tearDown() {
+        if (mMockingSession != null) {
+            mMockingSession.finishMocking();
+        }
+    }
+
+    private boolean pollingCheck(long timeout, Condition condition) {
+        final long deadline = SystemClock.uptimeMillis() + timeout;
+        boolean interrupted = false;
+        while (!condition.check() && SystemClock.uptimeMillis() < deadline) {
+            try {
+                Thread.sleep(500);
+            } catch (InterruptedException ie) {
+                interrupted = true;
+            }
+        }
+        if (interrupted) {
+            Thread.currentThread().interrupt();
+        }
+        return condition.check();
+    }
+
+    @FunctionalInterface
+    interface Condition {
+        boolean check();
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/AppStateTrackerTest.java b/services/tests/mockingservicestests/src/com/android/server/AppStateTrackerTest.java
similarity index 98%
rename from services/tests/servicestests/src/com/android/server/AppStateTrackerTest.java
rename to services/tests/mockingservicestests/src/com/android/server/AppStateTrackerTest.java
index 910aad7f..c8e6782 100644
--- a/services/tests/servicestests/src/com/android/server/AppStateTrackerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/AppStateTrackerTest.java
@@ -64,9 +64,6 @@
 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;
@@ -88,11 +85,14 @@
 import java.util.concurrent.TimeUnit;
 import java.util.function.Consumer;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 /**
  * Tests for {@link AppStateTracker}
  *
  * Run with:
- atest $ANDROID_BUILD_TOP/frameworks/base/services/tests/servicestests/src/com/android/server/AppStateTrackerTest.java
+ atest $ANDROID_BUILD_TOP/frameworks/base/services/tests/mockingservicestests/src/com/android/server/AppStateTrackerTest.java
  */
 @SmallTest
 @RunWith(AndroidJUnit4.class)
@@ -683,10 +683,10 @@
 
         //--------------------------------------------------
         List<OpEntry> entries = new ArrayList<>();
-        entries.add(new AppOpsManager.OpEntry(
+        entries.add(new OpEntry(
                 AppOpsManager.OP_ACCESS_NOTIFICATIONS,
                 AppOpsManager.MODE_IGNORED, 0, 0, 0, 0, null));
-        entries.add(new AppOpsManager.OpEntry(
+        entries.add(new OpEntry(
                 AppStateTracker.TARGET_OP,
                 AppOpsManager.MODE_IGNORED, 0, 0, 0, 0, null));
 
@@ -694,7 +694,7 @@
 
         //--------------------------------------------------
         entries = new ArrayList<>();
-        entries.add(new AppOpsManager.OpEntry(
+        entries.add(new OpEntry(
                 AppStateTracker.TARGET_OP,
                 AppOpsManager.MODE_IGNORED, 0, 0, 0, 0, null));
 
@@ -702,7 +702,7 @@
 
         //--------------------------------------------------
         entries = new ArrayList<>();
-        entries.add(new AppOpsManager.OpEntry(
+        entries.add(new OpEntry(
                 AppStateTracker.TARGET_OP,
                 AppOpsManager.MODE_ALLOWED, 0, 0, 0, 0, null));
 
@@ -710,10 +710,10 @@
 
         //--------------------------------------------------
         entries = new ArrayList<>();
-        entries.add(new AppOpsManager.OpEntry(
+        entries.add(new OpEntry(
                 AppStateTracker.TARGET_OP,
                 AppOpsManager.MODE_IGNORED, 0, 0, 0, 0, null));
-        entries.add(new AppOpsManager.OpEntry(
+        entries.add(new OpEntry(
                 AppOpsManager.OP_ACCESS_NOTIFICATIONS,
                 AppOpsManager.MODE_IGNORED, 0, 0, 0, 0, null));
 
@@ -754,7 +754,7 @@
         final AppStateTrackerTestable instance = newInstance();
         callStart(instance);
 
-        AppStateTracker.Listener l = mock(AppStateTracker.Listener.class);
+        Listener l = mock(Listener.class);
         instance.addListener(l);
 
         // Power save on.
@@ -797,7 +797,7 @@
         final AppStateTrackerTestable instance = newInstance();
         callStart(instance);
 
-        AppStateTracker.Listener l = mock(AppStateTracker.Listener.class);
+        Listener l = mock(Listener.class);
         instance.addListener(l);
 
         // -------------------------------------------------------------------------
diff --git a/services/tests/servicestests/Android.mk b/services/tests/servicestests/Android.mk
index 43f319e..80307ee 100644
--- a/services/tests/servicestests/Android.mk
+++ b/services/tests/servicestests/Android.mk
@@ -9,7 +9,9 @@
 LOCAL_MODULE_TAGS := tests
 
 # Include all test java files.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SRC_FILES := \
+    $(call all-java-files-under, src) \
+    $(call all-java-files-under, utils) \
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
     frameworks-base-testutils \
diff --git a/services/tests/servicestests/AndroidManifest.xml b/services/tests/servicestests/AndroidManifest.xml
index 348e201..863e487 100644
--- a/services/tests/servicestests/AndroidManifest.xml
+++ b/services/tests/servicestests/AndroidManifest.xml
@@ -143,7 +143,8 @@
         <activity android:name="com.android.server.pm.BaseShortcutManagerTest$ShortcutActivity2" />
         <activity android:name="com.android.server.pm.BaseShortcutManagerTest$ShortcutActivity3" />
 
-        <activity android:name="com.android.server.wm.ScreenDecorWindowTests$TestActivity" />
+        <activity android:name="com.android.server.wm.ScreenDecorWindowTests$TestActivity"
+                  android:showWhenLocked="true"/>
 
         <activity android:name="com.android.server.pm.ShortcutTestActivity"
                  android:enabled="true" android:exported="true" />
diff --git a/services/tests/servicestests/src/com/android/server/AlarmManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/BackgroundRestrictedAlarmsTest.java
similarity index 98%
rename from services/tests/servicestests/src/com/android/server/AlarmManagerServiceTest.java
rename to services/tests/servicestests/src/com/android/server/BackgroundRestrictedAlarmsTest.java
index 1f63d61..d248b89 100644
--- a/services/tests/servicestests/src/com/android/server/AlarmManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/BackgroundRestrictedAlarmsTest.java
@@ -35,14 +35,13 @@
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
-public class AlarmManagerServiceTest {
+public class BackgroundRestrictedAlarmsTest {
     private SparseArray<ArrayList<Alarm>> addPendingAlarm(
             SparseArray<ArrayList<Alarm>> all, int uid, String name, boolean removeIt) {
         ArrayList<Alarm> uidAlarms = all.get(uid);
         if (uidAlarms == null) {
             all.put(uid, uidAlarms = new ArrayList<>());
         }
-        // Details don't matter.
         uidAlarms.add(new Alarm(
                 removeIt ? RTC : RTC_WAKEUP,
                 0, 0, 0, 0, 0, null, null, null, null, 0, null, uid, name));
diff --git a/services/tests/servicestests/src/com/android/server/CachedDeviceStateServiceTest.java b/services/tests/servicestests/src/com/android/server/CachedDeviceStateServiceTest.java
new file mode 100644
index 0000000..81107cf
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/CachedDeviceStateServiceTest.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF 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.mockito.Mockito.when;
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.content.Intent;
+import android.os.BatteryManager;
+import android.os.BatteryManagerInternal;
+import android.os.IPowerManager;
+import android.os.OsProtoEnums;
+import android.os.PowerManager;
+import android.os.RemoteException;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.internal.os.CachedDeviceState;
+import com.android.internal.util.test.BroadcastInterceptingContext;
+
+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;
+
+/**
+ * Tests for {@link CachedDeviceStateService}.
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class CachedDeviceStateServiceTest {
+    @Mock private BatteryManagerInternal mBatteryManager;
+    @Mock private IPowerManager mPowerManager;
+    private BroadcastInterceptingContext mContext;
+
+    @Before
+    public void setUp() throws RemoteException {
+        MockitoAnnotations.initMocks(this);
+        Context context = InstrumentationRegistry.getContext();
+        PowerManager powerManager = new PowerManager(context, mPowerManager, null);
+        mContext = new BroadcastInterceptingContext(context) {
+            @Override
+            public Object getSystemService(String name) {
+                switch (name) {
+                    case Context.POWER_SERVICE:
+                        return powerManager;
+                    default:
+                        return super.getSystemService(name);
+                }
+            }
+        };
+
+        LocalServices.addService(BatteryManagerInternal.class, mBatteryManager);
+
+        when(mBatteryManager.getPlugType()).thenReturn(OsProtoEnums.BATTERY_PLUGGED_NONE);
+        when(mPowerManager.isInteractive()).thenReturn(true);
+    }
+
+    @After
+    public void tearDown() {
+        // Added by the CachedDeviceStateService.onStart().
+        LocalServices.removeServiceForTest(CachedDeviceState.Readonly.class);
+
+        // Added in @Before.
+        LocalServices.removeServiceForTest(BatteryManagerInternal.class);
+    }
+
+    @Test
+    public void correctlyReportsScreenInteractive() throws RemoteException {
+        CachedDeviceStateService service = new CachedDeviceStateService(mContext);
+        when(mPowerManager.isInteractive()).thenReturn(true); // Screen on.
+
+        service.onStart();
+        CachedDeviceState.Readonly deviceState =
+                LocalServices.getService(CachedDeviceState.Readonly.class);
+
+        // State can be initialized correctly only after PHASE_SYSTEM_SERVICES_READY.
+        assertThat(deviceState.isScreenInteractive()).isFalse();
+
+        service.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY);
+
+        assertThat(deviceState.isScreenInteractive()).isTrue();
+
+        mContext.sendBroadcast(new Intent(Intent.ACTION_SCREEN_OFF));
+        assertThat(deviceState.isScreenInteractive()).isFalse();
+
+        mContext.sendBroadcast(new Intent(Intent.ACTION_SCREEN_ON));
+        assertThat(deviceState.isScreenInteractive()).isTrue();
+    }
+
+    @Test
+    public void correctlyReportsCharging() {
+        CachedDeviceStateService service = new CachedDeviceStateService(mContext);
+        when(mBatteryManager.getPlugType()).thenReturn(OsProtoEnums.BATTERY_PLUGGED_NONE);
+
+        service.onStart();
+        CachedDeviceState.Readonly deviceState =
+                LocalServices.getService(CachedDeviceState.Readonly.class);
+
+        // State can be initialized correctly only after PHASE_SYSTEM_SERVICES_READY.
+        assertThat(deviceState.isCharging()).isTrue();
+
+        service.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY);
+
+        assertThat(deviceState.isCharging()).isFalse();
+
+        Intent intentPluggedIn = new Intent(Intent.ACTION_BATTERY_CHANGED);
+        intentPluggedIn.putExtra(BatteryManager.EXTRA_PLUGGED, OsProtoEnums.BATTERY_PLUGGED_AC);
+        mContext.sendBroadcast(intentPluggedIn);
+        assertThat(deviceState.isCharging()).isTrue();
+
+        Intent intentUnplugged = new Intent(Intent.ACTION_BATTERY_CHANGED);
+        intentUnplugged.putExtra(BatteryManager.EXTRA_PLUGGED, OsProtoEnums.BATTERY_PLUGGED_NONE);
+        mContext.sendBroadcast(intentUnplugged);
+        assertThat(deviceState.isCharging()).isFalse();
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
index eb28e1a..1eb88ba 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
@@ -100,6 +100,7 @@
 import android.net.NetworkInfo;
 import android.net.NetworkInfo.DetailedState;
 import android.net.NetworkPolicy;
+import android.net.NetworkPolicyManager;
 import android.net.NetworkState;
 import android.net.NetworkStats;
 import android.net.NetworkStatsHistory;
@@ -365,7 +366,7 @@
                 return null;
             }
         }).when(mActivityManager).registerUidObserver(any(), anyInt(),
-                eq(ActivityManager.PROCESS_STATE_UNKNOWN), isNull(String.class));
+                eq(NetworkPolicyManager.FOREGROUND_THRESHOLD_STATE), isNull(String.class));
 
         mFutureIntent = newRestrictBackgroundChangedFuture();
         mService = new NetworkPolicyManagerService(mServiceContext, mActivityManager,
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/FingerprintGestureControllerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/FingerprintGestureControllerTest.java
index 360ccbf..a3decb9 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/FingerprintGestureControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/FingerprintGestureControllerTest.java
@@ -20,6 +20,8 @@
 import android.accessibilityservice.FingerprintGestureController.FingerprintGestureCallback;
 import android.accessibilityservice.IAccessibilityServiceConnection;
 import android.os.Looper;
+import android.support.test.filters.FlakyTest;
+
 import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Test;
@@ -95,6 +97,7 @@
     }
 
     @Test
+    @FlakyTest
     public void testDetectionActiveCallback_withHandler_shouldPostRunnableToHandler() {
         MessageCapturingHandler messageCapturingHandler = new MessageCapturingHandler((message) -> {
             message.getCallback().run();
@@ -142,6 +145,7 @@
     }
 
     @Test
+    @FlakyTest
     public void testGestureCallback_withHandler_shouldPostRunnableToHandler() {
         MessageCapturingHandler messageCapturingHandler = new MessageCapturingHandler((message) -> {
             message.getCallback().run();
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 f9d264b..d6d21c6 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/MagnificationControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/MagnificationControllerTest.java
@@ -43,6 +43,7 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
+import android.support.test.filters.FlakyTest;
 import android.view.MagnificationSpec;
 
 import androidx.test.runner.AndroidJUnit4;
@@ -66,6 +67,7 @@
 import java.util.Locale;
 
 @RunWith(AndroidJUnit4.class)
+@FlakyTest
 public class MagnificationControllerTest {
     static final Rect INITIAL_MAGNIFICATION_BOUNDS = new Rect(0, 0, 100, 200);
     static final PointF INITIAL_MAGNIFICATION_BOUNDS_CENTER = new PointF(
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 20df2ae..1aa80c8 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java
@@ -33,9 +33,7 @@
 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.Matchers.anyInt;
-import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.reset;
@@ -46,7 +44,6 @@
 import android.app.WaitResult;
 import android.graphics.Rect;
 import android.platform.test.annotations.Presubmit;
-import android.util.SparseIntArray;
 
 import androidx.test.filters.MediumTest;
 import androidx.test.runner.AndroidJUnit4;
@@ -54,7 +51,6 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.invocation.InvocationOnMock;
 
 import java.util.ArrayList;
 
@@ -246,22 +242,6 @@
                 null /* target */, null /* targetOptions */);
     }
 
-    @Test
-    public void testTopRunningActivityLockedWithNonExistentDisplay() throws Exception {
-        // Create display that ActivityManagerService does not know about
-        final int unknownDisplayId = 100;
-
-        doAnswer((InvocationOnMock invocationOnMock) -> {
-            final SparseIntArray displayIds = invocationOnMock.<SparseIntArray>getArgument(0);
-            displayIds.put(0, 0);
-            displayIds.put(1, unknownDisplayId);
-            return null;
-        }).when(mSupervisor.mWindowManager).getDisplaysInFocusOrder(any());
-
-        // Supervisor should skip over the non-existent display.
-        assertEquals(null, mSupervisor.topRunningActivityLocked());
-    }
-
     /**
      * Verifies that removal of activity with task and stack is done correctly.
      */
@@ -339,12 +319,6 @@
         final ActivityRecord activity = new ActivityBuilder(mService).setCreateTask(true)
                 .setStack(stack).build();
 
-        doAnswer((InvocationOnMock invocationOnMock) -> {
-            final SparseIntArray displayIds = invocationOnMock.<SparseIntArray>getArgument(0);
-            displayIds.put(0, display.mDisplayId);
-            return null;
-        }).when(mSupervisor.mWindowManager).getDisplaysInFocusOrder(any());
-
         // Make sure the top running activity is not affected when keyguard is not locked
         assertEquals(activity, mService.mStackSupervisor.topRunningActivityLocked());
         assertEquals(activity, mService.mStackSupervisor.topRunningActivityLocked(
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 59b0890..95f8fd1 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
@@ -24,6 +24,7 @@
 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 static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
 
 import static com.android.server.am.ActivityStack.ActivityState.PAUSING;
 import static com.android.server.am.ActivityStack.ActivityState.RESUMED;
@@ -73,7 +74,7 @@
         mService = createActivityTaskManagerService();
         mSupervisor = mService.mStackSupervisor;
         mDefaultDisplay = mService.mStackSupervisor.getDefaultDisplay();
-        mStack = mDefaultDisplay.createStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
+        mStack = mDefaultDisplay.createStack(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD,
                 true /* onTop */);
         mTask = new TaskBuilder(mSupervisor).setStack(mStack).build();
     }
@@ -140,7 +141,7 @@
     }
 
     @Test
-    public void testPrimarySplitScreenToFullscreenWhenMovedToBack() throws Exception {
+    public void testPrimarySplitScreenRestoresWhenMovedToBack() throws Exception {
         // Create primary splitscreen stack. This will create secondary stacks and places the
         // existing fullscreen stack on the bottom.
         final ActivityStack primarySplitScreen = mDefaultDisplay.createStack(
@@ -158,6 +159,60 @@
 
         // Ensure no longer in splitscreen.
         assertEquals(primarySplitScreen.getWindowingMode(), WINDOWING_MODE_FULLSCREEN);
+
+        // Ensure that the override mode is restored to undefined
+        assertEquals(primarySplitScreen.getOverrideWindowingMode(), WINDOWING_MODE_UNDEFINED);
+    }
+
+    @Test
+    public void testPrimarySplitScreenRestoresPreviousWhenMovedToBack() throws Exception {
+        // This time, start with a fullscreen activitystack
+        final ActivityStack primarySplitScreen = mDefaultDisplay.createStack(
+            WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
+
+        primarySplitScreen.setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
+
+        // Assert windowing mode.
+        assertEquals(primarySplitScreen.getWindowingMode(), WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
+
+        // Move primary to back.
+        primarySplitScreen.moveToBack("testPrimarySplitScreenToFullscreenWhenMovedToBack",
+            null /* task */);
+
+        // Assert that stack is at the bottom.
+        assertEquals(mDefaultDisplay.getIndexOf(primarySplitScreen), 0);
+
+        // Ensure that the override mode is restored to what it was (fullscreen)
+        assertEquals(primarySplitScreen.getOverrideWindowingMode(), WINDOWING_MODE_FULLSCREEN);
+    }
+
+    @Test
+    public void testStackInheritsDisplayWindowingMode() throws Exception {
+        final ActivityStack primarySplitScreen = mDefaultDisplay.createStack(
+            WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD, true /* onTop */);
+
+        assertEquals(WINDOWING_MODE_FULLSCREEN, primarySplitScreen.getWindowingMode());
+        assertEquals(WINDOWING_MODE_UNDEFINED, primarySplitScreen.getOverrideWindowingMode());
+
+        mDefaultDisplay.setWindowingMode(WINDOWING_MODE_FREEFORM);
+        assertEquals(WINDOWING_MODE_FREEFORM, primarySplitScreen.getWindowingMode());
+        assertEquals(WINDOWING_MODE_UNDEFINED, primarySplitScreen.getOverrideWindowingMode());
+    }
+
+    @Test
+    public void testStackOverridesDisplayWindowingMode() throws Exception {
+        final ActivityStack primarySplitScreen = mDefaultDisplay.createStack(
+            WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD, true /* onTop */);
+
+        assertEquals(WINDOWING_MODE_FULLSCREEN, primarySplitScreen.getWindowingMode());
+        assertEquals(WINDOWING_MODE_UNDEFINED, primarySplitScreen.getOverrideWindowingMode());
+
+        primarySplitScreen.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
+        // setting windowing mode should still work even though resolved mode is already fullscreen
+        assertEquals(WINDOWING_MODE_FULLSCREEN, primarySplitScreen.getOverrideWindowingMode());
+
+        mDefaultDisplay.setWindowingMode(WINDOWING_MODE_FREEFORM);
+        assertEquals(WINDOWING_MODE_FULLSCREEN, primarySplitScreen.getWindowingMode());
     }
 
     @Test
@@ -189,7 +244,7 @@
 
         assertEquals(task.getTopActivity(false /* includeOverlays */), r);
         assertEquals(task.getTopActivity(true /* includeOverlays */), taskOverlay);
-        assertNotNull(result.r);
+        assertNotNull(result.mRecord);
     }
 
     @Test
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 9c0b525..bb8e5c5 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
@@ -35,7 +35,6 @@
 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;
@@ -45,7 +44,6 @@
 import com.android.server.wm.DisplayWindowController;
 
 import org.junit.Rule;
-import org.mockito.Mockito;
 import org.mockito.invocation.InvocationOnMock;
 
 import android.app.IApplicationThread;
@@ -63,26 +61,22 @@
 import android.os.UserHandle;
 import android.service.voice.IVoiceInteractionSession;
 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.RootWindowContainerController;
 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;
 
@@ -500,13 +494,14 @@
                     (DisplayManager) mService.mContext.getSystemService(Context.DISPLAY_SERVICE);
             mWindowManager = prepareMockWindowManager();
             mKeyguardController = mock(KeyguardController.class);
+            setWindowContainerController(mock(RootWindowContainerController.class));
         }
 
         @Override
         public void initialize() {
             super.initialize();
             mDisplay = spy(new TestActivityDisplay(this, DEFAULT_DISPLAY));
-            attachDisplay(mDisplay);
+            addChild(mDisplay, ActivityDisplay.POSITION_TOP);
         }
 
         @Override
@@ -525,6 +520,9 @@
         private final ActivityStackSupervisor mSupervisor;
         TestActivityDisplay(ActivityStackSupervisor supervisor, int displayId) {
             super(supervisor, displayId);
+            // Normally this comes from display-properties as exposed by WM. Without that, just
+            // hard-code to FULLSCREEN for tests.
+            setWindowingMode(WINDOWING_MODE_FULLSCREEN);
             mSupervisor = supervisor;
         }
 
@@ -576,12 +574,6 @@
             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/RecentTasksTest.java b/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java
index ba82487..5195214 100644
--- a/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java
@@ -872,8 +872,8 @@
             super.initialize();
             mDisplay = new TestActivityDisplay(this, DEFAULT_DISPLAY);
             mOtherDisplay = new TestActivityDisplay(this, DEFAULT_DISPLAY);
-            attachDisplay(mOtherDisplay);
-            attachDisplay(mDisplay);
+            addChild(mOtherDisplay, ActivityDisplay.POSITION_TOP);
+            addChild(mDisplay, ActivityDisplay.POSITION_TOP);
         }
 
         @Override
@@ -1045,7 +1045,7 @@
 
         @Override
         void getTasks(int maxNum, List<RunningTaskInfo> list, int ignoreActivityType,
-                int ignoreWindowingMode, SparseArray<ActivityDisplay> activityDisplays,
+                int ignoreWindowingMode, ArrayList<ActivityDisplay> activityDisplays,
                 int callingUid, boolean allowed) {
             lastAllowed = allowed;
             super.getTasks(maxNum, list, ignoreActivityType, ignoreWindowingMode, activityDisplays,
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 283c027..d56c6a6 100644
--- a/services/tests/servicestests/src/com/android/server/am/RunningTasksTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/RunningTasksTest.java
@@ -68,9 +68,9 @@
     public void testCollectTasksByLastActiveTime() throws Exception {
         // Create a number of stacks with tasks (of incrementing active time)
         final ActivityStackSupervisor supervisor = mService.mStackSupervisor;
-        final SparseArray<ActivityDisplay> displays = new SparseArray<>();
+        final ArrayList<ActivityDisplay> displays = new ArrayList<>();
         final ActivityDisplay display = new TestActivityDisplay(supervisor, DEFAULT_DISPLAY);
-        displays.put(DEFAULT_DISPLAY, display);
+        displays.add(display);
 
         final int numStacks = 2;
         for (int stackIndex = 0; stackIndex < numStacks; stackIndex++) {
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 e37a6c1..16b127c 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -57,7 +57,6 @@
 import android.app.admin.DevicePolicyManager;
 import android.app.admin.DevicePolicyManagerInternal;
 import android.app.admin.PasswordMetrics;
-import android.app.backup.ISelectBackupTransportCallback;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Intent;
@@ -1713,24 +1712,35 @@
                         UserManager.DISALLOW_ADD_USER),
                 eq(true), eq(CAMERA_DISABLED_GLOBALLY));
         reset(getServices().userManagerInternal);
+    }
 
-        // Set up another DA and let it disable camera.  Now DISALLOW_CAMERA will only be applied
-        // locally.
-        dpm.setCameraDisabled(admin1, false);
-        reset(getServices().userManagerInternal);
+    public void testDaDisallowedPolicies_SecurityException() throws Exception {
+        mContext.callerPermissions.add(permission.MANAGE_DEVICE_ADMINS);
+        mContext.callerPermissions.add(permission.INTERACT_ACROSS_USERS_FULL);
 
-        setUpPackageManagerForAdmin(admin2, DpmMockContext.CALLER_SYSTEM_USER_UID);
-        dpm.setActiveAdmin(admin2, /* replace =*/ false, UserHandle.USER_SYSTEM);
-        dpm.setCameraDisabled(admin2, true);
+        setUpPackageManagerForAdmin(admin1, DpmMockContext.CALLER_SYSTEM_USER_UID);
+        dpm.setActiveAdmin(admin1, /* replace =*/ false, UserHandle.USER_SYSTEM);
 
-        verify(getServices().userManagerInternal).setDevicePolicyUserRestrictions(
-                eq(UserHandle.USER_SYSTEM),
-                // DISALLOW_CAMERA will be applied to both local and global. <- TODO: fix this
-                MockUtils.checkUserRestrictions(UserManager.DISALLOW_FUN,
-                        UserManager.DISALLOW_ADD_USER),
-                eq(true), eq(CAMERA_DISABLED_LOCALLY));
-        reset(getServices().userManagerInternal);
-        // TODO Make sure restrictions are written to the file.
+        boolean originalCameraDisabled = dpm.getCameraDisabled(admin1);
+        assertExpectException(SecurityException.class, /* messageRegex= */ null,
+                () -> dpm.setCameraDisabled(admin1, true));
+        assertEquals(originalCameraDisabled, dpm.getCameraDisabled(admin1));
+
+        int originalKeyguardDisabledFeatures = dpm.getKeyguardDisabledFeatures(admin1);
+        assertExpectException(SecurityException.class, /* messageRegex= */ null,
+                () -> dpm.setKeyguardDisabledFeatures(admin1,
+                        DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_ALL));
+        assertEquals(originalKeyguardDisabledFeatures, dpm.getKeyguardDisabledFeatures(admin1));
+
+        long originalPasswordExpirationTimeout = dpm.getPasswordExpirationTimeout(admin1);
+        assertExpectException(SecurityException.class, /* messageRegex= */ null,
+                () -> dpm.setPasswordExpirationTimeout(admin1, 1234));
+        assertEquals(originalPasswordExpirationTimeout, dpm.getPasswordExpirationTimeout(admin1));
+
+        int originalPasswordQuality = dpm.getPasswordQuality(admin1);
+        assertExpectException(SecurityException.class, /* messageRegex= */ null,
+                () -> dpm.setPasswordQuality(admin1, DevicePolicyManager.PASSWORD_QUALITY_NUMERIC));
+        assertEquals(originalPasswordQuality, dpm.getPasswordQuality(admin1));
     }
 
     public void testSetUserRestriction_asPo() {
@@ -2240,8 +2250,8 @@
         assertEquals(UserManager.DISALLOW_ADJUST_VOLUME,
                 intent.getStringExtra(DevicePolicyManager.EXTRA_RESTRICTION));
 
-        // Try with POLICY_DISABLE_CAMERA, POLICY_DISABLE_SCREEN_CAPTURE and
-        // POLICY_MANDATORY_BACKUPS, which are not user restrictions
+        // Try with POLICY_DISABLE_CAMERA and POLICY_DISABLE_SCREEN_CAPTURE, which are not
+        // user restrictions
 
         // Camera is not disabled
         intent = dpm.createAdminSupportIntent(DevicePolicyManager.POLICY_DISABLE_CAMERA);
@@ -2265,34 +2275,6 @@
         assertEquals(DevicePolicyManager.POLICY_DISABLE_SCREEN_CAPTURE,
                 intent.getStringExtra(DevicePolicyManager.EXTRA_RESTRICTION));
 
-        // Make the backup transport selection succeed
-        doAnswer(new Answer<Void>() {
-            @Override
-            public Void answer(InvocationOnMock invocation) throws Throwable {
-                ISelectBackupTransportCallback callback =
-                    (ISelectBackupTransportCallback) invocation.getArguments()[1];
-                if (callback != null) {
-                    callback.onSuccess("");
-                }
-                return null;
-            }
-        }).when(getServices().ibackupManager).selectBackupTransportAsync(
-                any(ComponentName.class), any(ISelectBackupTransportCallback.class));
-
-
-        // Backups are not mandatory
-        intent = dpm.createAdminSupportIntent(DevicePolicyManager.POLICY_MANDATORY_BACKUPS);
-        assertNull(intent);
-
-        // Backups are mandatory
-        ComponentName transportComponent = ComponentName.unflattenFromString(
-                "android/com.android.internal.backup.LocalTransport");
-        dpm.setMandatoryBackupTransport(admin1, transportComponent);
-        intent = dpm.createAdminSupportIntent(DevicePolicyManager.POLICY_MANDATORY_BACKUPS);
-        assertNotNull(intent);
-        assertEquals(DevicePolicyManager.POLICY_MANDATORY_BACKUPS,
-                intent.getStringExtra(DevicePolicyManager.EXTRA_RESTRICTION));
-
         // Same checks for different user
         mContext.binder.callingUid = DpmMockContext.CALLER_UID;
         // Camera should be disabled by device owner
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 e6ca03b..48dda01 100644
--- a/services/tests/servicestests/src/com/android/server/display/BrightnessMappingStrategyTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/BrightnessMappingStrategyTest.java
@@ -152,8 +152,7 @@
         final float[] lux = { 0f, 1f };
         final float[] nits = { 0, PowerManager.BRIGHTNESS_ON };
 
-        BrightnessConfiguration config = new BrightnessConfiguration.Builder()
-                .setCurve(lux, nits)
+        BrightnessConfiguration config = new BrightnessConfiguration.Builder(lux, nits)
                 .build();
         strategy.setBrightnessConfiguration(config);
         assertNotEquals(1.0f, strategy.getBrightness(1f), 0.01 /*tolerance*/);
@@ -214,8 +213,7 @@
                 DISPLAY_RANGE_NITS[DISPLAY_RANGE_NITS.length - 1]
         };
 
-        BrightnessConfiguration config = new BrightnessConfiguration.Builder()
-                .setCurve(lux, nits)
+        BrightnessConfiguration config = new BrightnessConfiguration.Builder(lux, nits)
                 .build();
         strategy.setBrightnessConfiguration(config);
         assertEquals(1.0f, strategy.getBrightness(1f), 0.01 /*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 ece9f42..79a654b 100644
--- a/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java
@@ -52,6 +52,8 @@
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.internal.R;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -82,6 +84,8 @@
     private static HandlerThread sThread =
             new HandlerThread("brightness.test", android.os.Process.THREAD_PRIORITY_BACKGROUND);
 
+    private int mDefaultNightModeColorTemperature;
+
     private static Handler ensureHandler() {
         synchronized (sHandlerLock) {
             if (sHandler == null) {
@@ -98,6 +102,9 @@
         mInjector = new TestInjector(ensureHandler());
 
         mTracker = new BrightnessTracker(InstrumentationRegistry.getContext(), mInjector);
+        mDefaultNightModeColorTemperature =
+                InstrumentationRegistry.getContext().getResources().getInteger(
+                R.integer.config_nightDisplayColorTemperatureDefault);
     }
 
     @Test
@@ -188,7 +195,7 @@
         // System had no data so these should all be at defaults.
         assertEquals(Float.NaN, event.batteryLevel, 0.0);
         assertFalse(event.nightMode);
-        assertEquals(0, event.colorTemperature);
+        assertEquals(mDefaultNightModeColorTemperature, event.colorTemperature);
     }
 
     @Test
@@ -863,5 +870,17 @@
         public boolean isInteractive(Context context) {
             return mInteractive;
         }
+
+        @Override
+        public int getColorTemperature(Context context, int userId) {
+          return mSecureIntSettings.getOrDefault(Settings.Secure.NIGHT_DISPLAY_COLOR_TEMPERATURE,
+                  mDefaultNightModeColorTemperature);
+        }
+
+        @Override
+        public boolean isNightModeActive(Context context, int userId) {
+            return mSecureIntSettings.getOrDefault(Settings.Secure.NIGHT_DISPLAY_ACTIVATED,
+                    0) == 1;
+        }
     }
 }
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 0d40c5e..b330304 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
@@ -446,24 +446,6 @@
         assertEquals(anotherAlwaysOnTopStack, mDisplayContent.getStacks().get(topPosition - 1));
     }
 
-    /**
-     * Test that WM does not report displays to AM that are pending to be removed.
-     */
-    @Test
-    public void testDontReportDeferredRemoval() {
-        // Create a display and add an animating window to it.
-        final DisplayContent dc = createNewDisplay();
-        final WindowState window = createWindow(null /* parent */, TYPE_BASE_APPLICATION, dc, "w");
-        window.mAnimatingExit = true;
-        // Request display removal, it should be deferred.
-        dc.removeIfPossible();
-        // Request ordered display ids from WM.
-        final SparseIntArray orderedDisplayIds = new SparseIntArray();
-        sWm.getDisplaysInFocusOrder(orderedDisplayIds);
-        // Make sure that display that is marked for removal is not reported.
-        assertEquals(-1, orderedDisplayIds.indexOfValue(dc.getDisplayId()));
-    }
-
     @Test
     public void testDisplayCutout_rot0() throws Exception {
         synchronized (sWm.getWindowManagerLock()) {
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 9fa5ba4..ea44279 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskStackContainersTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskStackContainersTests.java
@@ -109,4 +109,22 @@
         assertEquals(taskStackContainer.mChildren.get(stackPos), stack1);
         assertEquals(taskStackContainer.mChildren.get(pinnedStackPos), mPinnedStack);
     }
+
+    @Test
+    public void testDisplayPositionWithPinnedStack() {
+        // The display contains pinned stack that was added in {@link #setUp}.
+        final TaskStack stack = createTaskStackOnDisplay(mDisplayContent);
+        final Task task = createTaskInStack(stack, 0 /* userId */);
+
+        // Add another display at top.
+        sWm.mRoot.positionChildAt(WindowContainer.POSITION_TOP, createNewDisplay(),
+                false /* includingParents */);
+
+        // Move the task of {@code mDisplayContent} to top.
+        stack.positionChildAt(WindowContainer.POSITION_TOP, task, true /* includingParents */);
+        final int indexOfDisplayWithPinnedStack = sWm.mRoot.mChildren.indexOf(mDisplayContent);
+
+        assertEquals("The testing DisplayContent should be moved to top with task",
+                sWm.mRoot.getChildCount() - 1, indexOfDisplayWithPinnedStack);
+    }
 }
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 ea3a3d0..e648230 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java
@@ -133,15 +133,15 @@
     }
 
     private void assertContentInset(WindowState w, int left, int top, int right, int bottom) {
-        assertRect(w.mContentInsets, left, top, right, bottom);
+        assertRect(w.getContentInsets(), left, top, right, bottom);
     }
 
     private void assertVisibleInset(WindowState w, int left, int top, int right, int bottom) {
-        assertRect(w.mVisibleInsets, left, top, right, bottom);
+        assertRect(w.getVisibleInsets(), left, top, right, bottom);
     }
 
     private void assertStableInset(WindowState w, int left, int top, int right, int bottom) {
-        assertRect(w.mStableInsets, left, top, right, bottom);
+        assertRect(w.getStableInsets(), left, top, right, bottom);
     }
 
     private void assertFrame(WindowState w, int left, int top, int right, int bottom) {
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 5a42a84..b43d9a6 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java
@@ -50,13 +50,19 @@
 import static org.mockito.Mockito.verify;
 
 import android.graphics.Matrix;
+import android.graphics.Rect;
 import android.platform.test.annotations.Presubmit;
+import android.util.Size;
+import android.view.DisplayCutout;
 import android.view.SurfaceControl;
 import android.view.WindowManager;
 
+import com.android.server.wm.utils.WmDisplayCutout;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.util.Arrays;
 import java.util.LinkedList;
 
 import androidx.test.filters.FlakyTest;
@@ -382,6 +388,20 @@
         }
     }
 
+    @Test
+    public void testDisplayCutoutIsCalculatedRelativeToFrame() {
+        final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
+        WindowFrames wf = new WindowFrames();
+        wf.mParentFrame.set(7, 10, 185, 380);
+        wf.mDisplayFrame.set(wf.mParentFrame);
+        final DisplayCutout cutout = new DisplayCutout(new Rect(0, 15, 0, 22),
+                Arrays.asList(new Rect(95, 0, 105, 15), new Rect(95, 378, 105, 400)));
+        wf.setDisplayCutout(new WmDisplayCutout(cutout, new Size(200, 400)));
+
+        app.computeFrameLw(wf);
+        assertThat(app.getWmDisplayCutout().getDisplayCutout(), is(cutout.inset(7, 10, 5, 20)));
+    }
+
     private void testPrepareWindowToDisplayDuringRelayout(boolean wasVisible) {
         reset(mPowerManagerWrapper);
         final WindowState root = createWindow(null, TYPE_APPLICATION, "root");
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 5db0867..70e4ce4 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
@@ -125,7 +125,7 @@
             synchronized (sWm.mWindowMap) {
                 mWallpaperWindow = createCommonWindow(null, TYPE_WALLPAPER, "wallpaperWindow");
                 mImeWindow = createCommonWindow(null, TYPE_INPUT_METHOD, "mImeWindow");
-                sWm.mInputMethodWindow = mImeWindow;
+                mDisplayContent.mInputMethodWindow = mImeWindow;
                 mImeDialogWindow = createCommonWindow(null, TYPE_INPUT_METHOD_DIALOG,
                         "mImeDialogWindow");
                 mStatusBarWindow = createCommonWindow(null, TYPE_STATUS_BAR, "mStatusBarWindow");
diff --git a/services/tests/servicestests/src/com/android/server/testutils/OffsettableClock.java b/services/tests/servicestests/utils/com/android/server/testutils/OffsettableClock.java
similarity index 100%
rename from services/tests/servicestests/src/com/android/server/testutils/OffsettableClock.java
rename to services/tests/servicestests/utils/com/android/server/testutils/OffsettableClock.java
diff --git a/services/tests/servicestests/src/com/android/server/testutils/TestHandler.java b/services/tests/servicestests/utils/com/android/server/testutils/TestHandler.java
similarity index 100%
rename from services/tests/servicestests/src/com/android/server/testutils/TestHandler.java
rename to services/tests/servicestests/utils/com/android/server/testutils/TestHandler.java
diff --git a/services/tests/servicestests/src/com/android/server/testutils/TestUtils.java b/services/tests/servicestests/utils/com/android/server/testutils/TestUtils.java
similarity index 100%
rename from services/tests/servicestests/src/com/android/server/testutils/TestUtils.java
rename to services/tests/servicestests/utils/com/android/server/testutils/TestUtils.java
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 0ff124e..519b3ae 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -65,6 +65,8 @@
 import static org.mockito.Mockito.when;
 
 import android.app.ActivityManager;
+import android.app.AppOpsManager;
+import android.app.Application;
 import android.app.IActivityManager;
 import android.app.INotificationManager;
 import android.app.Notification;
@@ -195,6 +197,8 @@
     IUriGrantsManager mUgm;
     @Mock
     UriGrantsManagerInternal mUgmInternal;
+    @Mock
+    AppOpsManager mAppOpsManager;
 
     // Use a Testable subclass so we can simulate calls from the system without failing.
     private static class TestableNotificationManagerService extends NotificationManagerService {
@@ -295,7 +299,8 @@
                     mListeners, mAssistants, mConditionProviders,
                     mCompanionMgr, mSnoozeHelper, mUsageStats, mPolicyFile, mActivityManager,
                     mGroupHelper, mAm, mAppUsageStats,
-                    mock(DevicePolicyManagerInternal.class), mUgm, mUgmInternal);
+                    mock(DevicePolicyManagerInternal.class), mUgm, mUgmInternal,
+                    mAppOpsManager);
         } catch (SecurityException e) {
             if (!e.getMessage().contains("Permission Denial: not allowed to send broadcast")) {
                 throw e;
@@ -531,7 +536,7 @@
         mBinderService.createNotificationChannels(
                 PKG, new ParceledListSlice(Arrays.asList(channel)));
         final StatusBarNotification sbn = generateNotificationRecord(channel).sbn;
-        mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag",
+        mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
         waitForIdle();
         assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
@@ -549,7 +554,7 @@
 
         final StatusBarNotification sbn = generateNotificationRecord(channel).sbn;
         sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
-        mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag",
+        mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
         waitForIdle();
         assertEquals(1, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
@@ -578,7 +583,7 @@
 
         StatusBarNotification sbn = generateNotificationRecord(channel).sbn;
         sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
-        mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag",
+        mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
         waitForIdle();
         // The first time a foreground service notification is shown, we allow the channel
@@ -600,7 +605,7 @@
 
         sbn = generateNotificationRecord(channel).sbn;
         sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
-        mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag",
+        mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
         waitForIdle();
         // The second time it is shown, we keep the user's preference.
@@ -631,7 +636,7 @@
         mBinderService.setNotificationsEnabledForPackage(PKG, mUid, false);
 
         final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
-        mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag",
+        mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
         waitForIdle();
         assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
@@ -645,7 +650,7 @@
 
         final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
         sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
-        mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag",
+        mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
         waitForIdle();
         assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
@@ -667,7 +672,7 @@
             final StatusBarNotification sbn =
                     generateNotificationRecord(mTestNotificationChannel, ++id, "", false).sbn;
             sbn.getNotification().category = category;
-            mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag",
+            mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
                     sbn.getId(), sbn.getNotification(), sbn.getUserId());
         }
         waitForIdle();
@@ -691,7 +696,7 @@
             final StatusBarNotification sbn =
                     generateNotificationRecord(mTestNotificationChannel, ++id, "", false).sbn;
             sbn.getNotification().category = category;
-            mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag",
+            mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
                     sbn.getId(), sbn.getNotification(), sbn.getUserId());
         }
         waitForIdle();
@@ -714,7 +719,7 @@
             final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
             sbn.getNotification().category = category;
             try {
-                mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag",
+                mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
                         sbn.getId(), sbn.getNotification(), sbn.getUserId());
                 fail("Calls from non system apps should not allow use of restricted categories");
             } catch (SecurityException e) {
@@ -746,7 +751,7 @@
 
     @Test
     public void testEnqueueNotificationWithTag_PopulatesGetActiveNotifications() throws Exception {
-        mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag", 0,
+        mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0,
                 generateNotificationRecord(null).getNotification(), 0);
         waitForIdle();
         StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
@@ -756,7 +761,7 @@
 
     @Test
     public void testCancelNotificationImmediatelyAfterEnqueue() throws Exception {
-        mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag", 0,
+        mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0,
                 generateNotificationRecord(null).getNotification(), 0);
         mBinderService.cancelNotificationWithTag(PKG, "tag", 0, 0);
         waitForIdle();
@@ -768,10 +773,10 @@
 
     @Test
     public void testCancelNotificationWhilePostedAndEnqueued() throws Exception {
-        mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag", 0,
+        mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0,
                 generateNotificationRecord(null).getNotification(), 0);
         waitForIdle();
-        mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag", 0,
+        mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0,
                 generateNotificationRecord(null).getNotification(), 0);
         mBinderService.cancelNotificationWithTag(PKG, "tag", 0, 0);
         waitForIdle();
@@ -788,7 +793,7 @@
     public void testCancelNotificationsFromListenerImmediatelyAfterEnqueue() throws Exception {
         NotificationRecord r = generateNotificationRecord(null);
         final StatusBarNotification sbn = r.sbn;
-        mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag",
+        mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
         mBinderService.cancelNotificationsFromListener(null, null);
         waitForIdle();
@@ -801,7 +806,7 @@
     @Test
     public void testCancelAllNotificationsImmediatelyAfterEnqueue() throws Exception {
         final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
-        mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag",
+        mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
         mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
         waitForIdle();
@@ -816,7 +821,7 @@
         final NotificationRecord n = generateNotificationRecord(
                 mTestNotificationChannel, 1, "group", true);
 
-        mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag",
+        mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
                 n.sbn.getId(), n.sbn.getNotification(), n.sbn.getUserId());
         waitForIdle();
 
@@ -839,9 +844,9 @@
         final NotificationRecord child = generateNotificationRecord(
                 mTestNotificationChannel, 2, "group1", false);
 
-        mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag",
+        mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
                 parent.sbn.getId(), parent.sbn.getNotification(), parent.sbn.getUserId());
-        mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag",
+        mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
                 child.sbn.getId(), child.sbn.getNotification(), child.sbn.getUserId());
         waitForIdle();
 
@@ -854,7 +859,7 @@
     public void testCancelAllNotificationsMultipleEnqueuedDoesNotCrash() throws Exception {
         final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
         for (int i = 0; i < 10; i++) {
-            mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag",
+            mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
                     sbn.getId(), sbn.getNotification(), sbn.getUserId());
         }
         mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
@@ -873,17 +878,17 @@
                 mTestNotificationChannel, 2, "group1", false);
 
         // fully post parent notification
-        mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag",
+        mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
                 parent.sbn.getId(), parent.sbn.getNotification(), parent.sbn.getUserId());
         waitForIdle();
 
         // enqueue the child several times
         for (int i = 0; i < 10; i++) {
-            mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag",
+            mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
                     child.sbn.getId(), child.sbn.getNotification(), child.sbn.getUserId());
         }
         // make the parent a child, which will cancel the child notification
-        mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag",
+        mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
                 parentAsChild.sbn.getId(), parentAsChild.sbn.getNotification(),
                 parentAsChild.sbn.getUserId());
         waitForIdle();
@@ -895,7 +900,7 @@
     public void testCancelAllNotifications_IgnoreForegroundService() throws Exception {
         final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
         sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
-        mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag",
+        mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
         mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
         waitForIdle();
@@ -909,7 +914,7 @@
     public void testCancelAllNotifications_IgnoreOtherPackages() throws Exception {
         final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
         sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
-        mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag",
+        mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
         mBinderService.cancelAllNotifications("other_pkg_name", sbn.getUserId());
         waitForIdle();
@@ -922,7 +927,7 @@
     @Test
     public void testCancelAllNotifications_NullPkgRemovesAll() throws Exception {
         final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
-        mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag",
+        mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
         mBinderService.cancelAllNotifications(null, sbn.getUserId());
         waitForIdle();
@@ -935,7 +940,7 @@
     @Test
     public void testCancelAllNotifications_NullPkgIgnoresUserAllNotifications() throws Exception {
         final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
-        mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag",
+        mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
                 sbn.getId(), sbn.getNotification(), UserHandle.USER_ALL);
         // Null pkg is how we signal a user switch.
         mBinderService.cancelAllNotifications(null, sbn.getUserId());
@@ -950,7 +955,7 @@
     public void testAppInitiatedCancelAllNotifications_CancelsNoClearFlag() throws Exception {
         final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
         sbn.getNotification().flags |= Notification.FLAG_NO_CLEAR;
-        mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag",
+        mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
         mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
         waitForIdle();
@@ -1037,7 +1042,7 @@
     public void testRemoveForegroundServiceFlag_ImmediatelyAfterEnqueue() throws Exception {
         final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
         sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
-        mBinderService.enqueueNotificationWithTag(PKG, "opPkg", null,
+        mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
         mInternalService.removeForegroundServiceFlagFromNotification(PKG, sbn.getId(),
                 sbn.getUserId());
@@ -1052,10 +1057,10 @@
         final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
         sbn.getNotification().flags =
                 Notification.FLAG_ONGOING_EVENT | FLAG_FOREGROUND_SERVICE;
-        mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag",
+        mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
         sbn.getNotification().flags = Notification.FLAG_ONGOING_EVENT;
-        mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag",
+        mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
         mBinderService.cancelNotificationWithTag(PKG, "tag", sbn.getId(), sbn.getUserId());
         waitForIdle();
@@ -1145,21 +1150,21 @@
         // should not be returned
         final NotificationRecord group2 = generateNotificationRecord(
                 mTestNotificationChannel, 2, "group2", true);
-        mBinderService.enqueueNotificationWithTag(PKG, "opPkg", null,
+        mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
                 group2.sbn.getId(), group2.sbn.getNotification(), group2.sbn.getUserId());
         waitForIdle();
 
         // should not be returned
         final NotificationRecord nonGroup = generateNotificationRecord(
                 mTestNotificationChannel, 3, null, false);
-        mBinderService.enqueueNotificationWithTag(PKG, "opPkg", null,
+        mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
                 nonGroup.sbn.getId(), nonGroup.sbn.getNotification(), nonGroup.sbn.getUserId());
         waitForIdle();
 
         // same group, child, should be returned
         final NotificationRecord group1Child = generateNotificationRecord(
                 mTestNotificationChannel, 4, "group1", false);
-        mBinderService.enqueueNotificationWithTag(PKG, "opPkg", null, group1Child.sbn.getId(),
+        mBinderService.enqueueNotificationWithTag(PKG, PKG, null, group1Child.sbn.getId(),
                 group1Child.sbn.getNotification(), group1Child.sbn.getUserId());
         waitForIdle();
 
@@ -1216,7 +1221,7 @@
     public void testAppInitiatedCancelAllNotifications_CancelsOnGoingFlag() throws Exception {
         final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
         sbn.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
-        mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag",
+        mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
         mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
         waitForIdle();
@@ -1333,7 +1338,7 @@
                         new NotificationChannel("foo", "foo", IMPORTANCE_HIGH));
 
         Notification.TvExtender tv = new Notification.TvExtender().setChannelId("foo");
-        mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag", 0,
+        mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0,
                 generateNotificationRecord(null, tv).getNotification(), 0);
         verify(mPreferencesHelper, times(1)).getNotificationChannel(
                 anyString(), anyInt(), eq("foo"), anyBoolean());
@@ -1348,7 +1353,7 @@
                 mTestNotificationChannel);
 
         Notification.TvExtender tv = new Notification.TvExtender().setChannelId("foo");
-        mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag", 0,
+        mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0,
                 generateNotificationRecord(null, tv).getNotification(), 0);
         verify(mPreferencesHelper, times(1)).getNotificationChannel(
                 anyString(), anyInt(), eq(mTestNotificationChannel.getId()), anyBoolean());
@@ -1879,7 +1884,7 @@
         final NotificationRecord child = generateNotificationRecord(
                 mTestNotificationChannel, 2, "group", false);
 
-        mBinderService.enqueueNotificationWithTag(PKG, "opPkg", null,
+        mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
                 child.sbn.getId(), child.sbn.getNotification(), child.sbn.getUserId());
         waitForIdle();
 
@@ -1892,7 +1897,7 @@
         final NotificationRecord record = generateNotificationRecord(
                 mTestNotificationChannel, 2, null, false);
 
-        mBinderService.enqueueNotificationWithTag(PKG, "opPkg", null,
+        mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
                 record.sbn.getId(), record.sbn.getNotification(), record.sbn.getUserId());
         waitForIdle();
 
@@ -1904,7 +1909,7 @@
         final NotificationRecord parent = generateNotificationRecord(
                 mTestNotificationChannel, 2, "group", true);
 
-        mBinderService.enqueueNotificationWithTag(PKG, "opPkg", null,
+        mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
                 parent.sbn.getId(), parent.sbn.getNotification(), parent.sbn.getUserId());
         waitForIdle();
 
@@ -2378,12 +2383,12 @@
     @Test
     public void testBumpFGImportance_noChannelChangePreOApp() throws Exception {
         String preOPkg = PKG_N_MR1;
-        int preOUid = 145;
         final ApplicationInfo legacy = new ApplicationInfo();
         legacy.targetSdkVersion = Build.VERSION_CODES.N_MR1;
         when(mPackageManagerClient.getApplicationInfoAsUser(eq(preOPkg), anyInt(), anyInt()))
                 .thenReturn(legacy);
-        when(mPackageManagerClient.getPackageUidAsUser(eq(preOPkg), anyInt())).thenReturn(preOUid);
+        when(mPackageManagerClient.getPackageUidAsUser(eq(preOPkg), anyInt()))
+                .thenReturn(Binder.getCallingUid());
         getContext().setMockPackageManager(mPackageManagerClient);
 
         Notification.Builder nb = new Notification.Builder(mContext,
@@ -2393,12 +2398,13 @@
                 .setFlag(FLAG_FOREGROUND_SERVICE, true)
                 .setPriority(Notification.PRIORITY_MIN);
 
-        StatusBarNotification sbn = new StatusBarNotification(preOPkg, preOPkg, 9, "tag", preOUid,
-                0, nb.build(), new UserHandle(preOUid), null, 0);
+        StatusBarNotification sbn = new StatusBarNotification(preOPkg, preOPkg, 9, "tag",
+                Binder.getCallingUid(), 0, nb.build(), new UserHandle(Binder.getCallingUid()), null, 0);
 
-        mBinderService.enqueueNotificationWithTag(preOPkg, preOPkg, "tag",
-                sbn.getId(), sbn.getNotification(), sbn.getUserId());
+        mBinderService.enqueueNotificationWithTag(sbn.getPackageName(), sbn.getOpPkg(),
+                sbn.getTag(), sbn.getId(), sbn.getNotification(), sbn.getUserId());
         waitForIdle();
+
         assertEquals(IMPORTANCE_LOW,
                 mService.getNotificationRecord(sbn.getKey()).getImportance());
 
@@ -2408,8 +2414,8 @@
                 .setFlag(FLAG_FOREGROUND_SERVICE, true)
                 .setPriority(Notification.PRIORITY_MIN);
 
-        sbn = new StatusBarNotification(preOPkg, preOPkg, 9, "tag", preOUid,
-                0, nb.build(), new UserHandle(preOUid), null, 0);
+        sbn = new StatusBarNotification(preOPkg, preOPkg, 9, "tag", Binder.getCallingUid(),
+                0, nb.build(), new UserHandle(Binder.getCallingUid()), null, 0);
 
         mBinderService.enqueueNotificationWithTag(preOPkg, preOPkg, "tag",
                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
@@ -3360,7 +3366,7 @@
     }
 
     @Test
-    public void testMybeRecordInterruptionLocked_doesNotRecordTwice()
+    public void testMaybeRecordInterruptionLocked_doesNotRecordTwice()
             throws RemoteException {
         final NotificationRecord r = generateNotificationRecord(
                 mTestNotificationChannel, 1, null, true);
@@ -3373,4 +3379,120 @@
         verify(mAppUsageStats, times(1)).reportInterruptiveNotification(
                 anyString(), anyString(), anyInt());
     }
+
+    @Test
+    public void testResolveNotificationUid_sameApp() throws Exception {
+        ApplicationInfo info = new ApplicationInfo();
+        info.uid = Binder.getCallingUid();
+        when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt())).thenReturn(info);
+
+        int actualUid = mService.resolveNotificationUid("caller", "caller", info.uid, 0);
+
+        assertEquals(info.uid, actualUid);
+    }
+
+    @Test
+    public void testResolveNotificationUid_sameAppWrongPkg() throws Exception {
+        ApplicationInfo info = new ApplicationInfo();
+        info.uid = Binder.getCallingUid();
+        when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt())).thenReturn(info);
+
+        try {
+            mService.resolveNotificationUid("caller", "other", info.uid, 0);
+            fail("Incorrect pkg didn't throw security exception");
+        } catch (SecurityException e) {
+            // yay
+        }
+    }
+
+    @Test
+    public void testResolveNotificationUid_sameAppWrongUid() throws Exception {
+        ApplicationInfo info = new ApplicationInfo();
+        info.uid = 1356347;
+        when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt())).thenReturn(info);
+
+        try {
+            mService.resolveNotificationUid("caller", "caller", 9, 0);
+            fail("Incorrect uid didn't throw security exception");
+        } catch (SecurityException e) {
+            // yay
+        }
+    }
+
+    @Test
+    public void testResolveNotificationUid_delegateAllowed() throws Exception {
+        int expectedUid = 123;
+
+        when(mPackageManagerClient.getPackageUidAsUser("target", 0)).thenReturn(expectedUid);
+        mService.setPreferencesHelper(mPreferencesHelper);
+        when(mPreferencesHelper.isDelegateAllowed(anyString(), anyInt(), anyString(), anyInt()))
+                .thenReturn(true);
+
+        assertEquals(expectedUid, mService.resolveNotificationUid("caller", "target", 9, 0));
+    }
+
+    @Test
+    public void testResolveNotificationUid_androidAllowed() throws Exception {
+        int expectedUid = 123;
+
+        when(mPackageManagerClient.getPackageUidAsUser("target", 0)).thenReturn(expectedUid);
+        // no delegate
+
+        assertEquals(expectedUid, mService.resolveNotificationUid("android", "target", 0, 0));
+    }
+
+    @Test
+    public void testResolveNotificationUid_delegateNotAllowed() throws Exception {
+        when(mPackageManagerClient.getPackageUidAsUser("target", 0)).thenReturn(123);
+        // no delegate
+
+        try {
+            mService.resolveNotificationUid("caller", "target", 9, 0);
+            fail("Incorrect uid didn't throw security exception");
+        } catch (SecurityException e) {
+            // yay
+        }
+    }
+
+    @Test
+    public void testRemoveForegroundServiceFlagFromNotification_enqueued() {
+        Notification n = new Notification.Builder(mContext, "").build();
+        n.flags |= FLAG_FOREGROUND_SERVICE;
+
+        StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 9, null, mUid, 0,
+                n, new UserHandle(mUid), null, 0);
+        NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
+
+        mService.addEnqueuedNotification(r);
+
+        mInternalService.removeForegroundServiceFlagFromNotification(
+                PKG, r.sbn.getId(), r.sbn.getUserId());
+
+        waitForIdle();
+
+        verify(mListeners, timeout(200).times(0)).notifyPostedLocked(any(), any());
+    }
+
+    @Test
+    public void testRemoveForegroundServiceFlagFromNotification_posted() {
+        Notification n = new Notification.Builder(mContext, "").build();
+        n.flags |= FLAG_FOREGROUND_SERVICE;
+
+        StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 9, null, mUid, 0,
+                n, new UserHandle(mUid), null, 0);
+        NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
+
+        mService.addNotification(r);
+
+        mInternalService.removeForegroundServiceFlagFromNotification(
+                PKG, r.sbn.getId(), r.sbn.getUserId());
+
+        waitForIdle();
+
+        ArgumentCaptor<NotificationRecord> captor =
+                ArgumentCaptor.forClass(NotificationRecord.class);
+        verify(mListeners, times(1)).notifyPostedLocked(captor.capture(), any());
+
+        assertEquals(0, captor.getValue().getNotification().flags);
+    }
 }
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
index 73adf25..750345b 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
@@ -123,7 +123,6 @@
     @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;
@@ -176,11 +175,6 @@
                 .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 {
@@ -1787,4 +1781,159 @@
         mHelper.setEnabled(PKG_N_MR1, 1000, true);
         assertEquals(3, mHelper.getBlockedAppCount(0));
     }
+
+    @Test
+    public void testSetNotificationDelegate() {
+        mHelper.setNotificationDelegate(PKG_O, UID_O, "other", 53);
+        assertEquals("other", mHelper.getNotificationDelegate(PKG_O, UID_O));
+    }
+
+    @Test
+    public void testRevokeNotificationDelegate() {
+        mHelper.setNotificationDelegate(PKG_O, UID_O, "other", 53);
+        mHelper.revokeNotificationDelegate(PKG_O, UID_O);
+
+        assertNull(mHelper.getNotificationDelegate(PKG_O, UID_O));
+    }
+
+    @Test
+    public void testRevokeNotificationDelegate_noDelegateExistsNoCrash() {
+        mHelper.revokeNotificationDelegate(PKG_O, UID_O);
+
+        assertNull(mHelper.getNotificationDelegate(PKG_O, UID_O));
+    }
+
+    @Test
+    public void testToggleNotificationDelegate() {
+        mHelper.setNotificationDelegate(PKG_O, UID_O, "other", 53);
+        mHelper.toggleNotificationDelegate(PKG_O, UID_O, false);
+
+        assertNull(mHelper.getNotificationDelegate(PKG_O, UID_O));
+
+        mHelper.toggleNotificationDelegate(PKG_O, UID_O, true);
+        assertEquals("other", mHelper.getNotificationDelegate(PKG_O, UID_O));
+    }
+
+    @Test
+    public void testToggleNotificationDelegate_noDelegateExistsNoCrash() {
+        mHelper.toggleNotificationDelegate(PKG_O, UID_O, false);
+        assertNull(mHelper.getNotificationDelegate(PKG_O, UID_O));
+
+        mHelper.toggleNotificationDelegate(PKG_O, UID_O, true);
+        assertNull(mHelper.getNotificationDelegate(PKG_O, UID_O));
+    }
+
+    @Test
+    public void testIsDelegateAllowed_noSource() {
+        assertFalse(mHelper.isDelegateAllowed("does not exist", -1, "whatever", 0));
+    }
+
+    @Test
+    public void testIsDelegateAllowed_noDelegate() {
+        mHelper.setImportance(PKG_O, UID_O, IMPORTANCE_UNSPECIFIED);
+
+        assertFalse(mHelper.isDelegateAllowed(PKG_O, UID_O, "whatever", 0));
+    }
+
+    @Test
+    public void testIsDelegateAllowed_delegateDisabledByApp() {
+        mHelper.setNotificationDelegate(PKG_O, UID_O, "other", 53);
+        mHelper.revokeNotificationDelegate(PKG_O, UID_O);
+
+        assertFalse(mHelper.isDelegateAllowed(PKG_O, UID_O, "other", 53));
+    }
+
+    @Test
+    public void testIsDelegateAllowed_wrongDelegate() {
+        mHelper.setNotificationDelegate(PKG_O, UID_O, "other", 53);
+        mHelper.revokeNotificationDelegate(PKG_O, UID_O);
+
+        assertFalse(mHelper.isDelegateAllowed(PKG_O, UID_O, "banana", 27));
+    }
+
+    @Test
+    public void testIsDelegateAllowed_delegateDisabledByUser() {
+        mHelper.setNotificationDelegate(PKG_O, UID_O, "other", 53);
+        mHelper.toggleNotificationDelegate(PKG_O, UID_O, false);
+
+        assertFalse(mHelper.isDelegateAllowed(PKG_O, UID_O, "other", 53));
+    }
+
+    @Test
+    public void testIsDelegateAllowed() {
+        mHelper.setNotificationDelegate(PKG_O, UID_O, "other", 53);
+
+        assertTrue(mHelper.isDelegateAllowed(PKG_O, UID_O, "other", 53));
+    }
+
+    @Test
+    public void testDelegateXml_noDelegate() throws Exception {
+        mHelper.setImportance(PKG_O, UID_O, IMPORTANCE_UNSPECIFIED);
+
+        ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false);
+        mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper);
+        loadStreamXml(baos, false);
+
+        assertNull(mHelper.getNotificationDelegate(PKG_O, UID_O));
+    }
+
+    @Test
+    public void testDelegateXml_delegate() throws Exception {
+        mHelper.setNotificationDelegate(PKG_O, UID_O, "other", 53);
+
+        ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false);
+        mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper);
+        loadStreamXml(baos, false);
+
+        assertEquals("other", mHelper.getNotificationDelegate(PKG_O, UID_O));
+    }
+
+    @Test
+    public void testDelegateXml_disabledDelegate() throws Exception {
+        mHelper.setNotificationDelegate(PKG_O, UID_O, "other", 53);
+        mHelper.revokeNotificationDelegate(PKG_O, UID_O);
+
+        ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false);
+        mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper);
+        loadStreamXml(baos, false);
+
+        assertNull(mHelper.getNotificationDelegate(PKG_O, UID_O));
+    }
+
+    @Test
+    public void testDelegateXml_userDisabledDelegate() throws Exception {
+        mHelper.setNotificationDelegate(PKG_O, UID_O, "other", 53);
+        mHelper.toggleNotificationDelegate(PKG_O, UID_O, false);
+
+        ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false);
+        mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper);
+        loadStreamXml(baos, false);
+
+        // appears disabled
+        assertNull(mHelper.getNotificationDelegate(PKG_O, UID_O));
+
+        // but was loaded and can be toggled back on
+        mHelper.toggleNotificationDelegate(PKG_O, UID_O, true);
+        assertEquals("other", mHelper.getNotificationDelegate(PKG_O, UID_O));
+    }
+
+    @Test
+    public void testDelegateXml_entirelyDisabledDelegate() throws Exception {
+        mHelper.setNotificationDelegate(PKG_O, UID_O, "other", 53);
+        mHelper.toggleNotificationDelegate(PKG_O, UID_O, false);
+        mHelper.revokeNotificationDelegate(PKG_O, UID_O);
+
+        ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false);
+        mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper);
+        loadStreamXml(baos, false);
+
+        // appears disabled
+        assertNull(mHelper.getNotificationDelegate(PKG_O, UID_O));
+
+        mHelper.setNotificationDelegate(PKG_O, UID_O, "other", 53);
+        assertNull(mHelper.getNotificationDelegate(PKG_O, UID_O));
+
+        mHelper.toggleNotificationDelegate(PKG_O, UID_O, true);
+        assertEquals("other", mHelper.getNotificationDelegate(PKG_O, UID_O));
+    }
 }
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java
new file mode 100644
index 0000000..100f9c6
--- /dev/null
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distriZenbuted on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF 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 junit.framework.Assert.assertEquals;
+
+import android.app.NotificationManager.Policy;
+import android.service.notification.ZenModeConfig;
+import android.service.notification.ZenPolicy;
+import android.support.test.runner.AndroidJUnit4;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import com.android.server.UiServiceTestCase;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class ZenModeConfigTest extends UiServiceTestCase {
+
+    @Test
+    public void testPriorityOnlyMutingAllNotifications() {
+        ZenModeConfig config = getMutedNotificationsConfig();
+        assertEquals(true, ZenModeConfig.areAllPriorityOnlyNotificationZenSoundsMuted(config));
+
+        config.allowReminders = true;
+        assertEquals(false, ZenModeConfig.areAllPriorityOnlyNotificationZenSoundsMuted(config));
+        config.allowReminders = false;
+
+        config.areChannelsBypassingDnd = true;
+        assertEquals(false, ZenModeConfig.areAllPriorityOnlyNotificationZenSoundsMuted(config));
+        config.areChannelsBypassingDnd = false;
+
+        assertEquals(true, ZenModeConfig.areAllPriorityOnlyNotificationZenSoundsMuted(config));
+    }
+
+    @Test
+    public void testZenPolicyNothingSetToNotificationPolicy() {
+        ZenModeConfig config = getMutedAllConfig();
+        ZenPolicy zenPolicy = new ZenPolicy.Builder().build();
+        assertEquals(config.toNotificationPolicy(), config.toNotificationPolicy(zenPolicy));
+    }
+
+    @Test
+    public void testZenPolicyToNotificationPolicy() {
+        ZenModeConfig config = getMutedAllConfig();
+        config.suppressedVisualEffects |= Policy.SUPPRESSED_EFFECT_BADGE;
+
+        ZenPolicy zenPolicy = new ZenPolicy.Builder()
+                .allowAlarms(true)
+                .allowReminders(true)
+                .allowEvents(true)
+                .showLights(false)
+                .showInAmbientDisplay(false)
+                .build();
+
+        Policy originalPolicy = config.toNotificationPolicy();
+        int priorityCategories = originalPolicy.priorityCategories;
+        int priorityCallSenders = originalPolicy.priorityCallSenders;
+        int priorityMessageSenders = originalPolicy.priorityMessageSenders;
+        int suppressedVisualEffects = originalPolicy.suppressedVisualEffects;
+        priorityCategories |= Policy.PRIORITY_CATEGORY_ALARMS;
+        priorityCategories |= Policy.PRIORITY_CATEGORY_REMINDERS;
+        priorityCategories |= Policy.PRIORITY_CATEGORY_EVENTS;
+        suppressedVisualEffects |= Policy.SUPPRESSED_EFFECT_LIGHTS;
+        suppressedVisualEffects |= Policy.SUPPRESSED_EFFECT_AMBIENT;
+
+        Policy expectedPolicy = new Policy(priorityCategories, priorityCallSenders,
+                priorityMessageSenders, suppressedVisualEffects);
+
+        assertEquals(expectedPolicy, config.toNotificationPolicy(zenPolicy));
+    }
+
+    @Test
+    public void testPriorityOnlyMutingAll() {
+        ZenModeConfig config = getMutedAllConfig();
+        assertEquals(true, ZenModeConfig.areAllPriorityOnlyNotificationZenSoundsMuted(config));
+        assertEquals(true, ZenModeConfig.areAllZenBehaviorSoundsMuted(config));
+
+        config.allowReminders = true;
+        assertEquals(false, ZenModeConfig.areAllPriorityOnlyNotificationZenSoundsMuted(config));
+        assertEquals(false, ZenModeConfig.areAllZenBehaviorSoundsMuted(config));
+        config.allowReminders = false;
+
+        config.areChannelsBypassingDnd = true;
+        assertEquals(false, ZenModeConfig.areAllPriorityOnlyNotificationZenSoundsMuted(config));
+        assertEquals(false, ZenModeConfig.areAllZenBehaviorSoundsMuted(config));
+        config.areChannelsBypassingDnd = false;
+
+        config.allowAlarms = true;
+        assertEquals(true, ZenModeConfig.areAllPriorityOnlyNotificationZenSoundsMuted(config));
+        assertEquals(false, ZenModeConfig.areAllZenBehaviorSoundsMuted(config));
+        config.allowAlarms = false;
+
+        assertEquals(true, ZenModeConfig.areAllPriorityOnlyNotificationZenSoundsMuted(config));
+        assertEquals(true, ZenModeConfig.areAllZenBehaviorSoundsMuted(config));
+    }
+
+    private ZenModeConfig getMutedNotificationsConfig() {
+        ZenModeConfig config = new ZenModeConfig();
+        // Allow alarms, media, and system
+        config.allowAlarms = true;
+        config.allowMedia = true;
+        config.allowSystem = true;
+
+        // All notification sounds are not allowed
+        config.allowCalls = false;
+        config.allowRepeatCallers = false;
+        config.allowMessages = false;
+        config.allowReminders = false;
+        config.allowEvents = false;
+        config.areChannelsBypassingDnd = false;
+
+        config.suppressedVisualEffects = 0;
+
+        return config;
+    }
+
+    private ZenModeConfig getMutedAllConfig() {
+        ZenModeConfig config = new ZenModeConfig();
+        // No sounds allowed
+        config.allowAlarms = false;
+        config.allowMedia = false;
+        config.allowSystem = false;
+        config.allowCalls = false;
+        config.allowRepeatCallers = false;
+        config.allowMessages = false;
+        config.allowReminders = false;
+        config.allowEvents = false;
+        config.areChannelsBypassingDnd = false;
+
+        config.suppressedVisualEffects = 0;
+        return config;
+    }
+}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenPolicyTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenPolicyTest.java
new file mode 100644
index 0000000..7c6b1c1
--- /dev/null
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenPolicyTest.java
@@ -0,0 +1,456 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distriZenbuted on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF 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 junit.framework.Assert.assertEquals;
+
+import android.service.notification.ZenPolicy;
+import android.support.test.runner.AndroidJUnit4;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import com.android.server.UiServiceTestCase;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class ZenPolicyTest extends UiServiceTestCase {
+
+    @Test
+    public void testZenPolicyApplyAllowedToDisallowed() {
+        ZenPolicy.Builder builder = new ZenPolicy.Builder();
+
+        // reminders are disallowed
+        builder.allowReminders(false);
+        ZenPolicy remindersDisallowed = builder.build();
+        assertEquals(ZenPolicy.STATE_DISALLOW,
+                remindersDisallowed.getPriorityCategoryReminders());
+
+        // reminders are allowed
+        builder.allowReminders(true);
+        ZenPolicy remindersAllowed = builder.build();
+        assertEquals(ZenPolicy.STATE_ALLOW,
+                remindersAllowed.getPriorityCategoryReminders());
+        assertEquals(ZenPolicy.STATE_DISALLOW,
+                remindersDisallowed.getPriorityCategoryReminders());
+
+        // we apply reminders allowed to reminders disallowed
+        // -> reminders should remain disallowed
+        remindersDisallowed.apply(remindersAllowed);
+        assertEquals(ZenPolicy.STATE_DISALLOW,
+                remindersDisallowed.getPriorityCategoryReminders());
+    }
+
+    @Test
+    public void testZenPolicyApplyAllowedToUnset() {
+        ZenPolicy.Builder builder = new ZenPolicy.Builder();
+
+        // reminders are unset
+        ZenPolicy remindersUnset = builder.build();
+
+        // reminders are allowed
+        builder.allowReminders(true);
+        ZenPolicy remindersAllowed = builder.build();
+
+        // we apply reminders allowed to reminders unset
+        // -> reminders should be allowed
+        remindersUnset.apply(remindersAllowed);
+        assertEquals(ZenPolicy.STATE_ALLOW, remindersUnset.getPriorityCategoryReminders());
+    }
+
+    @Test
+    public void testZenPolicyApplyDisallowedToUnset() {
+        ZenPolicy.Builder builder = new ZenPolicy.Builder();
+
+        // reminders are unset
+        ZenPolicy remindersUnset = builder.build();
+
+        // reminders are disallowed
+        builder.allowReminders(false);
+        ZenPolicy remindersDisallowed = builder.build();
+
+        // we apply reminders disallowed to reminders unset
+        // -> reminders should remain disallowed
+        remindersUnset.apply(remindersDisallowed);
+        assertEquals(ZenPolicy.STATE_DISALLOW,
+                remindersUnset.getPriorityCategoryReminders());
+    }
+
+    @Test
+    public void testZenPolicyApplyDisallowedToAllowed() {
+        ZenPolicy.Builder builder = new ZenPolicy.Builder();
+
+        // reminders are allowed
+        builder.allowReminders(true);
+        ZenPolicy remindersAllowed = builder.build();
+
+        // reminders are disallowed
+        builder.allowReminders(false);
+        ZenPolicy remindersDisallowed = builder.build();
+
+        // we apply reminders allowed to reminders disallowed
+        // -> reminders should change to disallowed
+        remindersAllowed.apply(remindersDisallowed);
+        assertEquals(ZenPolicy.STATE_DISALLOW, remindersAllowed.getPriorityCategoryReminders());
+    }
+
+    @Test
+    public void testZenPolicyApplyUnsetToAllowed() {
+        ZenPolicy.Builder builder = new ZenPolicy.Builder();
+
+        // reminders are allowed
+        builder.allowReminders(true);
+        ZenPolicy remindersAllowed = builder.build();
+
+        // reminders are unset
+        ZenPolicy.Builder builder2 = new ZenPolicy.Builder();
+        ZenPolicy remindersUnset = builder2.build();
+
+        // we apply reminders allowed to reminders unset
+        // -> reminders should remain allowed
+        remindersAllowed.apply(remindersUnset);
+        assertEquals(ZenPolicy.STATE_ALLOW, remindersAllowed.getPriorityCategoryReminders());
+    }
+
+    @Test
+    public void testZenPolicyApplyMoreSevereCallSenders() {
+        ZenPolicy.Builder builder = new ZenPolicy.Builder();
+
+        // calls from contacts allowed
+        builder.allowCalls(ZenPolicy.PEOPLE_TYPE_CONTACTS);
+        ZenPolicy contactsAllowed = builder.build();
+
+        // calls from starred contacts allowed
+        builder.allowCalls(ZenPolicy.PEOPLE_TYPE_STARRED);
+        ZenPolicy starredAllowed = builder.build();
+
+        // we apply starredAllowed to contactsAllowed -> starred contacts allowed (more restrictive)
+        contactsAllowed.apply(starredAllowed);
+        assertEquals(ZenPolicy.STATE_ALLOW, contactsAllowed.getPriorityCategoryCalls());
+        assertEquals(ZenPolicy.PEOPLE_TYPE_STARRED, contactsAllowed.getPriorityCallSenders());
+    }
+
+    @Test
+    public void testZenPolicyApplyLessSevereCallSenders() {
+        ZenPolicy.Builder builder = new ZenPolicy.Builder();
+
+        // calls from contacts allowed
+        builder.allowCalls(ZenPolicy.PEOPLE_TYPE_CONTACTS);
+        ZenPolicy contactsAllowed = builder.build();
+
+        // calls from anyone allowed
+        builder.allowCalls(ZenPolicy.PEOPLE_TYPE_ANYONE);
+        ZenPolicy anyoneAllowed = builder.build();
+
+        // we apply anyoneAllowed to contactsAllowed -> contactsAllowed (more restrictive)
+        contactsAllowed.apply(anyoneAllowed);
+        assertEquals(ZenPolicy.STATE_ALLOW, contactsAllowed.getPriorityCategoryCalls());
+        assertEquals(ZenPolicy.PEOPLE_TYPE_CONTACTS, contactsAllowed.getPriorityCallSenders());
+    }
+
+    @Test
+    public void testZenPolicyApplyMoreSevereMessageSenders() {
+        ZenPolicy.Builder builder = new ZenPolicy.Builder();
+
+        // messsages from contacts allowed
+        builder.allowMessages(ZenPolicy.PEOPLE_TYPE_CONTACTS);
+        ZenPolicy contactsAllowed = builder.build();
+
+        // messsages from no one allowed
+        builder.allowMessages(ZenPolicy.PEOPLE_TYPE_NONE);
+        ZenPolicy noneAllowed = builder.build();
+
+        // noneAllowed to contactsAllowed -> no messages allowed (more restrictive)
+        contactsAllowed.apply(noneAllowed);
+        assertEquals(ZenPolicy.STATE_DISALLOW, contactsAllowed.getPriorityCategoryMessages());
+        assertEquals(ZenPolicy.PEOPLE_TYPE_NONE, contactsAllowed.getPriorityMessageSenders());
+    }
+
+    @Test
+    public void testZenPolicyMessagesInvalid() {
+        ZenPolicy.Builder builder = new ZenPolicy.Builder();
+
+        builder.allowMessages(20); // invalid #, won't change policy
+        ZenPolicy policy = builder.build();
+        assertEquals(ZenPolicy.STATE_UNSET, policy.getPriorityCategoryMessages());
+        assertEquals(ZenPolicy.PEOPLE_TYPE_UNSET, policy.getPriorityMessageSenders());
+    }
+
+    @Test
+    public void testZenPolicyCallsInvalid() {
+        ZenPolicy.Builder builder = new ZenPolicy.Builder();
+
+        builder.allowCalls(ZenPolicy.PEOPLE_TYPE_ANYONE);
+        builder.allowCalls(20); // invalid #, won't change policy
+        ZenPolicy policy = builder.build();
+        assertEquals(ZenPolicy.STATE_ALLOW, policy.getPriorityCategoryCalls());
+        assertEquals(ZenPolicy.PEOPLE_TYPE_ANYONE, policy.getPriorityCallSenders());
+    }
+
+    @Test
+    public void testEmptyZenPolicy() {
+        ZenPolicy.Builder builder = new ZenPolicy.Builder();
+
+        ZenPolicy policy = builder.build();
+        assertAllPriorityCategoriesUnsetExcept(policy, -1);
+        assertAllVisualEffectsUnsetExcept(policy, -1);
+    }
+
+    @Test
+    public void testAllowReminders() {
+        ZenPolicy.Builder builder = new ZenPolicy.Builder();
+
+        builder.allowReminders(true);
+        ZenPolicy policy = builder.build();
+        assertAllPriorityCategoriesUnsetExcept(policy, ZenPolicy.PRIORITY_CATEGORY_REMINDERS);
+        assertEquals(ZenPolicy.STATE_ALLOW, policy.getPriorityCategoryReminders());
+        assertAllVisualEffectsUnsetExcept(policy, -1);
+
+        builder.allowReminders(false);
+        policy = builder.build();
+        assertAllPriorityCategoriesUnsetExcept(policy, ZenPolicy.PRIORITY_CATEGORY_REMINDERS);
+        assertEquals(ZenPolicy.STATE_DISALLOW, policy.getPriorityCategoryReminders());
+        assertAllVisualEffectsUnsetExcept(policy, -1);
+    }
+
+    @Test
+    public void testAllowEvents() {
+        ZenPolicy.Builder builder = new ZenPolicy.Builder();
+
+        builder.allowEvents(true);
+        ZenPolicy policy = builder.build();
+        assertAllPriorityCategoriesUnsetExcept(policy, ZenPolicy.PRIORITY_CATEGORY_EVENTS);
+        assertEquals(ZenPolicy.STATE_ALLOW, policy.getPriorityCategoryEvents());
+        assertAllVisualEffectsUnsetExcept(policy, -1);
+
+        builder.allowEvents(false);
+        policy = builder.build();
+        assertAllPriorityCategoriesUnsetExcept(policy, ZenPolicy.PRIORITY_CATEGORY_EVENTS);
+        assertEquals(ZenPolicy.STATE_DISALLOW, policy.getPriorityCategoryEvents());
+        assertAllVisualEffectsUnsetExcept(policy, -1);
+    }
+
+    @Test
+    public void testAllowMessages() {
+        ZenPolicy.Builder builder = new ZenPolicy.Builder();
+
+        builder.allowMessages(ZenPolicy.PEOPLE_TYPE_ANYONE);
+        ZenPolicy policy = builder.build();
+        assertAllPriorityCategoriesUnsetExcept(policy, ZenPolicy.PRIORITY_CATEGORY_MESSAGES);
+        assertEquals(ZenPolicy.STATE_ALLOW, policy.getPriorityCategoryMessages());
+        assertEquals(ZenPolicy.PEOPLE_TYPE_ANYONE, policy.getPriorityMessageSenders());
+        assertAllVisualEffectsUnsetExcept(policy, -1);
+
+        builder.allowMessages(ZenPolicy.PEOPLE_TYPE_CONTACTS);
+        policy = builder.build();
+        assertAllPriorityCategoriesUnsetExcept(policy, ZenPolicy.PRIORITY_CATEGORY_MESSAGES);
+        assertEquals(ZenPolicy.STATE_ALLOW, policy.getPriorityCategoryMessages());
+        assertEquals(ZenPolicy.PEOPLE_TYPE_CONTACTS, policy.getPriorityMessageSenders());
+        assertAllVisualEffectsUnsetExcept(policy, -1);
+
+        builder.allowMessages(ZenPolicy.PEOPLE_TYPE_STARRED);
+        policy = builder.build();
+        assertAllPriorityCategoriesUnsetExcept(policy, ZenPolicy.PRIORITY_CATEGORY_MESSAGES);
+        assertEquals(ZenPolicy.STATE_ALLOW, policy.getPriorityCategoryMessages());
+        assertEquals(ZenPolicy.PEOPLE_TYPE_STARRED, policy.getPriorityMessageSenders());
+        assertAllVisualEffectsUnsetExcept(policy, -1);
+
+        builder.allowMessages(ZenPolicy.PEOPLE_TYPE_NONE);
+        policy = builder.build();
+        assertAllPriorityCategoriesUnsetExcept(policy, ZenPolicy.PRIORITY_CATEGORY_MESSAGES);
+        assertEquals(ZenPolicy.STATE_DISALLOW, policy.getPriorityCategoryMessages());
+        assertEquals(ZenPolicy.PEOPLE_TYPE_NONE, policy.getPriorityMessageSenders());
+        assertAllVisualEffectsUnsetExcept(policy, -1);
+
+        builder.allowMessages(ZenPolicy.PEOPLE_TYPE_UNSET);
+        policy = builder.build();
+        assertAllPriorityCategoriesUnsetExcept(policy, -1);
+        assertAllVisualEffectsUnsetExcept(policy, -1);
+    }
+
+    @Test
+    public void testAllowCalls() {
+        ZenPolicy.Builder builder = new ZenPolicy.Builder();
+
+        builder.allowCalls(ZenPolicy.PEOPLE_TYPE_ANYONE);
+        ZenPolicy policy = builder.build();
+        assertAllPriorityCategoriesUnsetExcept(policy, ZenPolicy.PRIORITY_CATEGORY_CALLS);
+        assertEquals(ZenPolicy.STATE_ALLOW, policy.getPriorityCategoryCalls());
+        assertEquals(ZenPolicy.PEOPLE_TYPE_ANYONE, policy.getPriorityCallSenders());
+        assertAllVisualEffectsUnsetExcept(policy, -1);
+
+        builder.allowCalls(ZenPolicy.PEOPLE_TYPE_CONTACTS);
+        policy = builder.build();
+        assertAllPriorityCategoriesUnsetExcept(policy, ZenPolicy.PRIORITY_CATEGORY_CALLS);
+        assertEquals(ZenPolicy.STATE_ALLOW, policy.getPriorityCategoryCalls());
+        assertEquals(ZenPolicy.PEOPLE_TYPE_CONTACTS, policy.getPriorityCallSenders());
+        assertAllVisualEffectsUnsetExcept(policy, -1);
+
+        builder.allowCalls(ZenPolicy.PEOPLE_TYPE_STARRED);
+        policy = builder.build();
+        assertAllPriorityCategoriesUnsetExcept(policy, ZenPolicy.PRIORITY_CATEGORY_CALLS);
+        assertEquals(ZenPolicy.STATE_ALLOW, policy.getPriorityCategoryCalls());
+        assertEquals(ZenPolicy.PEOPLE_TYPE_STARRED, policy.getPriorityCallSenders());
+        assertAllVisualEffectsUnsetExcept(policy, -1);
+
+        builder.allowCalls(ZenPolicy.PEOPLE_TYPE_NONE);
+        policy = builder.build();
+        assertAllPriorityCategoriesUnsetExcept(policy, ZenPolicy.PRIORITY_CATEGORY_CALLS);
+        assertEquals(ZenPolicy.STATE_DISALLOW, policy.getPriorityCategoryCalls());
+        assertEquals(ZenPolicy.PEOPLE_TYPE_NONE, policy.getPriorityCallSenders());
+        assertAllVisualEffectsUnsetExcept(policy, -1);
+
+        builder.allowCalls(ZenPolicy.PEOPLE_TYPE_UNSET);
+        policy = builder.build();
+        assertAllPriorityCategoriesUnsetExcept(policy, -1);
+        assertAllVisualEffectsUnsetExcept(policy, -1);
+    }
+
+    @Test
+    public void testAllowRepeatCallers() {
+        ZenPolicy.Builder builder = new ZenPolicy.Builder();
+
+        builder.allowRepeatCallers(true);
+        ZenPolicy policy = builder.build();
+        assertAllPriorityCategoriesUnsetExcept(policy, ZenPolicy.PRIORITY_CATEGORY_REPEAT_CALLERS);
+        assertEquals(ZenPolicy.STATE_ALLOW, policy.getPriorityCategoryRepeatCallers());
+        assertAllVisualEffectsUnsetExcept(policy, -1);
+
+        builder.allowRepeatCallers(false);
+        policy = builder.build();
+        assertAllPriorityCategoriesUnsetExcept(policy, ZenPolicy.PRIORITY_CATEGORY_REPEAT_CALLERS);
+        assertEquals(ZenPolicy.STATE_DISALLOW, policy.getPriorityCategoryRepeatCallers());
+        assertAllVisualEffectsUnsetExcept(policy, -1);
+    }
+
+    @Test
+    public void testAllowAlarms() {
+        ZenPolicy.Builder builder = new ZenPolicy.Builder();
+
+        builder.allowAlarms(true);
+        ZenPolicy policy = builder.build();
+        assertAllPriorityCategoriesUnsetExcept(policy, ZenPolicy.PRIORITY_CATEGORY_ALARMS);
+        assertEquals(ZenPolicy.STATE_ALLOW, policy.getPriorityCategoryAlarms());
+        assertAllVisualEffectsUnsetExcept(policy, -1);
+
+        builder.allowAlarms(false);
+        policy = builder.build();
+        assertAllPriorityCategoriesUnsetExcept(policy, ZenPolicy.PRIORITY_CATEGORY_ALARMS);
+        assertEquals(ZenPolicy.STATE_DISALLOW, policy.getPriorityCategoryAlarms());
+        assertAllVisualEffectsUnsetExcept(policy, -1);
+    }
+
+    @Test
+    public void testAllowMedia() {
+        ZenPolicy.Builder builder = new ZenPolicy.Builder();
+
+        builder.allowMedia(true);
+        ZenPolicy policy = builder.build();
+        assertAllPriorityCategoriesUnsetExcept(policy, ZenPolicy.PRIORITY_CATEGORY_MEDIA);
+        assertEquals(ZenPolicy.STATE_ALLOW, policy.getPriorityCategoryMedia());
+        assertAllVisualEffectsUnsetExcept(policy, -1);
+
+        builder.allowMedia(false);
+        policy = builder.build();
+        assertAllPriorityCategoriesUnsetExcept(policy, ZenPolicy.PRIORITY_CATEGORY_MEDIA);
+        assertEquals(ZenPolicy.STATE_DISALLOW, policy.getPriorityCategoryMedia());
+        assertAllVisualEffectsUnsetExcept(policy, -1);
+    }
+
+    @Test
+    public void testAllowSystem() {
+        ZenPolicy.Builder builder = new ZenPolicy.Builder();
+
+        builder.allowSystem(true);
+        ZenPolicy policy = builder.build();
+        assertAllPriorityCategoriesUnsetExcept(policy, ZenPolicy.PRIORITY_CATEGORY_SYSTEM);
+        assertEquals(ZenPolicy.STATE_ALLOW, policy.getPriorityCategorySystem());
+        assertAllVisualEffectsUnsetExcept(policy, -1);
+
+        builder.allowSystem(false);
+        policy = builder.build();
+        assertAllPriorityCategoriesUnsetExcept(policy, ZenPolicy.PRIORITY_CATEGORY_SYSTEM);
+        assertEquals(ZenPolicy.STATE_DISALLOW, policy.getPriorityCategorySystem());
+        assertAllVisualEffectsUnsetExcept(policy, -1);
+    }
+
+    private void assertAllPriorityCategoriesUnsetExcept(ZenPolicy policy, int except) {
+        if (except != ZenPolicy.PRIORITY_CATEGORY_REMINDERS) {
+            assertEquals(ZenPolicy.STATE_UNSET, policy.getPriorityCategoryReminders());
+        }
+
+        if (except != ZenPolicy.PRIORITY_CATEGORY_EVENTS) {
+            assertEquals(ZenPolicy.STATE_UNSET, policy.getPriorityCategoryEvents());
+        }
+
+        if (except != ZenPolicy.PRIORITY_CATEGORY_MESSAGES) {
+            assertEquals(ZenPolicy.STATE_UNSET, policy.getPriorityCategoryMessages());
+        }
+
+        if (except != ZenPolicy.PRIORITY_CATEGORY_CALLS) {
+            assertEquals(ZenPolicy.STATE_UNSET, policy.getPriorityCategoryCalls());
+        }
+
+        if (except != ZenPolicy.PRIORITY_CATEGORY_REPEAT_CALLERS) {
+            assertEquals(ZenPolicy.STATE_UNSET, policy.getPriorityCategoryRepeatCallers());
+        }
+
+        if (except != ZenPolicy.PRIORITY_CATEGORY_ALARMS) {
+            assertEquals(ZenPolicy.STATE_UNSET, policy.getPriorityCategoryAlarms());
+        }
+
+        if (except != ZenPolicy.PRIORITY_CATEGORY_MEDIA) {
+            assertEquals(ZenPolicy.STATE_UNSET, policy.getPriorityCategoryMedia());
+        }
+
+        if (except != ZenPolicy.PRIORITY_CATEGORY_SYSTEM) {
+            assertEquals(ZenPolicy.STATE_UNSET, policy.getPriorityCategorySystem());
+        }
+    }
+
+    private void assertAllVisualEffectsUnsetExcept(ZenPolicy policy, int except) {
+        if (except != ZenPolicy.VISUAL_EFFECT_FULL_SCREEN_INTENT) {
+            assertEquals(ZenPolicy.STATE_UNSET, policy.getVisualEffectFullScreenIntent());
+        }
+
+        if (except != ZenPolicy.VISUAL_EFFECT_LIGHTS) {
+            assertEquals(ZenPolicy.STATE_UNSET, policy.getVisualEffectLights());
+        }
+
+        if (except != ZenPolicy.VISUAL_EFFECT_PEEK) {
+            assertEquals(ZenPolicy.STATE_UNSET, policy.getVisualEffectPeek());
+        }
+
+        if (except != ZenPolicy.VISUAL_EFFECT_STATUS_BAR) {
+            assertEquals(ZenPolicy.STATE_UNSET, policy.getVisualEffectStatusBar());
+        }
+
+        if (except != ZenPolicy.VISUAL_EFFECT_BADGE) {
+            assertEquals(ZenPolicy.STATE_UNSET, policy.getVisualEffectBadge());
+        }
+
+        if (except != ZenPolicy.VISUAL_EFFECT_AMBIENT) {
+            assertEquals(ZenPolicy.STATE_UNSET, policy.getVisualEffectAmbient());
+        }
+
+        if (except != ZenPolicy.VISUAL_EFFECT_NOTIFICATION_LIST) {
+            assertEquals(ZenPolicy.STATE_UNSET, policy.getVisualEffectNotificationList());
+        }
+    }
+}
diff --git a/services/tests/wmtests/Android.mk b/services/tests/wmtests/Android.mk
new file mode 100644
index 0000000..0f8b18a
--- /dev/null
+++ b/services/tests/wmtests/Android.mk
@@ -0,0 +1,41 @@
+#########################################################################
+# Build WmTests package
+#########################################################################
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+# We only want this apk build for tests.
+LOCAL_MODULE_TAGS := tests
+
+# Include all test java files.
+LOCAL_SRC_FILES := \
+    $(call all-java-files-under, src) \
+    $(call all-java-files-under, ../servicestests/utils)
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    androidx-test \
+    mockito-target-minus-junit4 \
+    platform-test-annotations \
+
+LOCAL_JAVA_LIBRARIES := \
+    android.test.mock \
+    android.test.base \
+    android.test.runner \
+
+LOCAL_PACKAGE_NAME := WmTests
+LOCAL_PRIVATE_PLATFORM_APIS := true
+LOCAL_COMPATIBILITY_SUITE := device-tests
+
+LOCAL_CERTIFICATE := platform
+
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+
+LOCAL_JACK_FLAGS := --multi-dex native
+LOCAL_DX_FLAGS := --multi-dex
+
+LOCAL_PROGUARD_ENABLED := disabled
+
+include $(BUILD_PACKAGE)
+
+include $(call all-makefiles-under, $(LOCAL_PATH))
diff --git a/core/tests/webkit/AndroidManifest.xml b/services/tests/wmtests/AndroidManifest.xml
similarity index 61%
rename from core/tests/webkit/AndroidManifest.xml
rename to services/tests/wmtests/AndroidManifest.xml
index 42accdf..1fb9473 100644
--- a/core/tests/webkit/AndroidManifest.xml
+++ b/services/tests/wmtests/AndroidManifest.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 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.
@@ -15,16 +15,17 @@
 -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-          package="com.android.webkit.tests"
-          android:sharedUserId="android.uid.system">
+    package="com.android.frameworks.wmtests">
 
-    <application>
-        <uses-library android:name="android.test.runner" />
-    </application>
+    <!-- Uses API introduced in P (28) -->
+    <uses-sdk
+        android:minSdkVersion="1"
+        android:targetSdkVersion="28" />
+
+    <application android:testOnly="true" />
 
     <instrumentation
-            android:name="android.support.test.runner.AndroidJUnitRunner"
-            android:targetPackage="com.android.webkit.tests"
-            android:label="Frameworks WebView Loader Tests" />
-
+        android:name="androidx.test.runner.AndroidJUnitRunner"
+        android:label="Window Manager Tests"
+        android:targetPackage="com.android.frameworks.wmtests" />
 </manifest>
diff --git a/core/tests/webkit/AndroidTest.xml b/services/tests/wmtests/AndroidTest.xml
similarity index 66%
rename from core/tests/webkit/AndroidTest.xml
rename to services/tests/wmtests/AndroidTest.xml
index 4c50b7d..2717ef90 100644
--- a/core/tests/webkit/AndroidTest.xml
+++ b/services/tests/wmtests/AndroidTest.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 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.
@@ -13,18 +13,20 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<configuration description="Runs Frameworks WebView Loading Tests.">
+
+<configuration description="Runs Window Manager 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="test-file-name" value="WebViewLoadingTests.apk" />
-        <option name="test-file-name" value="WebViewLoadingOnDiskTestApk.apk" />
-        <option name="test-file-name" value="WebViewLoadingFromApkTestApk.apk" />
         <option name="cleanup-apks" value="true" />
-        <option name="alt-dir" value="out" />
+        <option name="install-arg" value="-t" />
+        <option name="test-file-name" value="WmTests.apk" />
     </target_preparer>
 
-    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
-        <option name="package" value="com.android.webkit.tests" />
+    <option name="test-tag" value="WmTests" />
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest">
+        <option name="package" value="com.android.frameworks.wmtests" />
+        <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
+        <option name="hidden-api-checks" value="false" />
     </test>
 </configuration>
diff --git a/services/tests/wmtests/src/com/android/server/am/DummyAmTests.java b/services/tests/wmtests/src/com/android/server/am/DummyAmTests.java
new file mode 100644
index 0000000..023e4ab
--- /dev/null
+++ b/services/tests/wmtests/src/com/android/server/am/DummyAmTests.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.am;
+
+import android.platform.test.annotations.Presubmit;
+
+import org.junit.Test;
+
+import androidx.test.filters.FlakyTest;
+
+/**
+ * Dummy test for com.android.server.am.
+ * TODO(b/113800711): Remove this class once the actual tests are moved from servicestests.
+ */
+public class DummyAmTests {
+
+    @Presubmit
+    @Test
+    public void preSubmitTest() {}
+
+    @FlakyTest
+    @Presubmit
+    @Test
+    public void flakyPreSubmitTest() {}
+
+    @Test
+    public void postSubmitTest() {}
+
+    @FlakyTest
+    @Test
+    public void flakyPostSubmitTest() {}
+}
diff --git a/services/tests/wmtests/src/com/android/server/wm/DummyWmTests.java b/services/tests/wmtests/src/com/android/server/wm/DummyWmTests.java
new file mode 100644
index 0000000..aecb278
--- /dev/null
+++ b/services/tests/wmtests/src/com/android/server/wm/DummyWmTests.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.wm;
+
+import android.platform.test.annotations.Presubmit;
+
+import org.junit.Test;
+
+import androidx.test.filters.FlakyTest;
+
+/**
+ * Dummy test for com.android.server.wm
+ * TODO(b/113800711): Remove this class once the actual tests are moved from servicestests.
+ */
+public class DummyWmTests {
+
+    @Presubmit
+    @Test
+    public void preSubmitTest() {}
+
+    @FlakyTest
+    @Presubmit
+    @Test
+    public void flakyPreSubmitTest() {}
+
+    @Test
+    public void postSubmitTest() {}
+
+    @FlakyTest
+    @Test
+    public void flakyPostSubmitTest() {}
+}
diff --git a/services/usage/java/com/android/server/usage/AppTimeLimitController.java b/services/usage/java/com/android/server/usage/AppTimeLimitController.java
index e7c54d8..5916b04c 100644
--- a/services/usage/java/com/android/server/usage/AppTimeLimitController.java
+++ b/services/usage/java/com/android/server/usage/AppTimeLimitController.java
@@ -168,6 +168,7 @@
     }
 
     /** Returns an existing UserData object for the given userId, or creates one */
+    @GuardedBy("mLock")
     private UserData getOrCreateUserDataLocked(int userId) {
         UserData userData = mUsers.get(userId);
         if (userData == null) {
diff --git a/services/usb/java/com/android/server/usb/UsbAlsaManager.java b/services/usb/java/com/android/server/usb/UsbAlsaManager.java
index 2f1c516..4874bce 100644
--- a/services/usb/java/com/android/server/usb/UsbAlsaManager.java
+++ b/services/usb/java/com/android/server/usb/UsbAlsaManager.java
@@ -44,6 +44,10 @@
     private static final String TAG = UsbAlsaManager.class.getSimpleName();
     private static final boolean DEBUG = false;
 
+    // Flag to turn on/off multi-peripheral select mode
+    // Set to true to have single-device-only mode
+    private static final boolean mIsSingleMode = true;
+
     private static final String ALSA_DIRECTORY = "/dev/snd/";
 
     private final Context mContext;
@@ -84,10 +88,11 @@
      */
     private synchronized void selectAlsaDevice(UsbAlsaDevice alsaDevice) {
         if (DEBUG) {
-            Slog.d(TAG, "selectAlsaDevice " + alsaDevice);
+            Slog.d(TAG, "selectAlsaDevice() " + alsaDevice);
         }
 
-        if (mSelectedDevice != null) {
+        // This must be where an existing USB audio device is deselected.... (I think)
+        if (mIsSingleMode && mSelectedDevice != null) {
             deselectAlsaDevice();
         }
 
@@ -104,9 +109,15 @@
 
         mSelectedDevice = alsaDevice;
         alsaDevice.start();
+        if (DEBUG) {
+            Slog.d(TAG, "selectAlsaDevice() - done.");
+        }
     }
 
     private synchronized void deselectAlsaDevice() {
+        if (DEBUG) {
+            Slog.d(TAG, "deselectAlsaDevice() mSelectedDevice " + mSelectedDevice);
+        }
         if (mSelectedDevice != null) {
             mSelectedDevice.stop();
             mSelectedDevice = null;
@@ -133,7 +144,7 @@
 
     /* package */ UsbAlsaDevice selectDefaultDevice() {
         if (DEBUG) {
-            Slog.d(TAG, "UsbAudioManager.selectDefaultDevice()");
+            Slog.d(TAG, "selectDefaultDevice()");
         }
 
         if (mAlsaDevices.size() > 0) {
@@ -230,6 +241,8 @@
             }
         }
 
+        logDevices("deviceAdded()");
+
         if (DEBUG) {
             Slog.d(TAG, "deviceAdded() - done");
         }
@@ -254,6 +267,9 @@
             Slog.i(TAG, "USB MIDI Device Removed: " + usbMidiDevice);
             IoUtils.closeQuietly(usbMidiDevice);
         }
+
+        logDevices("usbDeviceRemoved()");
+
     }
 
    /* package */ void setPeripheralMidiState(boolean enabled, int card, int device) {
@@ -296,6 +312,7 @@
     /**
      * Dump the USB alsa state.
      */
+    // invoked with "adb shell dumpsys usb"
     public void dump(DualDumpOutputStream dump, String idName, long id) {
         long token = dump.start(idName, id);
 
@@ -314,29 +331,26 @@
         dump.end(token);
     }
 
-/*
     public void logDevicesList(String title) {
-      if (DEBUG) {
-          for (HashMap.Entry<UsbDevice,UsbAlsaDevice> entry : mAudioDevices.entrySet()) {
-              Slog.i(TAG, "UsbDevice-------------------");
-              Slog.i(TAG, "" + (entry != null ? entry.getKey() : "[none]"));
-              Slog.i(TAG, "UsbAlsaDevice--------------");
-              Slog.i(TAG, "" + entry.getValue());
-          }
-      }
+        if (DEBUG) {
+            Slog.i(TAG, title + "----------------");
+            for (UsbAlsaDevice alsaDevice : mAlsaDevices) {
+                Slog.i(TAG, "  -->");
+                Slog.i(TAG, "" + alsaDevice);
+                Slog.i(TAG, "  <--");
+            }
+            Slog.i(TAG, "----------------");
+        }
     }
-*/
 
     // This logs a more terse (and more readable) version of the devices list
-/*
     public void logDevices(String title) {
-      if (DEBUG) {
-          Slog.i(TAG, title);
-          for (HashMap.Entry<UsbDevice,UsbAlsaDevice> entry : mAudioDevices.entrySet()) {
-              Slog.i(TAG, entry.getValue().toShortString());
-          }
-      }
+        if (DEBUG) {
+            Slog.i(TAG, title + "----------------");
+            for (UsbAlsaDevice alsaDevice : mAlsaDevices) {
+                Slog.i(TAG, alsaDevice.toShortString());
+            }
+            Slog.i(TAG, "----------------");
+        }
     }
-*/
-
 }
diff --git a/services/usb/java/com/android/server/usb/UsbHandlerManager.java b/services/usb/java/com/android/server/usb/UsbHandlerManager.java
new file mode 100644
index 0000000..1730d8f
--- /dev/null
+++ b/services/usb/java/com/android/server/usb/UsbHandlerManager.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.usb;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.ActivityNotFoundException;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ResolveInfo;
+import android.hardware.usb.UsbAccessory;
+import android.hardware.usb.UsbDevice;
+import android.hardware.usb.UsbManager;
+import android.os.UserHandle;
+import android.util.Slog;
+
+import java.util.ArrayList;
+
+/**
+ * UsbResolveActivityManager creates UI dialogs for user to pick or confirm handler for
+ * usb attach event.
+ *
+ * @hide
+ */
+class UsbHandlerManager {
+    private static final String LOG_TAG = UsbHandlerManager.class.getSimpleName();
+
+    private final Context mContext;
+
+    UsbHandlerManager(@NonNull Context context) {
+        mContext = context;
+    }
+
+    /**
+     * Shows dialog to user to allow them to optionally visit that URL for more
+     * information or software downloads if the attached USB accessory has a valid
+     * URL associated with it.
+     *
+     * @param accessory The accessory to confirm in the UI dialog
+     * @param user The user to start the UI dialog
+     */
+    void showUsbAccessoryUriActivity(@NonNull UsbAccessory accessory,
+            @NonNull UserHandle user) {
+        String uri = accessory.getUri();
+        if (uri != null && uri.length() > 0) {
+            // display URI to user
+            Intent dialogIntent = createDialogIntent();
+            dialogIntent.setClassName("com.android.systemui",
+                    "com.android.systemui.usb.UsbAccessoryUriActivity");
+            dialogIntent.putExtra(UsbManager.EXTRA_ACCESSORY, accessory);
+            dialogIntent.putExtra("uri", uri);
+            try {
+                mContext.startActivityAsUser(dialogIntent, user);
+            } catch (ActivityNotFoundException e) {
+                Slog.e(LOG_TAG, "unable to start UsbAccessoryUriActivity");
+            }
+        }
+    }
+
+    /**
+     * Shows dialog to user to confirm the package to start when the USB device
+     * or accessory is attached and there is only one package claims to handle this
+     * USB device or accessory.
+     *
+     * @param rInfo The ResolveInfo of the package to confirm in the UI dialog
+     * @param device The USB device to confirm
+     * @param accessory The USB accessory to confirm
+     */
+    void confirmUsbHandler(@NonNull ResolveInfo rInfo, @Nullable UsbDevice device,
+            @Nullable UsbAccessory accessory) {
+        Intent resolverIntent = createDialogIntent();
+        // start UsbConfirmActivity if there is only one choice
+        resolverIntent.setClassName("com.android.systemui",
+                "com.android.systemui.usb.UsbConfirmActivity");
+        resolverIntent.putExtra("rinfo", rInfo);
+        UserHandle user =
+                UserHandle.getUserHandleForUid(rInfo.activityInfo.applicationInfo.uid);
+
+        if (device != null) {
+            resolverIntent.putExtra(UsbManager.EXTRA_DEVICE, device);
+        } else {
+            resolverIntent.putExtra(UsbManager.EXTRA_ACCESSORY, accessory);
+        }
+
+        try {
+            mContext.startActivityAsUser(resolverIntent, user);
+        } catch (ActivityNotFoundException e) {
+            Slog.e(LOG_TAG, "unable to start activity " + resolverIntent, e);
+        }
+    }
+
+    /**
+     * Shows dialog to user to select the package to start when the USB device
+     * or accessory is attached and there are more than one package claim to handle this
+     * USB device or accessory.
+     *
+     * @param matches The available resolutions of the intent
+     * @param user The user to start UI dialog
+     * @param intent The intent to start the UI dialog
+     */
+    void selectUsbHandler(@NonNull ArrayList<ResolveInfo> matches,
+            @NonNull UserHandle user, @NonNull Intent intent) {
+        Intent resolverIntent = createDialogIntent();
+        resolverIntent.setClassName("com.android.systemui",
+                "com.android.systemui.usb.UsbResolverActivity");
+        resolverIntent.putParcelableArrayListExtra("rlist", matches);
+        resolverIntent.putExtra(Intent.EXTRA_INTENT, intent);
+
+        try {
+            mContext.startActivityAsUser(resolverIntent, user);
+        } catch (ActivityNotFoundException e) {
+            Slog.e(LOG_TAG, "unable to start activity " + resolverIntent, e);
+        }
+    }
+
+    private Intent createDialogIntent() {
+        Intent intent = new Intent();
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        return intent;
+    }
+}
diff --git a/services/usb/java/com/android/server/usb/UsbHostManager.java b/services/usb/java/com/android/server/usb/UsbHostManager.java
index 67ad090..cf47ad3 100644
--- a/services/usb/java/com/android/server/usb/UsbHostManager.java
+++ b/services/usb/java/com/android/server/usb/UsbHostManager.java
@@ -40,6 +40,7 @@
 import com.android.server.usb.descriptors.UsbDescriptor;
 import com.android.server.usb.descriptors.UsbDescriptorParser;
 import com.android.server.usb.descriptors.UsbDeviceDescriptor;
+import com.android.server.usb.descriptors.UsbInterfaceDescriptor;
 import com.android.server.usb.descriptors.report.TextReportCanvas;
 import com.android.server.usb.descriptors.tree.UsbDescriptorsTree;
 
@@ -352,8 +353,6 @@
             }
             return false;
         }
-        UsbDescriptorParser parser = new UsbDescriptorParser(deviceAddress, descriptors);
-        logUsbDevice(parser);
 
         if (isBlackListed(deviceClass, deviceSubclass)) {
             if (DEBUG) {
@@ -362,6 +361,15 @@
             return false;
         }
 
+        UsbDescriptorParser parser = new UsbDescriptorParser(deviceAddress, descriptors);
+        if (deviceClass == UsbConstants.USB_CLASS_PER_INTERFACE
+                && !checkUsbInterfacesBlackListed(parser)) {
+            return false;
+        }
+
+        // Potentially can block as it may read data from the USB device.
+        logUsbDevice(parser);
+
         synchronized (mLock) {
             if (mDevices.get(deviceAddress) != null) {
                 Slog.w(TAG, "device already on mDevices list: " + deviceAddress);
@@ -408,11 +416,15 @@
     /* Called from JNI in monitorUsbHostBus to report USB device removal */
     @SuppressWarnings("unused")
     private void usbDeviceRemoved(String deviceAddress) {
+        if (DEBUG) {
+            Slog.d(TAG, "usbDeviceRemoved(" + deviceAddress + ") end");
+        }
+
         synchronized (mLock) {
             UsbDevice device = mDevices.remove(deviceAddress);
             if (device != null) {
                 Slog.d(TAG, "Removed device at " + deviceAddress + ": " + device.getProductName());
-                mUsbAlsaManager.usbDeviceRemoved(deviceAddress/*device*/);
+                mUsbAlsaManager.usbDeviceRemoved(deviceAddress);
                 mSettingsManager.usbDeviceRemoved(device);
                 getCurrentUserSettings().usbDeviceRemoved(device);
 
@@ -509,6 +521,29 @@
         }
     }
 
+    private boolean checkUsbInterfacesBlackListed(UsbDescriptorParser parser) {
+        // Device class needs to be obtained through the device interface.  Ignore device only
+        // if ALL interfaces are black-listed.
+        boolean shouldIgnoreDevice = false;
+        for (UsbDescriptor descriptor: parser.getDescriptors()) {
+            if (!(descriptor instanceof UsbInterfaceDescriptor)) {
+                continue;
+            }
+            UsbInterfaceDescriptor iface = (UsbInterfaceDescriptor) descriptor;
+            shouldIgnoreDevice = isBlackListed(iface.getUsbClass(), iface.getUsbSubclass());
+            if (!shouldIgnoreDevice) {
+                break;
+            }
+        }
+        if (shouldIgnoreDevice) {
+            if (DEBUG) {
+                Slog.d(TAG, "usb interface class is black listed");
+            }
+            return false;
+        }
+        return true;
+    }
+
     private native void monitorUsbHostBus();
     private native ParcelFileDescriptor nativeOpenDevice(String deviceAddress);
 }
diff --git a/services/usb/java/com/android/server/usb/UsbPermissionManager.java b/services/usb/java/com/android/server/usb/UsbPermissionManager.java
new file mode 100644
index 0000000..2c9ee36
--- /dev/null
+++ b/services/usb/java/com/android/server/usb/UsbPermissionManager.java
@@ -0,0 +1,246 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.usb;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.PendingIntent;
+import android.content.ActivityNotFoundException;
+import android.content.Context;
+import android.content.Intent;
+import android.hardware.usb.UsbAccessory;
+import android.hardware.usb.UsbDevice;
+import android.hardware.usb.UsbManager;
+import android.os.Binder;
+import android.os.Process;
+import android.os.UserHandle;
+import android.service.usb.UsbSettingsAccessoryPermissionProto;
+import android.service.usb.UsbSettingsDevicePermissionProto;
+import android.service.usb.UsbUserSettingsManagerProto;
+import android.util.Slog;
+import android.util.SparseBooleanArray;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.dump.DualDumpOutputStream;
+
+import java.util.HashMap;
+
+/**
+ * UsbPermissionManager manages usb device or accessory access permissions.
+ *
+ * @hide
+ */
+class UsbPermissionManager {
+    private static final String LOG_TAG = UsbPermissionManager.class.getSimpleName();
+
+    @GuardedBy("mLock")
+    /** Temporary mapping USB device name to list of UIDs with permissions for the device*/
+    private final HashMap<String, SparseBooleanArray> mDevicePermissionMap =
+            new HashMap<>();
+    @GuardedBy("mLock")
+    /** Temporary mapping UsbAccessory to list of UIDs with permissions for the accessory*/
+    private final HashMap<UsbAccessory, SparseBooleanArray> mAccessoryPermissionMap =
+            new HashMap<>();
+
+    private final UserHandle mUser;
+    private final boolean mDisablePermissionDialogs;
+
+    private final Object mLock = new Object();
+
+    UsbPermissionManager(@NonNull Context context, @NonNull UserHandle user) {
+        mUser = user;
+        mDisablePermissionDialogs = context.getResources().getBoolean(
+                com.android.internal.R.bool.config_disableUsbPermissionDialogs);
+    }
+
+    /**
+     * Removes access permissions of all packages for the USB accessory.
+     *
+     * @param accessory to remove permissions for
+     */
+    void removeAccessoryPermissions(@NonNull UsbAccessory accessory) {
+        synchronized (mLock) {
+            mAccessoryPermissionMap.remove(accessory);
+        }
+    }
+
+    /**
+     * Removes access permissions of all packages for the USB device.
+     *
+     * @param device to remove permissions for
+     */
+    void removeDevicePermissions(@NonNull UsbDevice device) {
+        synchronized (mLock) {
+            mDevicePermissionMap.remove(device.getDeviceName());
+        }
+    }
+
+    /**
+     * Grants permission for USB device without showing system dialog for package with uid.
+     *
+     * @param device to grant permission for
+     * @param uid to grant permission for
+     */
+    void grantDevicePermission(@NonNull UsbDevice device, int uid) {
+        synchronized (mLock) {
+            String deviceName = device.getDeviceName();
+            SparseBooleanArray uidList = mDevicePermissionMap.get(deviceName);
+            if (uidList == null) {
+                uidList = new SparseBooleanArray(1);
+                mDevicePermissionMap.put(deviceName, uidList);
+            }
+            uidList.put(uid, true);
+        }
+    }
+
+    /**
+     * Grants permission for USB accessory without showing system dialog for package with uid.
+     *
+     * @param accessory to grant permission for
+     * @param uid to grant permission for
+     */
+    void grantAccessoryPermission(@NonNull UsbAccessory accessory, int uid) {
+        synchronized (mLock) {
+            SparseBooleanArray uidList = mAccessoryPermissionMap.get(accessory);
+            if (uidList == null) {
+                uidList = new SparseBooleanArray(1);
+                mAccessoryPermissionMap.put(accessory, uidList);
+            }
+            uidList.put(uid, true);
+        }
+    }
+
+    /**
+     * Returns true if package with uid has permission to access the device.
+     *
+     * @param device to check permission for
+     * @param uid to check permission for
+     * @return {@code true} if package with uid has permission
+     */
+    boolean hasPermission(@NonNull UsbDevice device, int uid) {
+        synchronized (mLock) {
+            if (uid == Process.SYSTEM_UID || mDisablePermissionDialogs) {
+                return true;
+            }
+            SparseBooleanArray uidList = mDevicePermissionMap.get(device.getDeviceName());
+            if (uidList == null) {
+                return false;
+            }
+            return uidList.get(uid);
+        }
+    }
+
+    /**
+     * Returns true if caller has permission to access the accessory.
+     *
+     * @param accessory to check permission for
+     * @return {@code true} if caller has permssion
+     */
+    boolean hasPermission(@NonNull UsbAccessory accessory) {
+        synchronized (mLock) {
+            int uid = Binder.getCallingUid();
+            if (uid == Process.SYSTEM_UID || mDisablePermissionDialogs) {
+                return true;
+            }
+            SparseBooleanArray uidList = mAccessoryPermissionMap.get(accessory);
+            if (uidList == null) {
+                return false;
+            }
+            return uidList.get(uid);
+        }
+    }
+
+    /**
+     * Creates UI dialog to request permission for the given package to access the device
+     * or accessory.
+     *
+     * @param device The USB device attached
+     * @param accessory The USB accessory attached
+     * @param canBeDefault Whether the calling pacakge can set as default handler
+     * of the USB device or accessory
+     * @param packageName The package name of the calling package
+     * @param uid The uid of the calling package
+     * @param userContext The context to start the UI dialog
+     * @param pi PendingIntent for returning result
+     */
+    void requestPermissionDialog(@Nullable UsbDevice device,
+                                 @Nullable UsbAccessory accessory,
+                                 boolean canBeDefault,
+                                 @NonNull String packageName,
+                                 int uid,
+                                 @NonNull Context userContext,
+                                 @NonNull PendingIntent pi) {
+        long identity = Binder.clearCallingIdentity();
+        Intent intent = new Intent();
+        if (device != null) {
+            intent.putExtra(UsbManager.EXTRA_DEVICE, device);
+        } else {
+            intent.putExtra(UsbManager.EXTRA_ACCESSORY, accessory);
+        }
+        intent.putExtra(Intent.EXTRA_INTENT, pi);
+        intent.putExtra(Intent.EXTRA_UID, uid);
+        intent.putExtra(UsbManager.EXTRA_CAN_BE_DEFAULT, canBeDefault);
+        intent.putExtra(UsbManager.EXTRA_PACKAGE, packageName);
+        intent.setClassName("com.android.systemui",
+                "com.android.systemui.usb.UsbPermissionActivity");
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+        try {
+            userContext.startActivityAsUser(intent, mUser);
+        } catch (ActivityNotFoundException e) {
+            Slog.e(LOG_TAG, "unable to start UsbPermissionActivity");
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    void dump(@NonNull DualDumpOutputStream dump) {
+        synchronized (mLock) {
+            for (String deviceName : mDevicePermissionMap.keySet()) {
+                long devicePermissionToken = dump.start("device_permissions",
+                        UsbUserSettingsManagerProto.DEVICE_PERMISSIONS);
+
+                dump.write("device_name", UsbSettingsDevicePermissionProto.DEVICE_NAME, deviceName);
+
+                SparseBooleanArray uidList = mDevicePermissionMap.get(deviceName);
+                int count = uidList.size();
+                for (int i = 0; i < count; i++) {
+                    dump.write("uids", UsbSettingsDevicePermissionProto.UIDS, uidList.keyAt(i));
+                }
+
+                dump.end(devicePermissionToken);
+            }
+
+            for (UsbAccessory accessory : mAccessoryPermissionMap.keySet()) {
+                long accessoryPermissionToken = dump.start("accessory_permissions",
+                        UsbUserSettingsManagerProto.ACCESSORY_PERMISSIONS);
+
+                dump.write("accessory_description",
+                        UsbSettingsAccessoryPermissionProto.ACCESSORY_DESCRIPTION,
+                        accessory.getDescription());
+
+                SparseBooleanArray uidList = mAccessoryPermissionMap.get(accessory);
+                int count = uidList.size();
+                for (int i = 0; i < count; i++) {
+                    dump.write("uids", UsbSettingsAccessoryPermissionProto.UIDS, uidList.keyAt(i));
+                }
+
+                dump.end(accessoryPermissionToken);
+            }
+        }
+    }
+}
diff --git a/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java b/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java
index 7a906d0..1ab1f7e 100644
--- a/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java
+++ b/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java
@@ -193,6 +193,8 @@
 
     MyPackageMonitor mPackageMonitor = new MyPackageMonitor();
 
+    private final UsbHandlerManager mUsbHandlerManager;
+
     private final MtpNotificationManager mMtpNotificationManager;
 
     /**
@@ -201,9 +203,11 @@
      * @param context The context of the service
      * @param user The parent profile
      * @param settingsManager The settings manager of the service
+     * @param usbResolveActivityManager The resovle activity manager of the service
      */
     UsbProfileGroupSettingsManager(@NonNull Context context, @NonNull UserHandle user,
-            @NonNull UsbSettingsManager settingsManager) {
+            @NonNull UsbSettingsManager settingsManager,
+            @NonNull UsbHandlerManager usbResolveActivityManager) {
         if (DEBUG) Slog.v(TAG, "Creating settings for " + user);
 
         Context parentUserContext;
@@ -238,6 +242,8 @@
                 parentUserContext,
                 device -> resolveActivity(createDeviceAttachedIntent(device),
                         device, false /* showMtpNotification */));
+
+        mUsbHandlerManager = usbResolveActivityManager;
     }
 
     /**
@@ -830,23 +836,8 @@
         // don't show the resolver activity if there are no choices available
         if (matches.size() == 0) {
             if (accessory != null) {
-                String uri = accessory.getUri();
-                if (uri != null && uri.length() > 0) {
-                    // display URI to user
-                    Intent dialogIntent = new Intent();
-                    dialogIntent.setClassName("com.android.systemui",
-                            "com.android.systemui.usb.UsbAccessoryUriActivity");
-                    dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-                    dialogIntent.putExtra(UsbManager.EXTRA_ACCESSORY, accessory);
-                    dialogIntent.putExtra("uri", uri);
-                    try {
-                        mContext.startActivityAsUser(dialogIntent, mParentUser);
-                    } catch (ActivityNotFoundException e) {
-                        Slog.e(TAG, "unable to start UsbAccessoryUriActivity");
-                    }
-                }
+                mUsbHandlerManager.showUsbAccessoryUriActivity(accessory, mParentUser);
             }
-
             // do nothing
             return;
         }
@@ -875,37 +866,10 @@
                 Slog.e(TAG, "startActivity failed", e);
             }
         } else {
-            Intent resolverIntent = new Intent();
-            resolverIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-            UserHandle user;
-
             if (matches.size() == 1) {
-                ResolveInfo rInfo = matches.get(0);
-
-                // start UsbConfirmActivity if there is only one choice
-                resolverIntent.setClassName("com.android.systemui",
-                        "com.android.systemui.usb.UsbConfirmActivity");
-                resolverIntent.putExtra("rinfo", rInfo);
-                user = UserHandle.getUserHandleForUid(rInfo.activityInfo.applicationInfo.uid);
-
-                if (device != null) {
-                    resolverIntent.putExtra(UsbManager.EXTRA_DEVICE, device);
-                } else {
-                    resolverIntent.putExtra(UsbManager.EXTRA_ACCESSORY, accessory);
-                }
+                mUsbHandlerManager.confirmUsbHandler(matches.get(0), device, accessory);
             } else {
-                user = mParentUser;
-
-                // start UsbResolverActivity so user can choose an activity
-                resolverIntent.setClassName("com.android.systemui",
-                        "com.android.systemui.usb.UsbResolverActivity");
-                resolverIntent.putParcelableArrayListExtra("rlist", matches);
-                resolverIntent.putExtra(Intent.EXTRA_INTENT, intent);
-            }
-            try {
-                mContext.startActivityAsUser(resolverIntent, user);
-            } catch (ActivityNotFoundException e) {
-                Slog.e(TAG, "unable to start activity " + resolverIntent, e);
+                mUsbHandlerManager.selectUsbHandler(matches, mParentUser, intent);
             }
         }
     }
diff --git a/services/usb/java/com/android/server/usb/UsbSettingsManager.java b/services/usb/java/com/android/server/usb/UsbSettingsManager.java
index 9221825..27566f0 100644
--- a/services/usb/java/com/android/server/usb/UsbSettingsManager.java
+++ b/services/usb/java/com/android/server/usb/UsbSettingsManager.java
@@ -57,10 +57,12 @@
     private final SparseArray<UsbProfileGroupSettingsManager> mSettingsByProfileGroup
             = new SparseArray<>();
     private UserManager mUserManager;
+    private UsbHandlerManager mUsbHandlerManager;
 
     public UsbSettingsManager(@NonNull Context context) {
         mContext = context;
         mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
+        mUsbHandlerManager = new UsbHandlerManager(context);
     }
 
     /**
@@ -74,7 +76,8 @@
         synchronized (mSettingsByUser) {
             UsbUserSettingsManager settings = mSettingsByUser.get(userId);
             if (settings == null) {
-                settings = new UsbUserSettingsManager(mContext, new UserHandle(userId));
+                settings = new UsbUserSettingsManager(mContext, UserHandle.of(userId),
+                        new UsbPermissionManager(mContext, UserHandle.of(userId)));
                 mSettingsByUser.put(userId, settings);
             }
             return settings;
@@ -102,7 +105,8 @@
             UsbProfileGroupSettingsManager settings = mSettingsByProfileGroup.get(
                     parentUser.getIdentifier());
             if (settings == null) {
-                settings = new UsbProfileGroupSettingsManager(mContext, parentUser, this);
+                settings = new UsbProfileGroupSettingsManager(mContext, parentUser, this,
+                      mUsbHandlerManager);
                 mSettingsByProfileGroup.put(parentUser.getIdentifier(), settings);
             }
             return settings;
diff --git a/services/usb/java/com/android/server/usb/UsbUserSettingsManager.java b/services/usb/java/com/android/server/usb/UsbUserSettingsManager.java
index 24a2d72..fe93399 100644
--- a/services/usb/java/com/android/server/usb/UsbUserSettingsManager.java
+++ b/services/usb/java/com/android/server/usb/UsbUserSettingsManager.java
@@ -21,15 +21,18 @@
 import static com.android.server.usb.UsbProfileGroupSettingsManager.getDeviceFilters;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.app.PendingIntent;
-import android.content.ActivityNotFoundException;
 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.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ResolveInfo;
+import android.content.res.XmlResourceParser;
 import android.hardware.usb.AccessoryFilter;
 import android.hardware.usb.DeviceFilter;
 import android.hardware.usb.UsbAccessory;
@@ -38,42 +41,34 @@
 import android.hardware.usb.UsbInterface;
 import android.hardware.usb.UsbManager;
 import android.os.Binder;
-import android.os.Process;
 import android.os.UserHandle;
 import android.service.usb.UsbAccessoryAttachedActivities;
 import android.service.usb.UsbDeviceAttachedActivities;
-import android.service.usb.UsbSettingsAccessoryPermissionProto;
-import android.service.usb.UsbSettingsDevicePermissionProto;
 import android.service.usb.UsbUserSettingsManagerProto;
 import android.util.Slog;
-import android.util.SparseBooleanArray;
 
+import com.android.internal.util.XmlUtils;
 import com.android.internal.util.dump.DualDumpOutputStream;
 
+import org.xmlpull.v1.XmlPullParser;
+
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.List;
 
 class UsbUserSettingsManager {
-    private static final String TAG = "UsbUserSettingsManager";
+    private static final String TAG = UsbUserSettingsManager.class.getSimpleName();
     private static final boolean DEBUG = false;
 
     private final UserHandle mUser;
-    private final boolean mDisablePermissionDialogs;
 
     private final Context mUserContext;
     private final PackageManager mPackageManager;
-
-    // Temporary mapping USB device name to list of UIDs with permissions for the device
-    private final HashMap<String, SparseBooleanArray> mDevicePermissionMap =
-            new HashMap<>();
-    // Temporary mapping UsbAccessory to list of UIDs with permissions for the accessory
-    private final HashMap<UsbAccessory, SparseBooleanArray> mAccessoryPermissionMap =
-            new HashMap<>();
+    private final UsbPermissionManager mUsbPermissionManager;
 
     private final Object mLock = new Object();
 
-    public UsbUserSettingsManager(Context context, UserHandle user) {
+    UsbUserSettingsManager(Context context, UserHandle user,
+            @NonNull UsbPermissionManager usbPermissionManager) {
         if (DEBUG) Slog.v(TAG, "Creating settings for " + user);
 
         try {
@@ -85,9 +80,7 @@
         mPackageManager = mUserContext.getPackageManager();
 
         mUser = user;
-
-        mDisablePermissionDialogs = context.getResources().getBoolean(
-                com.android.internal.R.bool.config_disableUsbPermissionDialogs);
+        mUsbPermissionManager = usbPermissionManager;
     }
 
     /**
@@ -96,9 +89,7 @@
      * @param device The device the permissions are for
      */
     void removeDevicePermissions(@NonNull UsbDevice device) {
-        synchronized (mLock) {
-            mDevicePermissionMap.remove(device.getDeviceName());
-        }
+        mUsbPermissionManager.removeDevicePermissions(device);
     }
 
     /**
@@ -107,9 +98,7 @@
      * @param accessory The accessory the permissions are for
      */
     void removeAccessoryPermissions(@NonNull UsbAccessory accessory) {
-        synchronized (mLock) {
-            mAccessoryPermissionMap.remove(accessory);
-        }
+        mUsbPermissionManager.removeAccessoryPermissions(accessory);
     }
 
     /**
@@ -170,35 +159,17 @@
     }
 
     public boolean hasPermission(UsbDevice device, String packageName, int uid) {
-        synchronized (mLock) {
-            if (isCameraDevicePresent(device)) {
-                if (!isCameraPermissionGranted(packageName, uid)) {
-                    return false;
-                }
-            }
-            if (uid == Process.SYSTEM_UID || mDisablePermissionDialogs) {
-                return true;
-            }
-            SparseBooleanArray uidList = mDevicePermissionMap.get(device.getDeviceName());
-            if (uidList == null) {
+        if (isCameraDevicePresent(device)) {
+            if (!isCameraPermissionGranted(packageName, uid)) {
                 return false;
             }
-            return uidList.get(uid);
         }
+
+        return mUsbPermissionManager.hasPermission(device, uid);
     }
 
     public boolean hasPermission(UsbAccessory accessory) {
-        synchronized (mLock) {
-            int uid = Binder.getCallingUid();
-            if (uid == Process.SYSTEM_UID || mDisablePermissionDialogs) {
-                return true;
-            }
-            SparseBooleanArray uidList = mAccessoryPermissionMap.get(accessory);
-            if (uidList == null) {
-                return false;
-            }
-            return uidList.get(uid);
-        }
+        return mUsbPermissionManager.hasPermission(accessory);
     }
 
     public void checkPermission(UsbDevice device, String packageName, int uid) {
@@ -213,7 +184,11 @@
         }
     }
 
-    private void requestPermissionDialog(Intent intent, String packageName, PendingIntent pi) {
+    private void requestPermissionDialog(@Nullable UsbDevice device,
+                                         @Nullable UsbAccessory accessory,
+                                         boolean canBeDefault,
+                                         String packageName,
+                                         PendingIntent pi) {
         final int uid = Binder.getCallingUid();
 
         // compare uid with packageName to foil apps pretending to be someone else
@@ -227,27 +202,15 @@
             throw new IllegalArgumentException("package " + packageName + " not found");
         }
 
-        long identity = Binder.clearCallingIdentity();
-        intent.setClassName("com.android.systemui",
-                "com.android.systemui.usb.UsbPermissionActivity");
-        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        intent.putExtra(Intent.EXTRA_INTENT, pi);
-        intent.putExtra("package", packageName);
-        intent.putExtra(Intent.EXTRA_UID, uid);
-        try {
-            mUserContext.startActivityAsUser(intent, mUser);
-        } catch (ActivityNotFoundException e) {
-            Slog.e(TAG, "unable to start UsbPermissionActivity");
-        } finally {
-            Binder.restoreCallingIdentity(identity);
-        }
+        mUsbPermissionManager.requestPermissionDialog(device,
+                accessory, canBeDefault, packageName, uid, mUserContext, pi);
     }
 
     public void requestPermission(UsbDevice device, String packageName, PendingIntent pi, int uid) {
-      Intent intent = new Intent();
+        Intent intent = new Intent();
 
         // respond immediately if permission has already been granted
-      if (hasPermission(device, packageName, uid)) {
+        if (hasPermission(device, packageName, uid)) {
             intent.putExtra(UsbManager.EXTRA_DEVICE, device);
             intent.putExtra(UsbManager.EXTRA_PERMISSION_GRANTED, true);
             try {
@@ -270,16 +233,13 @@
             }
         }
 
-        // start UsbPermissionActivity so user can choose an activity
-        intent.putExtra(UsbManager.EXTRA_DEVICE, device);
-        requestPermissionDialog(intent, packageName, pi);
+        requestPermissionDialog(device, null, canBeDefault(device, packageName), packageName, pi);
     }
 
     public void requestPermission(UsbAccessory accessory, String packageName, PendingIntent pi) {
-        Intent intent = new Intent();
-
         // respond immediately if permission has already been granted
         if (hasPermission(accessory)) {
+            Intent intent = new Intent();
             intent.putExtra(UsbManager.EXTRA_ACCESSORY, accessory);
             intent.putExtra(UsbManager.EXTRA_PERMISSION_GRANTED, true);
             try {
@@ -290,31 +250,16 @@
             return;
         }
 
-        intent.putExtra(UsbManager.EXTRA_ACCESSORY, accessory);
-        requestPermissionDialog(intent, packageName, pi);
+        requestPermissionDialog(null, accessory,
+                canBeDefault(accessory, packageName), packageName, pi);
     }
 
     public void grantDevicePermission(UsbDevice device, int uid) {
-        synchronized (mLock) {
-            String deviceName = device.getDeviceName();
-            SparseBooleanArray uidList = mDevicePermissionMap.get(deviceName);
-            if (uidList == null) {
-                uidList = new SparseBooleanArray(1);
-                mDevicePermissionMap.put(deviceName, uidList);
-            }
-            uidList.put(uid, true);
-        }
+        mUsbPermissionManager.grantDevicePermission(device, uid);
     }
 
     public void grantAccessoryPermission(UsbAccessory accessory, int uid) {
-        synchronized (mLock) {
-            SparseBooleanArray uidList = mAccessoryPermissionMap.get(accessory);
-            if (uidList == null) {
-                uidList = new SparseBooleanArray(1);
-                mAccessoryPermissionMap.put(accessory, uidList);
-            }
-            uidList.put(uid, true);
-        }
+        mUsbPermissionManager.grantAccessoryPermission(accessory, uid);
     }
 
     /**
@@ -329,42 +274,108 @@
                 mUser.getIdentifier());
     }
 
+    /**
+     * Can the app be the default for the USB device. I.e. can the app be launched by default if
+     * the device is plugged in.
+     *
+     * @param device The device the app would be default for
+     * @param packageName The package name of the app
+     *
+     * @return {@code true} if the app can be default
+     */
+    private boolean canBeDefault(@NonNull UsbDevice device, String packageName) {
+        ActivityInfo[] activities = getPackageActivities(packageName);
+        if (activities != null) {
+            int numActivities = activities.length;
+            for (int i = 0; i < numActivities; i++) {
+                ActivityInfo activityInfo = activities[i];
+
+                try (XmlResourceParser parser = activityInfo.loadXmlMetaData(mPackageManager,
+                        UsbManager.ACTION_USB_DEVICE_ATTACHED)) {
+                    if (parser == null) {
+                        continue;
+                    }
+
+                    XmlUtils.nextElement(parser);
+                    while (parser.getEventType() != XmlPullParser.END_DOCUMENT) {
+                        if ("usb-device".equals(parser.getName())) {
+                            DeviceFilter filter = DeviceFilter.read(parser);
+                            if (filter.matches(device)) {
+                                return true;
+                            }
+                        }
+
+                        XmlUtils.nextElement(parser);
+                    }
+                } catch (Exception e) {
+                    Slog.w(TAG, "Unable to load component info " + activityInfo.toString(), e);
+                }
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * Can the app be the default for the USB accessory. I.e. can the app be launched by default if
+     * the accessory is plugged in.
+     *
+     * @param accessory The accessory the app would be default for
+     * @param packageName The package name of the app
+     *
+     * @return {@code true} if the app can be default
+     */
+    private boolean canBeDefault(@NonNull UsbAccessory accessory, String packageName) {
+        ActivityInfo[] activities = getPackageActivities(packageName);
+        if (activities != null) {
+            int numActivities = activities.length;
+            for (int i = 0; i < numActivities; i++) {
+                ActivityInfo activityInfo = activities[i];
+
+                try (XmlResourceParser parser = activityInfo.loadXmlMetaData(mPackageManager,
+                        UsbManager.ACTION_USB_ACCESSORY_ATTACHED)) {
+                    if (parser == null) {
+                        continue;
+                    }
+
+                    XmlUtils.nextElement(parser);
+                    while (parser.getEventType() != XmlPullParser.END_DOCUMENT) {
+                        if ("usb-accessory".equals(parser.getName())) {
+                            AccessoryFilter filter = AccessoryFilter.read(parser);
+                            if (filter.matches(accessory)) {
+                                return true;
+                            }
+                        }
+
+                        XmlUtils.nextElement(parser);
+                    }
+                } catch (Exception e) {
+                    Slog.w(TAG, "Unable to load component info " + activityInfo.toString(), e);
+                }
+            }
+        }
+
+        return false;
+    }
+
+    private ActivityInfo[] getPackageActivities(String packageName) {
+        try {
+            PackageInfo packageInfo = mPackageManager.getPackageInfo(packageName,
+                    PackageManager.GET_ACTIVITIES | PackageManager.GET_META_DATA);
+            return packageInfo.activities;
+        } catch (PackageManager.NameNotFoundException e) {
+            // ignore
+        }
+        return null;
+    }
+
     public void dump(@NonNull DualDumpOutputStream dump, @NonNull String idName, long id) {
         long token = dump.start(idName, id);
 
         synchronized (mLock) {
             dump.write("user_id", UsbUserSettingsManagerProto.USER_ID, mUser.getIdentifier());
 
-            for (String deviceName : mDevicePermissionMap.keySet()) {
-                long devicePermissionToken = dump.start("device_permissions",
-                        UsbUserSettingsManagerProto.DEVICE_PERMISSIONS);
-
-                dump.write("device_name", UsbSettingsDevicePermissionProto.DEVICE_NAME, deviceName);
-
-                SparseBooleanArray uidList = mDevicePermissionMap.get(deviceName);
-                int count = uidList.size();
-                for (int i = 0; i < count; i++) {
-                    dump.write("uids", UsbSettingsDevicePermissionProto.UIDS, uidList.keyAt(i));
-                }
-
-                dump.end(devicePermissionToken);
-            }
-            for (UsbAccessory accessory : mAccessoryPermissionMap.keySet()) {
-                long accessoryPermissionToken = dump.start("accessory_permissions",
-                        UsbUserSettingsManagerProto.ACCESSORY_PERMISSIONS);
-
-                dump.write("accessory_description",
-                        UsbSettingsAccessoryPermissionProto.ACCESSORY_DESCRIPTION,
-                        accessory.getDescription());
-
-                SparseBooleanArray uidList = mAccessoryPermissionMap.get(accessory);
-                int count = uidList.size();
-                for (int i = 0; i < count; i++) {
-                    dump.write("uids", UsbSettingsAccessoryPermissionProto.UIDS, uidList.keyAt(i));
-                }
-
-                dump.end(accessoryPermissionToken);
-            }
+            mUsbPermissionManager.dump(dump);
 
             List<ResolveInfo> deviceAttachedActivities = queryIntentActivities(
                     new Intent(UsbManager.ACTION_USB_DEVICE_ATTACHED));
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
index de177169..7c22613 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
@@ -670,6 +670,7 @@
         /**
          * Disconnect from the service, but allow to re-connect when new operations are triggered.
          */
+        @GuardedBy("mRemoteServiceLock")
         private void disconnectLocked() {
             if (mService != null) {
                 try {
diff --git a/startop/OWNERS b/startop/OWNERS
new file mode 100644
index 0000000..bfe96d3
--- /dev/null
+++ b/startop/OWNERS
@@ -0,0 +1,5 @@
+# mailing list: startop-eng@google.com
+chriswailes@google.com
+eholk@google.com
+iam@google.com
+sehr@google.com
diff --git a/startop/scripts/app_startup/analyze_metrics.py b/startop/scripts/app_startup/analyze_metrics.py
new file mode 100755
index 0000000..d74d6f6
--- /dev/null
+++ b/startop/scripts/app_startup/analyze_metrics.py
@@ -0,0 +1,457 @@
+#!/usr/bin/env python3
+#
+# 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.
+
+"""
+Perform statistical analysis on measurements produced by app_startup_runner.py
+
+Install:
+$> sudo apt-get install python3-scipy
+
+Usage:
+$> ./analyze_metrics.py <filename.csv> [<filename2.csv> ...]
+$> ./analyze_metrics.py --help
+"""
+
+import argparse
+import csv
+import itertools
+import os
+import subprocess
+import sys
+import tempfile
+from typing import Any, List, Dict, Iterable, TextIO, Tuple
+
+from scipy import stats as sc
+import numpy as np
+
+
+# These CSV columns are considered labels. Everything after them in the same row are metrics.
+_LABEL_COLUMNS=['packages', 'readaheads', 'compiler_filters']
+# The metric series with the 'cold' readahead is the baseline.
+# All others (warm, jit, etc) are the potential improvements.
+
+#fixme: this should probably be an option
+_BASELINE=('readaheads', 'cold')
+# ignore this for some statistic calculations
+_IGNORE_PAIR=('readaheads', 'warm')
+_PLOT_SUBKEY='readaheads'
+_PLOT_GROUPKEY='packages'
+_PLOT_DATA_INDEX = 0
+_DELTA=50
+_DELTA2=100
+_PVALUE_THRESHOLD=0.10
+_debug = False  # See -d/--debug flag.
+
+def parse_options(argv: List[str] = None):
+  """Parse command line arguments and return an argparse Namespace object."""
+  parser = argparse.ArgumentParser(description="Perform statistical analysis on measurements produced by app_start_runner.py.")
+  parser.add_argument('input_files', metavar='file.csv', nargs='+', help='CSV file produced by app_startup_runner.py')
+
+  parser.add_argument('-d', '--debug', dest='debug', action='store_true', help='Add extra debugging output')
+  parser.add_argument('-os', '--output-samples', dest='output_samples', default='/dev/null', action='store', help='Store CSV for per-sample data')
+  parser.add_argument('-oc', '--output-comparable', dest='output_comparable', default='/dev/null', action='store', help='Output CSV for comparable against baseline')
+  parser.add_argument('-ocs', '--output-comparable-significant', dest='output_comparable_significant', default='/dev/null', action='store', help='Output CSV for comparable against baseline (significant only)')
+  parser.add_argument('-pt', '--pvalue-threshold', dest='pvalue_threshold', type=float, default=_PVALUE_THRESHOLD, action='store')
+  parser.add_argument('-dt', '--delta-threshold', dest='delta_threshold', type=int, default=_DELTA, action='store')
+
+  return parser.parse_args(argv)
+
+def _debug_print(*args, **kwargs):
+  """Print the args to sys.stderr if the --debug/-d flag was passed in."""
+  global _debug
+  if _debug:
+    print(*args, **kwargs, file=sys.stderr)
+
+def _expand_gen_repr(args):
+  new_args_list = []
+  for i in args:
+    # detect iterable objects that do not have their own override of __str__
+    if hasattr(i, '__iter__'):
+      to_str = getattr(i, '__str__')
+      if to_str.__objclass__ == object:
+        # the repr for a generator is just type+address, expand it out instead.
+        new_args_list.append([_expand_gen_repr([j])[0] for j in i])
+        continue
+    # normal case: uses the built-in to-string
+    new_args_list.append(i)
+  return new_args_list
+
+def _debug_print_gen(*args, **kwargs):
+  """Like _debug_print but will turn any iterable args into a list."""
+  if not _debug:
+    return
+
+  new_args_list = _expand_gen_repr(args)
+  _debug_print(*new_args_list, **kwargs)
+
+def read_headers(input_file: TextIO) -> Tuple[List[str], List[str]]:
+  _debug_print("read_headers for file: ", input_file.name)
+  csv_reader = csv.reader(input_file)
+
+  label_num_columns = len(_LABEL_COLUMNS)
+
+  try:
+    header = next(csv_reader)
+  except StopIteration:
+    header = None
+  _debug_print('header', header)
+
+  if not header:
+    return (None, None)
+
+  labels = header[0:label_num_columns]
+  data = header[label_num_columns:]
+
+  return (labels, data)
+
+def read_labels_and_data(input_file: TextIO) -> Iterable[Tuple[List[str], List[int]]]:
+  _debug_print("print_analysis for file: ", input_file.name)
+  csv_reader = csv.reader(input_file)
+
+  # Skip the header because it doesn't contain any data.
+  # To get the header see read_headers function.
+  try:
+    header = next(csv_reader)
+  except StopIteration:
+    header = None
+
+  label_num_columns = len(_LABEL_COLUMNS)
+
+  for row in csv_reader:
+    if len(row) > 0 and row[0][0] == ';':
+      _debug_print("skip comment line", row)
+      continue
+
+    labels = row[0:label_num_columns]
+    data = [int(i) for i in row[label_num_columns:]]
+
+#    _debug_print("labels:", labels)
+#    _debug_print("data:", data)
+
+    yield (labels, data)
+
+def group_metrics_by_label(it: Iterable[Tuple[List[str], List[int]]]):
+  prev_labels = None
+  data_2d = []
+
+  for label_list, data_list in it:
+    if prev_labels != label_list:
+      if prev_labels:
+#        _debug_print("grouped labels:", prev_labels, "data_2d:", data_2d)
+        yield (prev_labels, data_2d)
+      data_2d = []
+
+    data_2d.append(data_list)
+    prev_labels = label_list
+
+  if prev_labels:
+#    _debug_print("grouped labels:", prev_labels, "data_2d:", data_2d)
+    yield (prev_labels, data_2d)
+
+def data_to_numpy(it: Iterable[Tuple[List[str], List[List[int]]]]) -> Iterable[Tuple[List[str], Any]]:
+  for label_list, data_2d in it:
+    yield (label_list, np.asarray(data_2d, dtype=int))
+
+def iterate_columns(np_data_2d):
+  for col in range(np_data_2d.shape[1]):
+    col_as_array = np_data_2d[:, col]
+    yield col_as_array
+
+def confidence_interval(np_data_2d, percent=0.95):
+  """
+  Given some data [[a,b,c],[d,e,f,]...]
+
+  We assume the same metric is in the column (e.g. [a,d])
+  and that data in the rows (e.g. [b,e]) are separate metric values.
+
+  We then calculate the CI for each metric individually returning it as a list of tuples.
+  """
+  arr = []
+  for col_2d in iterate_columns(np_data_2d):
+    mean = col_2d.mean()
+    sigma = col_2d.std()
+
+    ci = sc.norm.interval(percent, loc=mean, scale=sigma / np.sqrt(len(col_2d)))
+    arr.append(ci)
+
+  # TODO: This seems to be returning NaN when all the samples have the same exact value
+  # (e.g. stddev=0, which can trivially happen when sample count = 1).
+
+  return arr
+
+def print_analysis(it, label_header: List[str], data_header: List[str], output_samples: str):
+  print(label_header)
+
+  with open(output_samples, "w") as output_file:
+
+    csv_writer = csv.writer(output_file)
+    csv_writer.writerow(label_header + ['mean', 'std', 'confidence_interval_a', 'confidence_interval_b'])
+
+    for label_list, np_data_2d in it:
+      print("**********************")
+      print(label_list)
+      print()
+      print("      ", data_header)
+      # aggregate computation column-wise
+      print("Mean: ", np_data_2d.mean(axis=0))
+      print("Std:  ", np_data_2d.std(axis=0))
+      print("CI95%:", confidence_interval(np_data_2d))
+      print("SEM:  ", stats_standard_error_one(np_data_2d, axis=0))
+
+      #ci = confidence_interval(np_data_2d)[_PLOT_DATA_INDEX]
+      sem = stats_standard_error_one(np_data_2d, axis=0)[_PLOT_DATA_INDEX]
+      mean = np_data_2d.mean(axis=0)[_PLOT_DATA_INDEX]
+
+      ci = (mean - sem, mean + sem)
+
+      csv_writer.writerow(label_list + [mean, np_data_2d.std(axis=0)[_PLOT_DATA_INDEX], ci[0], ci[1]])
+
+def from_file_group_by_labels(input_file):
+  (label_header, data_header) = read_headers(input_file)
+  label_data_iter = read_labels_and_data(input_file)
+  grouped_iter = group_metrics_by_label(label_data_iter)
+  grouped_numpy_iter = data_to_numpy(grouped_iter)
+
+  return grouped_numpy_iter, label_header, data_header
+
+def list_without_index(list, index):
+  return list[:index] + list[index+1:]
+
+def group_by_without_baseline_key(grouped_numpy_iter, label_header):
+  """
+  Data is considered comparable if the only difference is the baseline key
+  (i.e. the readahead is different but the package, compilation filter, etc, are the same).
+
+  Returns iterator that's grouped by the non-baseline labels to an iterator of
+  (label_list, data_2d).
+  """
+  baseline_index = label_header.index(_BASELINE[0])
+
+  def get_label_without_baseline(tpl):
+    label_list, _ = tpl
+    return list_without_index(label_list, baseline_index)
+  # [['pkgname', 'compfilter', 'warm'], [data]]
+  # [['pkgname', 'compfilter', 'cold'], [data2]]
+  # [['pkgname2', 'compfilter', 'warm'], [data3]]
+  #
+  #   ->
+  # ( [['pkgname', 'compfilter', 'warm'], [data]]      # ignore baseline label change.
+  #   [['pkgname', 'compfilter', 'cold'], [data2]] ),  # split here because the pkgname changed.
+  # ( [['pkgname2', 'compfilter', 'warm'], [data3]] )
+  for group_info, it in itertools.groupby(grouped_numpy_iter, key = get_label_without_baseline):
+    yield it
+
+  # TODO: replace this messy manual iteration/grouping with pandas
+
+def iterate_comparable_metrics(without_baseline_iter, label_header):
+  baseline_index = label_header.index(_BASELINE[0])
+  baseline_value = _BASELINE[1]
+
+  _debug_print("iterate comparables")
+
+  def is_baseline_fun(tp):
+    ll, dat = tp
+    return ll[baseline_index] == baseline_value
+
+  # iterating here when everything but the baseline key is the same.
+  for it in without_baseline_iter:
+    it1, it2 = itertools.tee(it)
+
+    # find all the baseline data.
+    baseline_filter_it = filter(is_baseline_fun, it1)
+
+    # find non-baseline data.
+    nonbaseline_filter_it = itertools.filterfalse(is_baseline_fun, it2)
+
+    yield itertools.product(baseline_filter_it, nonbaseline_filter_it)
+
+def stats_standard_error_one(a, axis):
+  a_std = a.std(axis=axis, ddof=0)
+  a_len = a.shape[axis]
+
+  return a_std / np.sqrt(a_len)
+
+def stats_standard_error(a, b, axis):
+  a_std = a.std(axis=axis, ddof=0)
+  b_std = b.std(axis=axis, ddof=0)
+
+  a_len = a.shape[axis]
+  b_len = b.shape[axis]
+
+  temp1 = a_std*a_std/a_len
+  temp2 = b_std*b_std/b_len
+
+  return np.sqrt(temp1 + temp2)
+
+def stats_tvalue(a, b, axis, delta = 0):
+  a_mean = a.mean(axis=axis)
+  b_mean = b.mean(axis=axis)
+
+  return (a_mean - b_mean - delta) / stats_standard_error(a, b, axis)
+
+def stats_pvalue(a, b, axis, delta, left:bool = False):
+  """
+  Single-tailed 2-sample t-test.
+
+  Returns p-value for the null hypothesis: mean(a) - mean(b) >= delta.
+  :param a: numpy 2d array
+  :param b: numpy 2d array
+  :param axis: which axis to do the calculations across
+  :param delta: test value of mean differences
+  :param left: if true then use <= delta instead of >= delta
+  :return: p-value
+  """
+  # implement our own pvalue calculation because the built-in t-test (t,p values)
+  # only offer delta=0 , e.g. m1-m1 ? 0
+  # we are however interested in m1-m2 ? delta
+  t_value = stats_tvalue(a, b, axis, delta)
+
+  # 2-sample degrees of freedom is using the array sizes - 2.
+  dof = a.shape[axis] + b.shape[axis] - 2
+
+  if left:
+    # left tailed test. e.g. m1-m2 <= delta
+    return sc.t.cdf(t_value, dof)
+  else:
+    # right tailed test. e.g. m1-m2 >= delta
+    return sc.t.sf(t_value, dof)
+  # a left+right tailed test is a 2-tail t-test and can be done using ttest_ind for delta=0
+
+def print_comparable_analysis(comparable_metrics_iter, label_header, data_header, output_comparable: str, output_comparable_significant: str):
+  baseline_value = _BASELINE[1]
+  baseline_index = label_header.index(_BASELINE[0])
+
+  old_baseline_label_list = None
+  delta = _DELTA
+  filter_value = _IGNORE_PAIR[1]
+  filter_index = label_header.index(_IGNORE_PAIR[0])
+
+  pvalue_threshold = _PVALUE_THRESHOLD
+  ci_threshold = (1 - _PVALUE_THRESHOLD) * 100.0
+
+  with open(output_comparable, "w") as output_file:
+
+    csv_writer = csv.writer(output_file)
+    csv_writer.writerow(label_header + ['mean', 'mean_diff', 'sem', 'pvalue_2tailed', 'pvalue_gt%d' %(_DELTA), 'pvalue_gt%d' %(_DELTA2)])
+
+    print("------------------------------------------------------------------")
+    print("Comparison against the baseline %s = %s" %(_BASELINE, baseline_value))
+    print("--- Right-tailed t-test checks if the baseline >= current %s by at least %d" %(_BASELINE[0], delta))
+    print()
+
+    global_stats = {'better_than_delta': [], 'better_than_delta_p95': []}
+
+    for nested_it in comparable_metrics_iter:
+      print("************************")
+
+      better_than_delta = []
+      better_than_delta_p95 = []
+
+      saw_baseline_once = False
+
+      for ((baseline_label_list, baseline_np_data_2d), (rest_label_list, rest_np_data_2d)) in nested_it:
+        _debug_print("baseline_label_list:", baseline_label_list)
+        _debug_print("baseline_np_data_2d:", baseline_np_data_2d)
+        _debug_print("rest_label_list:", rest_label_list)
+        _debug_print("rest_np_data_2d:", rest_np_data_2d)
+
+        mean_diff = baseline_np_data_2d.mean(axis=0) - rest_np_data_2d.mean(axis=0)
+        # 2-sample 2-tailed t-test with delta=0
+        # e.g. "Is it true that usually the two sample means are different?"
+        t_statistic, t_pvalue = sc.ttest_ind(baseline_np_data_2d, rest_np_data_2d, axis=0)
+
+        # 2-sample 1-tailed t-test with delta=50
+        # e.g. "Is it true that usually the sample means better than 50ms?"
+        t2 = stats_tvalue(baseline_np_data_2d, rest_np_data_2d, axis=0, delta=delta)
+        p2 = stats_pvalue(baseline_np_data_2d, rest_np_data_2d, axis=0, delta=delta)
+
+        t2_b = stats_tvalue(baseline_np_data_2d, rest_np_data_2d, axis=0, delta=_DELTA2)
+        p2_b = stats_pvalue(baseline_np_data_2d, rest_np_data_2d, axis=0, delta=_DELTA2)
+
+        print("%s vs %s" %(rest_label_list, baseline_value))
+        print("                           ", data_header)
+        print("Mean Difference:           ", mean_diff)
+        print("T-test (2-tailed) != 0:      t=%s, p=%s" %(t_statistic, t_pvalue))
+        print("T-test (right-tailed) >= %d: t=%s, p=%s" %(_DELTA, t2, p2))
+        print("T-test (right-tailed) >= %d: t=%s, p=%s" %(_DELTA2, t2_b, p2_b))
+
+        def write_out_values(label_list, *args):
+          csv_writer.writerow(label_list + [i[_PLOT_DATA_INDEX] for i in args])
+
+        sem = stats_standard_error(baseline_np_data_2d, rest_np_data_2d, axis=0)
+        if saw_baseline_once == False:
+          saw_baseline_once = True
+          base_sem = stats_standard_error_one(baseline_np_data_2d, axis=0)
+          write_out_values(baseline_label_list, baseline_np_data_2d.mean(axis=0), [0], base_sem, [None], [None], [None])
+        write_out_values(rest_label_list, rest_np_data_2d.mean(axis=0), mean_diff, sem, t_pvalue, p2, p2_b)
+
+        # now do the global statistics aggregation
+
+        if rest_label_list[filter_index] == filter_value:
+          continue
+
+        if mean_diff > delta:
+          better_than_delta.append((mean_diff, p2, rest_label_list))
+
+          if p2 <= pvalue_threshold:
+            better_than_delta_p95.append((mean_diff, rest_label_list))
+
+      if better_than_delta:
+        global_stats['better_than_delta'].append(better_than_delta)
+      if better_than_delta_p95:
+        global_stats['better_than_delta_p95'].append(better_than_delta_p95)
+
+    print("------------------------")
+    print("Global statistics:")
+    print("//// Rows with %s=%s are ignored here." %_IGNORE_PAIR)
+    print("- # of results with mean diff better than delta(%d)       = %d" %(delta, len(global_stats['better_than_delta'])))
+    print("    > (meandiff, pvalue, labels)")
+    for i in global_stats['better_than_delta']:
+      print("    > %s" %i)
+    print("- # of results with mean diff better than delta(%d) CI%d%% = %d" %(delta, ci_threshold, len(global_stats['better_than_delta_p95'])))
+    print("    > (meandiff, labels)")
+    for i in global_stats['better_than_delta_p95']:
+      print("    > %s" %i)
+
+def main():
+  global _debug
+  global _DELTA
+  global _PVALUE_THRESHOLD
+
+  opts = parse_options()
+  _debug = opts.debug
+  _debug_print("parsed options: ", opts)
+
+  _PVALUE_THRESHOLD = opts.pvalue_threshold or _PVALUE_THRESHOLD
+
+  for file_name in opts.input_files:
+    with open(file_name, 'r') as input_file:
+      (grouped_numpy_iter, label_header, data_header) = from_file_group_by_labels(input_file)
+      print_analysis(grouped_numpy_iter, label_header, data_header, opts.output_samples)
+
+    with open(file_name, 'r') as input_file:
+      (grouped_numpy_iter, label_header, data_header) = from_file_group_by_labels(input_file)
+      without_baseline_iter = group_by_without_baseline_key(grouped_numpy_iter, label_header)
+      #_debug_print_gen(without_baseline_iter)
+
+      comparable_metrics_iter = iterate_comparable_metrics(without_baseline_iter, label_header)
+      print_comparable_analysis(comparable_metrics_iter, label_header, data_header, opts.output_comparable, opts.output_comparable_significant)
+
+  return 0
+
+
+if __name__ == '__main__':
+  sys.exit(main())
diff --git a/startop/scripts/app_startup/app_startup_runner.py b/startop/scripts/app_startup/app_startup_runner.py
new file mode 100755
index 0000000..780bb4e
--- /dev/null
+++ b/startop/scripts/app_startup/app_startup_runner.py
@@ -0,0 +1,322 @@
+#!/usr/bin/env python3
+#
+# 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.
+
+#
+#
+# Measure application start-up time by launching applications under various combinations.
+# See --help for more details.
+#
+#
+# Sample usage:
+# $> ./app_startup_runner.py -p com.google.android.calculator -r warm -r cold -lc 10  -o out.csv
+# $> ./analyze_metrics.py out.csv
+#
+#
+
+import argparse
+import csv
+import itertools
+import os
+import subprocess
+import sys
+import tempfile
+from typing import Any, Callable, Dict, Generic, Iterable, List, NamedTuple, TextIO, Tuple, TypeVar, Optional, Union
+
+# The following command line options participate in the combinatorial generation.
+# All other arguments have a global effect.
+_COMBINATORIAL_OPTIONS=['packages', 'readaheads', 'compiler_filters']
+_TRACING_READAHEADS=['mlock', 'fadvise']
+_FORWARD_OPTIONS={'loop_count': '--count'}
+_RUN_SCRIPT=os.path.join(os.path.dirname(os.path.realpath(__file__)), 'run_app_with_prefetch')
+
+RunCommandArgs = NamedTuple('RunCommandArgs', [('package', str), ('readahead', str), ('compiler_filter', Optional[str])])
+CollectorPackageInfo = NamedTuple('CollectorPackageInfo', [('package', str), ('compiler_filter', str)])
+_COLLECTOR_SCRIPT=os.path.join(os.path.dirname(os.path.realpath(__file__)), 'collector')
+_COLLECTOR_TIMEOUT_MULTIPLIER = 2 # take the regular --timeout and multiply by 2; systrace starts up slowly.
+
+_UNLOCK_SCREEN_SCRIPT=os.path.join(os.path.dirname(os.path.realpath(__file__)), 'unlock_screen')
+
+# This must be the only mutable global variable. All other global variables are constants to avoid magic literals.
+_debug = False  # See -d/--debug flag.
+_DEBUG_FORCE = None  # Ignore -d/--debug if this is not none.
+
+# Type hinting names.
+T = TypeVar('T')
+NamedTupleMeta = Callable[..., T]  # approximation of a (S : NamedTuple<T> where S() == T) metatype.
+
+def parse_options(argv: List[str] = None):
+  """Parse command line arguments and return an argparse Namespace object."""
+  parser = argparse.ArgumentParser(description="Run one or more Android applications under various settings in order to measure startup time.")
+  # argparse considers args starting with - and -- optional in --help, even though required=True.
+  # by using a named argument group --help will clearly say that it's required instead of optional.
+  required_named = parser.add_argument_group('required named arguments')
+  required_named.add_argument('-p', '--package', action='append', dest='packages', help='package of the application', required=True)
+  required_named.add_argument('-r', '--readahead', action='append', dest='readaheads', help='which readahead mode to use', choices=('warm', 'cold', 'mlock', 'fadvise'), required=True)
+
+  # optional arguments
+  # use a group here to get the required arguments to appear 'above' the optional arguments in help.
+  optional_named = parser.add_argument_group('optional named arguments')
+  optional_named.add_argument('-c', '--compiler-filter', action='append', dest='compiler_filters', help='which compiler filter to use. if omitted it does not enforce the app\'s compiler filter', choices=('speed', 'speed-profile', 'quicken'))
+  optional_named.add_argument('-s', '--simulate', dest='simulate', action='store_true', help='Print which commands will run, but don\'t run the apps')
+  optional_named.add_argument('-d', '--debug', dest='debug', action='store_true', help='Add extra debugging output')
+  optional_named.add_argument('-o', '--output', dest='output', action='store', help='Write CSV output to file.')
+  optional_named.add_argument('-t', '--timeout', dest='timeout', action='store', type=int, help='Timeout after this many seconds when executing a single run.')
+  optional_named.add_argument('-lc', '--loop-count', dest='loop_count', default=1, type=int, action='store', help='How many times to loop a single run.')
+  optional_named.add_argument('-in', '--inodes', dest='inodes', type=str, action='store', help='Path to inodes file (system/extras/pagecache/pagecache.py -d inodes)')
+
+  return parser.parse_args(argv)
+
+# TODO: refactor this with a common library file with analyze_metrics.py
+def _debug_print(*args, **kwargs):
+  """Print the args to sys.stderr if the --debug/-d flag was passed in."""
+  if _debug:
+    print(*args, **kwargs, file=sys.stderr)
+
+def _expand_gen_repr(args):
+  """Like repr but any generator-like object has its iterator consumed
+  and then called repr on."""
+  new_args_list = []
+  for i in args:
+    # detect iterable objects that do not have their own override of __str__
+    if hasattr(i, '__iter__'):
+      to_str = getattr(i, '__str__')
+      if to_str.__objclass__ == object:
+        # the repr for a generator is just type+address, expand it out instead.
+        new_args_list.append([_expand_gen_repr([j])[0] for j in i])
+        continue
+    # normal case: uses the built-in to-string
+    new_args_list.append(i)
+  return new_args_list
+
+def _debug_print_gen(*args, **kwargs):
+  """Like _debug_print but will turn any iterable args into a list."""
+  if not _debug:
+    return
+
+  new_args_list = _expand_gen_repr(args)
+  _debug_print(*new_args_list, **kwargs)
+
+def _debug_print_nd(*args, **kwargs):
+  """Like _debug_print but will turn any NamedTuple-type args into a string."""
+  if not _debug:
+    return
+
+  new_args_list = []
+  for i in args:
+    if hasattr(i, '_field_types'):
+      new_args_list.append("%s: %s" %(i.__name__, i._field_types))
+    else:
+      new_args_list.append(i)
+
+  _debug_print(*new_args_list, **kwargs)
+
+def dict_lookup_any_key(dictionary: dict, *keys: List[Any]):
+  for k in keys:
+    if k in dictionary:
+      return dictionary[k]
+  raise KeyError("None of the keys %s were in the dictionary" %(keys))
+
+def generate_run_combinations(named_tuple: NamedTupleMeta[T], opts_dict: Dict[str, List[Optional[str]]])\
+    -> Iterable[T]:
+  """
+  Create all possible combinations given the values in opts_dict[named_tuple._fields].
+
+  :type T: type annotation for the named_tuple type.
+  :param named_tuple: named tuple type, whose fields are used to make combinations for
+  :param opts_dict: dictionary of keys to value list. keys correspond to the named_tuple fields.
+  :return: an iterable over named_tuple instances.
+  """
+  combinations_list = []
+  for k in named_tuple._fields:
+    # the key can be either singular or plural , e.g. 'package' or 'packages'
+    val = dict_lookup_any_key(opts_dict, k, k + "s")
+
+    # treat {'x': None} key value pairs as if it was [None]
+    # otherwise itertools.product throws an exception about not being able to iterate None.
+    combinations_list.append(val or [None])
+
+  _debug_print("opts_dict: ", opts_dict)
+  _debug_print_nd("named_tuple: ", named_tuple)
+  _debug_print("combinations_list: ", combinations_list)
+
+  for combo in itertools.product(*combinations_list):
+    yield named_tuple(*combo)
+
+def key_to_cmdline_flag(key: str) -> str:
+  """Convert key into a command line flag, e.g. 'foo-bars' -> '--foo-bar' """
+  if key.endswith("s"):
+    key = key[:-1]
+  return "--" + key.replace("_", "-")
+
+def as_run_command(tpl: NamedTuple) -> List[Union[str, Any]]:
+  """
+  Convert a named tuple into a command-line compatible arguments list.
+
+  Example: ABC(1, 2, 3) -> ['--a', 1, '--b', 2, '--c', 3]
+  """
+  args = []
+  for key, value in tpl._asdict().items():
+    if value is None:
+      continue
+    args.append(key_to_cmdline_flag(key))
+    args.append(value)
+  return args
+
+def generate_group_run_combinations(run_combinations: Iterable[NamedTuple], dst_nt: NamedTupleMeta[T])\
+    -> Iterable[Tuple[T, Iterable[NamedTuple]]]:
+
+  def group_by_keys(src_nt):
+    src_d = src_nt._asdict()
+    # now remove the keys that aren't legal in dst.
+    for illegal_key in set(src_d.keys()) - set(dst_nt._fields):
+      if illegal_key in src_d:
+        del src_d[illegal_key]
+
+    return dst_nt(**src_d)
+
+  for args_list_it in itertools.groupby(run_combinations, group_by_keys):
+    (group_key_value, args_it) = args_list_it
+    yield (group_key_value, args_it)
+
+def parse_run_script_csv_file(csv_file: TextIO) -> List[int]:
+  """Parse a CSV file full of integers into a flat int list."""
+  csv_reader = csv.reader(csv_file)
+  arr = []
+  for row in csv_reader:
+    for i in row:
+      if i:
+        arr.append(int(i))
+  return arr
+
+def make_script_command_with_temp_output(script: str, args: List[str], **kwargs)\
+    -> Tuple[str, TextIO]:
+  """
+  Create a command to run a script given the args.
+  Appends --count <loop_count> --output <tmp-file-name>.
+  Returns a tuple (cmd, tmp_file)
+  """
+  tmp_output_file = tempfile.NamedTemporaryFile(mode='r')
+  cmd = [script] + args
+  for key, value in kwargs.items():
+    cmd += ['--%s' %(key), "%s" %(value)]
+  if _debug:
+    cmd += ['--verbose']
+  cmd = cmd + ["--output", tmp_output_file.name]
+  return cmd, tmp_output_file
+
+def execute_arbitrary_command(cmd: List[str], simulate: bool, timeout: int) -> Tuple[bool, str]:
+  if simulate:
+    print(" ".join(cmd))
+    return (True, "")
+  else:
+    _debug_print("[EXECUTE]", cmd)
+    proc = subprocess.Popen(cmd,
+                            stderr=subprocess.STDOUT,
+                            stdout=subprocess.PIPE,
+                            universal_newlines=True)
+    try:
+      script_output = proc.communicate(timeout=timeout)[0]
+    except subprocess.TimeoutExpired:
+      print("[TIMEDOUT]")
+      proc.kill()
+      script_output = proc.communicate()[0]
+
+    _debug_print("[STDOUT]", script_output)
+    return_code = proc.wait()
+    passed = (return_code == 0)
+    _debug_print("[$?]", return_code)
+    if not passed:
+      print("[FAILED, code:%s]" %(return_code), script_output, file=sys.stderr)
+
+    return (passed, script_output)
+
+def execute_run_combos(grouped_run_combos: Iterable[Tuple[CollectorPackageInfo, Iterable[RunCommandArgs]]], simulate: bool, inodes_path: str, timeout: int, loop_count: int, need_trace: bool):
+  # nothing will work if the screen isn't unlocked first.
+  execute_arbitrary_command([_UNLOCK_SCREEN_SCRIPT], simulate, timeout)
+
+  for collector_info, run_combos in grouped_run_combos:
+    #collector_args = ["--package", package_name]
+    collector_args = as_run_command(collector_info)
+    # TODO: forward --wait_time for how long systrace runs?
+    # TODO: forward --trace_buffer_size for size of systrace buffer size?
+    collector_cmd, collector_tmp_output_file = make_script_command_with_temp_output(_COLLECTOR_SCRIPT, collector_args, inodes=inodes_path)
+
+    with collector_tmp_output_file:
+      collector_passed = True
+      if need_trace:
+        collector_timeout = timeout and _COLLECTOR_TIMEOUT_MULTIPLIER * timeout
+        (collector_passed, collector_script_output) = execute_arbitrary_command(collector_cmd, simulate, collector_timeout)
+        # TODO: consider to print a ; collector wrote file to <...> into the CSV file so we know it was ran.
+
+      for combos in run_combos:
+        args = as_run_command(combos)
+
+        cmd, tmp_output_file = make_script_command_with_temp_output(_RUN_SCRIPT, args, count=loop_count, input=collector_tmp_output_file.name)
+        with tmp_output_file:
+          (passed, script_output) = execute_arbitrary_command(cmd, simulate, timeout)
+          parsed_output = simulate and [1,2,3] or parse_run_script_csv_file(tmp_output_file)
+          yield (passed, script_output, parsed_output)
+
+def gather_results(commands: Iterable[Tuple[bool, str, List[int]]], key_list: List[str], value_list: List[Tuple[str, ...]]):
+  _debug_print("gather_results: key_list = ", key_list)
+  yield key_list + ["time(ms)"]
+
+  stringify_none = lambda s: s is None and "<none>" or s
+
+  for ((passed, script_output, run_result_list), values) in itertools.zip_longest(commands, value_list):
+    if not passed:
+      continue
+    for result in run_result_list:
+      yield [stringify_none(i) for i in values] + [result]
+
+    yield ["; avg(%s), min(%s), max(%s), count(%s)" %(sum(run_result_list, 0.0) / len(run_result_list), min(run_result_list), max(run_result_list), len(run_result_list)) ]
+
+def eval_and_save_to_csv(output, annotated_result_values):
+  csv_writer = csv.writer(output)
+  for row in annotated_result_values:
+    csv_writer.writerow(row)
+    output.flush() # see the output live.
+
+def main():
+  global _debug
+
+  opts = parse_options()
+  _debug = opts.debug
+  if _DEBUG_FORCE is not None:
+    _debug = _DEBUG_FORCE
+  _debug_print("parsed options: ", opts)
+  need_trace = not not set(opts.readaheads).intersection(set(_TRACING_READAHEADS))
+  if need_trace and not opts.inodes:
+    print("Error: Missing -in/--inodes, required when using a readahead of %s" %(_TRACING_READAHEADS), file=sys.stderr)
+    return 1
+
+  output_file = opts.output and open(opts.output, 'w') or sys.stdout
+
+  combos = lambda: generate_run_combinations(RunCommandArgs, vars(opts))
+  _debug_print_gen("run combinations: ", combos())
+
+  grouped_combos = lambda: generate_group_run_combinations(combos(), CollectorPackageInfo)
+  _debug_print_gen("grouped run combinations: ", grouped_combos())
+
+  exec = execute_run_combos(grouped_combos(), opts.simulate, opts.inodes, opts.timeout, opts.loop_count, need_trace)
+  results = gather_results(exec, _COMBINATORIAL_OPTIONS, combos())
+  eval_and_save_to_csv(output_file, results)
+
+  return 0
+
+
+if __name__ == '__main__':
+  sys.exit(main())
diff --git a/startop/scripts/app_startup/app_startup_runner_test.py b/startop/scripts/app_startup/app_startup_runner_test.py
new file mode 100755
index 0000000..f96f802a
--- /dev/null
+++ b/startop/scripts/app_startup/app_startup_runner_test.py
@@ -0,0 +1,210 @@
+#!/usr/bin/env python3
+#
+# 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.
+#
+
+"""
+Unit tests for the app_startup_runner.py script.
+
+Install:
+  $> sudo apt-get install python3-pytest   ##  OR
+  $> pip install -U pytest
+See also https://docs.pytest.org/en/latest/getting-started.html
+
+Usage:
+  $> ./app_startup_runner_test.py
+  $> pytest app_startup_runner_test.py
+  $> python -m pytest app_startup_runner_test.py
+
+See also https://docs.pytest.org/en/latest/usage.html
+"""
+
+# global imports
+from contextlib import contextmanager
+import io
+import shlex
+import sys
+import typing
+
+# pip imports
+import pytest
+
+# local imports
+import app_startup_runner as asr
+
+#
+# Argument Parsing Helpers
+#
+
+@contextmanager
+def ignore_stdout_stderr():
+  """Ignore stdout/stderr output for duration of this context."""
+  old_stdout = sys.stdout
+  old_stderr = sys.stderr
+  sys.stdout = io.StringIO()
+  sys.stderr = io.StringIO()
+  try:
+    yield
+  finally:
+    sys.stdout = old_stdout
+    sys.stderr = old_stderr
+
+@contextmanager
+def argparse_bad_argument(msg):
+  """
+  Assert that a SystemExit is raised when executing this context.
+  If the assertion fails, print the message 'msg'.
+  """
+  with pytest.raises(SystemExit, message=msg):
+    with ignore_stdout_stderr():
+      yield
+
+def assert_bad_argument(args, msg):
+  """
+  Assert that the command line arguments in 'args' are malformed.
+  Prints 'msg' if the assertion fails.
+  """
+  with argparse_bad_argument(msg):
+    parse_args(args)
+
+def parse_args(args):
+  """
+  :param args: command-line like arguments as a single string
+  :return:  dictionary of parsed key/values
+  """
+  # "-a b -c d"    => ['-a', 'b', '-c', 'd']
+  return vars(asr.parse_options(shlex.split(args)))
+
+def default_dict_for_parsed_args(**kwargs):
+  """
+  # Combine it with all of the "optional" parameters' default values.
+  """
+  d = {'compiler_filters': None, 'simulate': False, 'debug': False, 'output': None, 'timeout': None, 'loop_count': 1, 'inodes': None}
+  d.update(kwargs)
+  return d
+
+def default_mock_dict_for_parsed_args(include_optional=True, **kwargs):
+  """
+  Combine default dict with all optional parameters with some mock required parameters.
+  """
+  d = {'packages': ['com.fake.package'], 'readaheads': ['warm']}
+  if include_optional:
+    d.update(default_dict_for_parsed_args())
+  d.update(kwargs)
+  return d
+
+def parse_optional_args(str):
+  """
+  Parse an argument string which already includes all the required arguments
+  in default_mock_dict_for_parsed_args.
+  """
+  req = "--package com.fake.package --readahead warm"
+  return parse_args("%s %s" %(req, str))
+
+def test_argparse():
+  # missing arguments
+  assert_bad_argument("", "-p and -r are required")
+  assert_bad_argument("-r warm", "-p is required")
+  assert_bad_argument("--readahead warm", "-p is required")
+  assert_bad_argument("-p com.fake.package", "-r is required")
+  assert_bad_argument("--package com.fake.package", "-r is required")
+
+  # required arguments are parsed correctly
+  ad = default_dict_for_parsed_args  # assert dict
+
+  assert parse_args("--package xyz --readahead warm") == ad(packages=['xyz'], readaheads=['warm'])
+  assert parse_args("-p xyz -r warm") == ad(packages=['xyz'], readaheads=['warm'])
+
+  assert parse_args("-p xyz -r warm -s") == ad(packages=['xyz'], readaheads=['warm'], simulate=True)
+  assert parse_args("-p xyz -r warm --simulate") == ad(packages=['xyz'], readaheads=['warm'], simulate=True)
+
+  # optional arguments are parsed correctly.
+  mad = default_mock_dict_for_parsed_args  # mock assert dict
+  assert parse_optional_args("--output filename.csv") == mad(output='filename.csv')
+  assert parse_optional_args("-o filename.csv") == mad(output='filename.csv')
+
+  assert parse_optional_args("--timeout 123") == mad(timeout=123)
+  assert parse_optional_args("-t 456") == mad(timeout=456)
+
+  assert parse_optional_args("--loop-count 123") == mad(loop_count=123)
+  assert parse_optional_args("-lc 456") == mad(loop_count=456)
+
+  assert parse_optional_args("--inodes bar") == mad(inodes="bar")
+  assert parse_optional_args("-in baz") == mad(inodes="baz")
+
+
+def generate_run_combinations(*args):
+  # expand out the generator values so that assert x == y works properly.
+  return [i for i in asr.generate_run_combinations(*args)]
+
+def test_generate_run_combinations():
+  blank_nd = typing.NamedTuple('Blank')
+  assert generate_run_combinations(blank_nd, {}) == [()], "empty"
+  assert generate_run_combinations(blank_nd, {'a' : ['a1', 'a2']}) == [()], "empty filter"
+  a_nd = typing.NamedTuple('A', [('a', str)])
+  assert generate_run_combinations(a_nd, {'a': None}) == [(None,)], "None"
+  assert generate_run_combinations(a_nd, {'a': ['a1', 'a2']}) == [('a1',), ('a2',)], "one item"
+  assert generate_run_combinations(a_nd,
+                                   {'a' : ['a1', 'a2'], 'b': ['b1', 'b2']}) == [('a1',), ('a2',)],\
+      "one item filter"
+  ab_nd = typing.NamedTuple('AB', [('a', str), ('b', str)])
+  assert generate_run_combinations(ab_nd,
+                                   {'a': ['a1', 'a2'],
+                                    'b': ['b1', 'b2']}) == [ab_nd('a1', 'b1'),
+                                                            ab_nd('a1', 'b2'),
+                                                            ab_nd('a2', 'b1'),
+                                                            ab_nd('a2', 'b2')],\
+      "two items"
+
+  assert generate_run_combinations(ab_nd,
+                                   {'as': ['a1', 'a2'],
+                                    'bs': ['b1', 'b2']}) == [ab_nd('a1', 'b1'),
+                                                             ab_nd('a1', 'b2'),
+                                                             ab_nd('a2', 'b1'),
+                                                             ab_nd('a2', 'b2')],\
+      "two items plural"
+
+def test_key_to_cmdline_flag():
+  assert asr.key_to_cmdline_flag("abc") == "--abc"
+  assert asr.key_to_cmdline_flag("foos") == "--foo"
+  assert asr.key_to_cmdline_flag("ba_r") == "--ba-r"
+  assert asr.key_to_cmdline_flag("ba_zs") == "--ba-z"
+
+
+def test_make_script_command_with_temp_output():
+  cmd_str, tmp_file = asr.make_script_command_with_temp_output("fake_script", args=[], count=1)
+  with tmp_file:
+    assert cmd_str == ["fake_script", "--count", "1", "--output", tmp_file.name]
+
+  cmd_str, tmp_file = asr.make_script_command_with_temp_output("fake_script", args=['a', 'b'], count=2)
+  with tmp_file:
+    assert cmd_str == ["fake_script", "a", "b", "--count", "2", "--output", tmp_file.name]
+
+def test_parse_run_script_csv_file():
+  # empty file -> empty list
+  f = io.StringIO("")
+  assert asr.parse_run_script_csv_file(f) == []
+
+  # common case
+  f = io.StringIO("1,2,3")
+  assert asr.parse_run_script_csv_file(f) == [1,2,3]
+
+  # ignore trailing comma
+  f = io.StringIO("1,2,3,4,5,")
+  assert asr.parse_run_script_csv_file(f) == [1,2,3,4,5]
+
+
+if __name__ == '__main__':
+  pytest.main()
diff --git a/startop/scripts/app_startup/force_compiler_filter b/startop/scripts/app_startup/force_compiler_filter
new file mode 100755
index 0000000..78e915b
--- /dev/null
+++ b/startop/scripts/app_startup/force_compiler_filter
@@ -0,0 +1,173 @@
+#!/bin/bash
+#
+# 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.
+
+#
+# Forces an application APK to be compiled (by ART's dex2oat)
+# with a specific compiler filter.
+#
+# Example usage:
+#    $> ./force_compiler_filter -p com.google.android.apps.maps -c speed-profile
+#
+# (The application may be started/stopped as a side effect)
+#
+
+DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+source "$DIR/lib/common"
+
+usage() {
+    cat <<EOF
+Usage: $(basename $0) [OPTION]...
+
+  Required:
+    -p, --package               package of the app to recompile
+    -c, --compiler-filter       override the compiler filter if set (default none)
+                                valid options are listed by: adb shell cmd package, under compile -m
+
+  Optional:
+    -a, --activity              activity of the app to recompile
+    -h, --help                  usage information (this)
+    -v, --verbose               enable extra verbose printing
+    -w, --wait_time             how long to wait for app startup (default 10) in seconds
+EOF
+}
+
+wait_time="10" # seconds
+
+parse_arguments() {
+  while [[ $# -gt 0 ]]; do
+    case "$1" in
+      -a|--activity)
+        activity="$2"
+        shift
+        ;;
+      -h|--help)
+        usage
+        exit 0
+        ;;
+      -p|--package)
+        package="$2"
+        shift
+        ;;
+      -w|--wait_time)
+        wait_time="$2"
+        shift
+        ;;
+      -c|--compiler-filter)
+        compiler_filter="$2"
+        shift
+        ;;
+      -v|--verbose)
+        verbose="y"
+        ;;
+    esac
+    shift
+  done
+
+  if [[ -z "$compiler_filter" ]]; then
+    echo "Missing required --compiler-filter" >&2
+    echo ""
+    usage
+    exit 1
+  fi
+  if [[ -z "$package" ]]; then
+    echo "Missing required --package" >&2
+    echo ""
+    usage
+    exit 1
+  fi
+
+  if [[ "$activity" == "" ]]; then
+    activity="$(get_activity_name "$package")"
+    if [[ "$activity" == "" ]]; then
+      echo "Activity name could not be found, invalid package name?" 1>&2
+      exit 1
+    else
+      verbose_print "Activity name inferred: " "$activity"
+    fi
+  fi
+}
+
+get_activity_name() {
+  local package="$1"
+  local action_key="android.intent.action.MAIN:"
+
+  local activity_line="$(adb shell cmd package query-activities --brief -a android.intent.action.MAIN -c android.intent.category.LAUNCHER | grep "$package")"
+  verbose_print $activity_line
+  IFS="/" read -a array <<< "$activity_line"
+  local activity_name="${array[1]}"
+  echo "$activity_name"
+  #adb shell am start "$package/$activity_name"
+}
+
+remote_pidof() {
+  local procname="$1"
+  adb shell ps | grep "$procname" | awk '{print $2;}'
+}
+
+remote_pkill() {
+  local procname="$1"
+  shift
+
+  local the_pids=$(remote_pidof "$procname")
+  local pid
+
+  for pid in $the_pids; do
+    verbose_print adb shell kill "$@" "$pid"
+    adb shell kill "$@" "$pid"
+  done
+}
+
+force_package_compilation() {
+  local arg_compiler_filter="$1"
+  local arg_package="$2"
+
+  if [[ $arg_compiler_filter == speed-profile ]]; then
+    # Force the running app to dump its profiles to disk.
+    remote_pkill "$arg_package" -SIGUSR1
+    sleep 1 # give some time for above to complete.
+  fi
+
+  adb shell cmd package compile -m "$arg_compiler_filter" -f "$arg_package"
+}
+
+main() {
+  parse_arguments "$@"
+
+  if [[ $compiler_filter == speed-profile ]]; then
+    # screen needs to be unlocked in order to run an app
+    "$DIR"/unlock_screen
+
+    am_output="$(adb shell am start -S -W "$package"/"$activity")"
+    if [[ $? -ne 0 ]]; then
+      echo "am start failed" >&2
+      exit 1
+    fi
+
+    verbose_print "$am_output"
+    # give some time for app startup to complete.
+    # this is supposed to be an upper bound for measuring startup time.
+    sleep "$wait_time"
+  fi
+
+  force_package_compilation "$compiler_filter" "$package"
+
+  # kill the application to ensure next time it's started,
+  # it picks up the correct compilation filter.
+  adb shell am force-stop "$package"
+  remote_pkill "$package"
+}
+
+main "$@"
diff --git a/startop/scripts/app_startup/launch_application b/startop/scripts/app_startup/launch_application
new file mode 100755
index 0000000..bc4ec51
--- /dev/null
+++ b/startop/scripts/app_startup/launch_application
@@ -0,0 +1,41 @@
+#!/bin/bash
+#
+# 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.
+
+DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+source "$DIR/lib/common"
+
+launch_application() {
+  local package="$1"
+  local activity="$2"
+  local am_output="$(adb shell am start -S -W "$package"/"$activity")"
+  verbose_print adb shell am start -S -W "$package"/"$activity"
+  if [[ $? -ne 0 ]]; then
+    echo "am start failed" >&2
+
+    return 1
+  fi
+
+  # for everything else use the am start "TotalTime" output.
+  verbose_print "$am_output"
+  local total_time="$(echo "$am_output" | grep 'TotalTime:' | sed 's/TotalTime: //g')"
+  verbose_print "total time: $total_time"
+
+  # TODO: Extract alternative metrics such as the #reportFullyDrawn.
+
+  echo "$total_time"
+}
+
+launch_application "$@"
diff --git a/startop/scripts/app_startup/lib/common b/startop/scripts/app_startup/lib/common
new file mode 100755
index 0000000..4d5a53e
--- /dev/null
+++ b/startop/scripts/app_startup/lib/common
@@ -0,0 +1,14 @@
+#!/bin/bash
+
+if [[ -z $ANDROID_BUILD_TOP ]]; then
+  echo "Please run source build/envsetup.sh first" >&2
+  exit 1
+fi
+
+source $ANDROID_BUILD_TOP/build/envsetup.sh
+
+verbose_print() {
+  if [[ "$verbose" == "y" ]]; then
+    echo "$@" >&2
+  fi
+}
diff --git a/startop/scripts/app_startup/query_compiler_filter.py b/startop/scripts/app_startup/query_compiler_filter.py
new file mode 100755
index 0000000..dc97c66
--- /dev/null
+++ b/startop/scripts/app_startup/query_compiler_filter.py
@@ -0,0 +1,226 @@
+#!/usr/bin/env python3
+#
+# 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.
+
+#
+#
+# Query the current compiler filter for an application by its package name.
+# (By parsing the results of the 'adb shell dumpsys package $package' command).
+# The output is a string "$compilation_filter $compilation_reason $isa".
+#
+# See --help for more details.
+#
+# -----------------------------------
+#
+# Sample usage:
+#
+# $> ./query_compiler_filter.py --package com.google.android.calculator
+# speed-profile unknown arm64
+#
+
+import argparse
+import sys
+import re
+
+# TODO: refactor this with a common library file with analyze_metrics.py
+import app_startup_runner
+from app_startup_runner import _debug_print
+from app_startup_runner import execute_arbitrary_command
+
+from typing import List, NamedTuple, Iterable
+
+_DEBUG_FORCE = None  # Ignore -d/--debug if this is not none.
+
+def parse_options(argv: List[str] = None):
+  """Parse command line arguments and return an argparse Namespace object."""
+  parser = argparse.ArgumentParser(description="Query the compiler filter for a package.")
+  # argparse considers args starting with - and -- optional in --help, even though required=True.
+  # by using a named argument group --help will clearly say that it's required instead of optional.
+  required_named = parser.add_argument_group('required named arguments')
+  required_named.add_argument('-p', '--package', action='store', dest='package', help='package of the application', required=True)
+
+  # optional arguments
+  # use a group here to get the required arguments to appear 'above' the optional arguments in help.
+  optional_named = parser.add_argument_group('optional named arguments')
+  optional_named.add_argument('-i', '--isa', '--instruction-set', action='store', dest='instruction_set', help='which instruction set to select. defaults to the first one available if not specified.', choices=('arm64', 'arm', 'x86_64', 'x86'))
+  optional_named.add_argument('-s', '--simulate', dest='simulate', action='store_true', help='Print which commands will run, but don\'t run the apps')
+  optional_named.add_argument('-d', '--debug', dest='debug', action='store_true', help='Add extra debugging output')
+
+  return parser.parse_args(argv)
+
+def remote_dumpsys_package(package: str, simulate: bool) -> str:
+  # --simulate is used for interactive debugging/development, but also for the unit test.
+  if simulate:
+    return """
+Dexopt state:
+  [%s]
+    path: /data/app/%s-D7s8PLidqqEq7Jc7UH_a5A==/base.apk
+      arm64: [status=speed-profile] [reason=unknown]
+    path: /data/app/%s-D7s8PLidqqEq7Jc7UH_a5A==/base.apk
+      arm: [status=speed] [reason=first-boot]
+    path: /data/app/%s-D7s8PLidqqEq7Jc7UH_a5A==/base.apk
+      x86: [status=quicken] [reason=install]
+""" %(package, package, package, package)
+
+  code, res = execute_arbitrary_command(['adb', 'shell', 'dumpsys', 'package', package], simulate=False, timeout=5)
+  if code:
+    return res
+  else:
+    raise AssertionError("Failed to dumpsys package, errors = %s", res)
+
+ParseTree = NamedTuple('ParseTree', [('label', str), ('children', List['ParseTree'])])
+DexoptState = ParseTree # With the Dexopt state: label
+ParseResult = NamedTuple('ParseResult', [('remainder', List[str]), ('tree', ParseTree)])
+
+def find_parse_subtree(parse_tree: ParseTree, match_regex: str) -> ParseTree:
+  if re.match(match_regex, parse_tree.label):
+    return parse_tree
+
+  for node in parse_tree.children:
+    res = find_parse_subtree(node, match_regex)
+    if res:
+      return res
+
+  return None
+
+def find_parse_children(parse_tree: ParseTree, match_regex: str) -> Iterable[ParseTree]:
+  for node in parse_tree.children:
+    if re.match(match_regex, node.label):
+      yield node
+
+def parse_tab_subtree(label: str, str_lines: List[str], separator=' ', indent=-1) -> ParseResult:
+  children = []
+
+  get_indent_level = lambda line: len(line) - len(line.lstrip())
+
+  line_num = 0
+
+  keep_going = True
+  while keep_going:
+    keep_going = False
+
+    for line_num in range(len(str_lines)):
+      line = str_lines[line_num]
+      current_indent = get_indent_level(line)
+
+      _debug_print("INDENT=%d, LINE=%s" %(current_indent, line))
+
+      current_label = line.lstrip()
+
+      # skip empty lines
+      if line.lstrip() == "":
+        continue
+
+      if current_indent > indent:
+        parse_result = parse_tab_subtree(current_label, str_lines[line_num+1::], separator, current_indent)
+        str_lines = parse_result.remainder
+        children.append(parse_result.tree)
+        keep_going = True
+      else:
+        # current_indent <= indent
+        keep_going = False
+
+      break
+
+  new_remainder = str_lines[line_num::]
+  _debug_print("NEW REMAINDER: ", new_remainder)
+
+  parse_tree = ParseTree(label, children)
+  return ParseResult(new_remainder, parse_tree)
+
+def parse_tab_tree(str_tree: str, separator=' ', indentation_level=-1) -> ParseTree:
+
+  label = None
+  lst = []
+
+  line_num = 0
+  line_lst = str_tree.split("\n")
+
+  return parse_tab_subtree("", line_lst, separator, indentation_level).tree
+
+def parse_dexopt_state(dumpsys_tree: ParseTree) -> DexoptState:
+  res = find_parse_subtree(dumpsys_tree, "Dexopt(\s+)state[:]?")
+  if not res:
+    raise AssertionError("Could not find the Dexopt state")
+  return res
+
+def find_first_compiler_filter(dexopt_state: DexoptState, package: str, instruction_set: str) -> str:
+  lst = find_all_compiler_filters(dexopt_state, package)
+
+  _debug_print("all compiler filters: ", lst)
+
+  for compiler_filter_info in lst:
+    if not instruction_set:
+      return compiler_filter_info
+
+    if compiler_filter_info.isa == instruction_set:
+      return compiler_filter_info
+
+  return None
+
+CompilerFilterInfo = NamedTuple('CompilerFilterInfo', [('isa', str), ('status', str), ('reason', str)])
+
+def find_all_compiler_filters(dexopt_state: DexoptState, package: str) -> List[CompilerFilterInfo]:
+
+  lst = []
+  package_tree = find_parse_subtree(dexopt_state, re.escape("[%s]" %package))
+
+  if not package_tree:
+    raise AssertionError("Could not find any package subtree for package %s" %(package))
+
+  _debug_print("package tree: ", package_tree)
+
+  for path_tree in find_parse_children(package_tree, "path: "):
+    _debug_print("path tree: ", path_tree)
+
+    matchre = re.compile("([^:]+):\s+\[status=([^\]]+)\]\s+\[reason=([^\]]+)\]")
+
+    for isa_node in find_parse_children(path_tree, matchre):
+
+      matches = re.match(matchre, isa_node.label).groups()
+
+      info = CompilerFilterInfo(*matches)
+      lst.append(info)
+
+  return lst
+
+def main() -> int:
+  opts = parse_options()
+  app_startup_runner._debug = opts.debug
+  if _DEBUG_FORCE is not None:
+    app_startup_runner._debug = _DEBUG_FORCE
+  _debug_print("parsed options: ", opts)
+
+  # Note: This can often 'fail' if the package isn't actually installed.
+  package_dumpsys = remote_dumpsys_package(opts.package, opts.simulate)
+  _debug_print("package dumpsys: ", package_dumpsys)
+  dumpsys_parse_tree = parse_tab_tree(package_dumpsys, package_dumpsys)
+  _debug_print("parse tree: ", dumpsys_parse_tree)
+  dexopt_state = parse_dexopt_state(dumpsys_parse_tree)
+
+  filter = find_first_compiler_filter(dexopt_state, opts.package, opts.instruction_set)
+
+  if filter:
+    print(filter.status, end=' ')
+    print(filter.reason, end=' ')
+    print(filter.isa)
+  else:
+    print("ERROR: Could not find any compiler-filter for package %s, isa %s" %(opts.package, opts.instruction_set), file=sys.stderr)
+    return 1
+
+  return 0
+
+if __name__ == '__main__':
+  sys.exit(main())
diff --git a/startop/scripts/app_startup/query_compiler_filter_test.py b/startop/scripts/app_startup/query_compiler_filter_test.py
new file mode 100755
index 0000000..a751a43
--- /dev/null
+++ b/startop/scripts/app_startup/query_compiler_filter_test.py
@@ -0,0 +1,116 @@
+#!/usr/bin/env python3
+#
+# 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.
+#
+
+"""
+Unit tests for the query_compiler_filter.py script.
+
+Install:
+  $> sudo apt-get install python3-pytest   ##  OR
+  $> pip install -U pytest
+See also https://docs.pytest.org/en/latest/getting-started.html
+
+Usage:
+  $> ./query_compiler_filter.py
+  $> pytest query_compiler_filter.py
+  $> python -m pytest query_compiler_filter.py
+
+See also https://docs.pytest.org/en/latest/usage.html
+"""
+
+# global imports
+from contextlib import contextmanager
+import io
+import shlex
+import sys
+import typing
+
+# pip imports
+import pytest
+
+# local imports
+import query_compiler_filter as qcf
+
+@contextmanager
+def redirect_stdout_stderr():
+  """Redirect stdout/stderr to a new StringIO for duration of context."""
+  old_stdout = sys.stdout
+  old_stderr = sys.stderr
+  new_stdout = io.StringIO()
+  sys.stdout = new_stdout
+  new_stderr = io.StringIO()
+  sys.stderr = new_stderr
+  try:
+    yield (new_stdout, new_stderr)
+  finally:
+    sys.stdout = old_stdout
+    sys.stderr = old_stderr
+    # Seek back to the beginning so we can read whatever was written into it.
+    new_stdout.seek(0)
+    new_stderr.seek(0)
+
+@contextmanager
+def replace_argv(argv):
+  """ Temporarily replace argv for duration of this context."""
+  old_argv = sys.argv
+  sys.argv = [sys.argv[0]] + argv
+  try:
+    yield
+  finally:
+    sys.argv = old_argv
+
+def exec_main(argv):
+  """Run the query_compiler_filter main function with the provided arguments.
+
+  Returns the stdout result when successful, assertion failure otherwise.
+  """
+  try:
+    with redirect_stdout_stderr() as (the_stdout, the_stderr):
+      with replace_argv(argv):
+        code = qcf.main()
+    assert 0 == code, the_stderr.readlines()
+
+    all_lines = the_stdout.readlines()
+    return "".join(all_lines)
+  finally:
+    the_stdout.close()
+    the_stderr.close()
+
+def test_query_compiler_filter():
+  # no --instruction-set specified: provide whatever was the 'first' filter.
+  assert exec_main(['--simulate',
+                    '--package', 'com.google.android.apps.maps']) == \
+      "speed-profile unknown arm64\n"
+
+  # specifying an instruction set finds the exact compiler filter match.
+  assert exec_main(['--simulate',
+                    '--package', 'com.google.android.apps.maps',
+                    '--instruction-set', 'arm64']) == \
+      "speed-profile unknown arm64\n"
+
+  assert exec_main(['--simulate',
+                    '--package', 'com.google.android.apps.maps',
+                    '--instruction-set', 'arm']) == \
+      "speed first-boot arm\n"
+
+  assert exec_main(['--simulate',
+                    '--debug',
+                    '--package', 'com.google.android.apps.maps',
+                    '--instruction-set', 'x86']) == \
+      "quicken install x86\n"
+
+if __name__ == '__main__':
+  pytest.main()
diff --git a/startop/scripts/app_startup/run_app_with_prefetch b/startop/scripts/app_startup/run_app_with_prefetch
new file mode 100755
index 0000000..ce63ff9
--- /dev/null
+++ b/startop/scripts/app_startup/run_app_with_prefetch
@@ -0,0 +1,381 @@
+#!/bin/bash
+#
+# 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.
+
+usage() {
+    cat <<EOF
+Usage: run_app_with_prefetch --package <name> [OPTIONS]...
+
+    -p, --package <name>        package of the app to test
+    -a, --activity <name>       activity to use
+    -h, --help                  usage information (this)
+    -v, --verbose               enable extra verbose printing
+    -i, --input <file>          trace file protobuf (default 'TraceFile.pb')
+    -r, --readahead <mode>      cold, warm, fadvise, mlock (default 'warm')
+    -w, --when <when>           aot or jit (default 'aot')
+    -c, --count <count>         how many times to run (default 1)
+    -s, --sleep <sec>           how long to sleep after readahead
+    -t, --timeout <sec>         how many seconds to timeout in between each app run (default 10)
+    -o, --output <file.csv>     what file to write the performance results into as csv (default stdout)
+EOF
+}
+
+DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+source "$DIR/lib/common"
+
+needs_trace_file="n"
+input_file=""
+package=""
+mode='warm'
+count=2
+sleep_time=2
+timeout=10
+output="" # stdout by default
+when="aot"
+parse_arguments() {
+  while [[ $# -gt 0 ]]; do
+    case "$1" in
+      -h|--help)
+        usage
+        exit 0
+        ;;
+      -p|--package)
+        package="$2"
+        shift
+        ;;
+      -a|--activity)
+        activity="$2"
+        shift
+        ;;
+      -i|--input)
+        input_file="$2"
+        shift
+        ;;
+      -v|--verbose)
+        export verbose="y"
+        ;;
+      -r|--readahead)
+        mode="$2"
+        shift
+        ;;
+      -c|--count)
+        count="$2"
+        ((count+=1))
+        shift
+        ;;
+      -s|--sleep)
+        sleep_time="$2"
+        shift
+        ;;
+      -t|--timeout)
+        timeout="$2"
+        shift
+        ;;
+      -o|--output)
+        output="$2"
+        shift
+        ;;
+      -w|--when)
+        when="$2"
+        shift
+        ;;
+      --compiler-filter)
+        compiler_filter="$2"
+        shift
+        ;;
+      *)
+        echo "Invalid argument: $1" >&2
+        exit 1
+    esac
+    shift
+  done
+}
+
+echo_to_output_file() {
+  if [[ "x$output" != x ]]; then
+    echo "$@" >> $output
+  fi
+  # Always echo to stdout as well.
+  echo "$@"
+}
+
+get_activity_name() {
+  local package="$1"
+  local action_key="android.intent.action.MAIN:"
+
+  local activity_line="$(adb shell cmd package query-activities --brief -a android.intent.action.MAIN -c android.intent.category.LAUNCHER | grep "$package")"
+  #echo $activity_line
+  IFS="/" read -a array <<< "$activity_line"
+  local activity_name="${array[1]}"
+  echo "$activity_name"
+  #adb shell am start "$package/$activity_name"
+}
+
+find_package_path() {
+  local pkg="$1"
+
+  res="$(adb shell find "/data/app/$pkg"-'*' -maxdepth 0 2> /dev/null)"
+  if [[ -z $res ]]; then
+    res="$(adb shell find "/system/app/$pkg"-'*' -maxdepth 0 2> /dev/null)"
+  fi
+  echo "$res"
+}
+
+remote_pkill() {
+  local what="$1"
+  adb shell "for i in $(pid $what); do kill \$i; done"
+}
+
+# Main entry point
+if [[ $# -eq 0 ]]; then
+  usage
+  exit 1
+else
+  parse_arguments "$@"
+
+  # if we do not have have package exit early with an error
+  [[ "$package" == "" ]] && echo "--package not specified" 1>&2 && exit 1
+
+  if [[ $mode != "cold" && $mode != "warm" ]]; then
+    needs_trace_file="y"
+    if [[ -z "$input_file" ]] || ! [[ -f $input_file ]]; then
+      echo "--input not specified" 1>&2
+      exit 1
+    fi
+  fi
+
+  if [[ "$activity" == "" ]]; then
+    activity="$(get_activity_name "$package")"
+    if [[ "$activity" == "" ]]; then
+      echo "Activity name could not be found, invalid package name?" 1>&2
+      exit 1
+    else
+      verbose_print "Activity name inferred: " "$activity"
+    fi
+  fi
+fi
+
+adb root > /dev/null
+
+if [[ ($when == jit) || ($when == aot) ]] && [[ "$(adb shell getenforce)" != "Permissive" ]]; then
+  echo "Disable selinux permissions and restart framework."
+  adb shell setenforce 0
+  adb shell stop
+  adb shell start
+  adb wait-for-device
+fi
+
+# TODO: set performance governor etc, preferrably only once
+# before every single app run.
+
+# Kill everything before running.
+remote_pkill "$package"
+sleep 1
+
+timings_array=()
+
+package_path="$(find_package_path "$package")"
+if [[ $? -ne 0 ]]; then
+  echo "Failed to detect package path for '$package'" >&2
+  exit 1
+fi
+verbose_print "Package was in path '$package_path'"
+
+keep_application_trace_file=n
+application_trace_file_path="$package_path/TraceFile.pb"
+trace_file_directory="$package_path"
+if [[ $needs_trace_file == y ]]; then
+  # system server always passes down the package path in a hardcoded spot.
+  if [[ $when == "jit" ]]; then
+    verbose_print adb push "$input_file" "$application_trace_file_path"
+    adb push "$input_file" "$application_trace_file_path"
+    keep_application_trace_file="y"
+  else
+    # otherwise use a temporary directory to get normal non-jit behavior.
+    trace_file_directory="/data/local/tmp/prefetch/$package"
+    adb shell mkdir -p "$trace_file_directory"
+    verbose_print  adb push "$input_file" "$trace_file_directory/TraceFile.pb"
+    adb push "$input_file" "$trace_file_directory/TraceFile.pb"
+  fi
+fi
+
+# Everything other than JIT: remove the trace file,
+# otherwise system server activity hints will kick in
+# and the new just-in-time app pre-warmup will happen.
+if [[ $keep_application_trace_file == "n" ]]; then
+  adb shell "[[ -f '$application_trace_file_path' ]] && rm '$application_trace_file_path'"
+fi
+
+# Perform AOT readahead/pinning/etc when an application is about to be launched.
+# For JIT readahead, we allow the system to handle it itself (this is a no-op).
+#
+# For warm, cold, etc modes which don't need readahead this is always a no-op.
+perform_aot() {
+  local the_when="$1" # user: aot, jit
+  local the_mode="$2" # warm, cold, fadvise, mlock, etc.
+
+  if [[ $the_when != "aot" ]]; then
+    # TODO: just in time implementation.. should probably use system server.
+    return 0
+  fi
+
+  # any non-warm/non-cold modes should use the iorap-activity-hint wrapper script.
+  if [[ $the_mode != 'warm' && $the_mode != 'cold' ]]; then
+
+    # TODO: add activity_hint_sender.exp
+    verbose_print "starting with package=$package package_path=$trace_file_directory"
+    coproc hint_sender_fd { $ANDROID_BUILD_TOP/system/iorap/src/sh/activity_hint_sender.exp "$package" "$trace_file_directory" "$the_mode"; }
+    hint_sender_pid=$!
+    verbose_print "Activity hint sender began"
+
+    notification_success="n"
+    while read -r -u "${hint_sender_fd[0]}" hint_sender_output; do
+      verbose_print "$hint_sender_output"
+      if [[ "$hint_sender_output" == "Press any key to send completed event..."* ]]; then
+        verbose_print "WE DID SEE NOTIFICATION SUCCESS."
+        notification_success='y'
+        # Give it some time to actually perform the readaheads.
+        sleep $sleep_time
+        break
+      fi
+    done
+
+    if [[ $notification_success == 'n' ]]; then
+      echo "[FATAL] Activity hint notification failed." 1>&2
+      exit 1
+    fi
+  fi
+}
+
+perform_aot_cleanup() {
+  local the_when="$1" # user: aot, jit
+  local the_mode="$2" # warm, cold, fadvise, mlock, etc.
+
+  if [[ $the_when != "aot" ]]; then
+    # TODO: just in time implementation.. should probably use system server.
+    return 0
+  fi
+
+  # any non-warm/non-cold modes should use the iorap-activity-hint wrapper script.
+  if [[ $the_mode != 'warm' && $the_mode != 'cold' ]]; then
+    # Clean up the hint sender by telling it that the launch was completed,
+    # and to shutdown the watcher.
+    echo "Done\n" >&"${hint_sender_fd[1]}"
+
+    while read -r -u "${hint_sender_fd[0]}" hint_sender_output; do
+      verbose_print "$hint_sender_output"
+    done
+
+    wait $hint_sender_pid
+  fi
+}
+
+configure_compiler_filter() {
+  local the_compiler_filter="$1"
+  local the_package="$2"
+  local the_activity="$3"
+
+  if [[ -z $the_compiler_filter ]]; then
+    verbose_print "No --compiler-filter specified, don't need to force it."
+    return 0
+  fi
+
+  local current_compiler_filter_info="$("$DIR"/query_compiler_filter.py --package "$the_package")"
+  local res=$?
+  if [[ $res -ne 0 ]]; then
+    return $res
+  fi
+
+  local current_compiler_filter
+  local current_reason
+  local current_isa
+  read current_compiler_filter current_reason current_isa <<< "$current_compiler_filter_info"
+
+  verbose_print "Compiler Filter="$current_compiler_filter "Reason="$current_reason "Isa="$current_isa
+
+  # Don't trust reasons that aren't 'unknown' because that means we didn't manually force the compilation filter.
+  # (e.g. if any automatic system-triggered compilations are not unknown).
+  if [[ $current_reason != "unknown" ]] || [[ $current_compiler_filter != $the_compiler_filter ]]; then
+    verbose_print "$DIR"/force_compiler_filter --compiler-filter "$the_compiler_filter" --package "$the_package" --activity "$the_activity"
+    "$DIR"/force_compiler_filter --compiler-filter "$the_compiler_filter" --package "$the_package" --activity "$the_activity"
+    res=$?
+  else
+    verbose_print "Queried compiler-filter matched requested compiler-filter, skip forcing."
+    res=0
+  fi
+
+  return $res
+}
+
+# Ensure the APK is currently compiled with whatever we passed in via --compiler-filter.
+# No-op if this option was not passed in.
+configure_compiler_filter "$compiler_filter" "$package" "$activity" || exit 1
+
+# TODO: This loop logic could probably be moved into app_startup_runner.py
+for ((i=0;i<count;++i)) do
+  verbose_print "=========================================="
+  verbose_print "====         ITERATION $i             ===="
+  verbose_print "=========================================="
+  if [[ $mode != "warm" ]]; then
+    verbose_print "Drop caches for non-warm start."
+    # Drop all caches to get cold starts.
+    adb shell "echo 3 > /proc/sys/vm/drop_caches"
+  fi
+
+  perform_aot "$when" "$mode"
+
+  verbose_print "Running with timeout $timeout"
+
+  # TODO: multiple metrics output.
+  total_time="$(timeout $timeout $DIR/launch_application "$package" "$activity")"
+
+  if [[ $? -ne 0 ]]; then
+    echo "WARNING: Skip bad result, try iteration again." >&2
+    ((i=i-1))
+    continue
+  fi
+
+  perform_aot_cleanup "$when" "$mode"
+
+  echo "Iteration $i. Total time was: $total_time"
+
+  timings_array+=($total_time)
+done
+
+# drop the first result which is usually garbage.
+timings_array=("${timings_array[@]:1}")
+
+
+# Print out interactive/debugging timings and averages.
+# Other scripts should use the --output flag and parse the CSV.
+for tim in "${timings_array[@]}"; do
+  echo_to_output_file -ne "$tim,"
+done
+echo_to_output_file ""
+
+average_string=$(echo "${timings_array[@]}" | awk '{s+=$0}END{print "Average:",s/NR}' RS=" ")
+echo -ne ${average_string}.
+if [[ x$output != x ]]; then
+  echo " Saved results to '$output'"
+fi
+
+# Temporary hack around multiple activities being launched with different package paths (for same app):
+# Clean up all left-over TraceFile.pb
+adb shell 'for i in $(find /data/app -name TraceFile.pb); do rm \$i; done'
+
+# Kill the process to ensure AM isn't keeping it around.
+remote_pkill "$package"
+
+exit 0
diff --git a/startop/scripts/app_startup/unlock_screen b/startop/scripts/app_startup/unlock_screen
new file mode 100755
index 0000000..478294c
--- /dev/null
+++ b/startop/scripts/app_startup/unlock_screen
@@ -0,0 +1,22 @@
+#!/bin/bash
+#
+# 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 turns the screen on if it's off.
+# If it's on it does nothing unless its on the home screen, in which case it opens up some background
+# menu.
+#
+# However, this menu is ignored because "am start" commands still work as expected.
+adb shell input keyevent MENU
diff --git a/telecomm/java/android/telecom/ParcelableCall.java b/telecomm/java/android/telecom/ParcelableCall.java
index 8b0211e..3ad0f0c 100644
--- a/telecomm/java/android/telecom/ParcelableCall.java
+++ b/telecomm/java/android/telecom/ParcelableCall.java
@@ -18,6 +18,7 @@
 
 import android.annotation.UnsupportedAppUsage;
 import android.net.Uri;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -118,7 +119,7 @@
     }
 
     /** The unique ID of the call. */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     public String getId() {
         return mId;
     }
diff --git a/telecomm/java/android/telecom/ParcelableCallAnalytics.java b/telecomm/java/android/telecom/ParcelableCallAnalytics.java
index 383d10b..bb066ad 100644
--- a/telecomm/java/android/telecom/ParcelableCallAnalytics.java
+++ b/telecomm/java/android/telecom/ParcelableCallAnalytics.java
@@ -195,6 +195,8 @@
         public static final int BLOCK_CHECK_FINISHED_TIMING = 9;
         public static final int FILTERING_COMPLETED_TIMING = 10;
         public static final int FILTERING_TIMED_OUT_TIMING = 11;
+        /** {@hide} */
+        public static final int START_CONNECTION_TO_REQUEST_DISCONNECT_TIMING = 12;
 
         public static final int INVALID = 999999;
 
@@ -256,6 +258,27 @@
     public static final int SIP_PHONE = 0x8;
     public static final int THIRD_PARTY_PHONE = 0x10;
 
+    /**
+     * Indicating the call source is not specified.
+     *
+     * @hide
+     */
+    public static final int CALL_SOURCE_UNSPECIFIED = 0;
+
+    /**
+     * Indicating the call is initiated via emergency dialer's dialpad.
+     *
+     * @hide
+     */
+    public static final int CALL_SOURCE_EMERGENCY_DIALPAD = 1;
+
+    /**
+     * Indicating the call is initiated via emergency dialer's shortcut button.
+     *
+     * @hide
+     */
+    public static final int CALL_SOURCE_EMERGENCY_SHORTCUT = 2;
+
     public static final long MILLIS_IN_5_MINUTES = 1000 * 60 * 5;
     public static final long MILLIS_IN_1_SECOND = 1000;
 
@@ -319,6 +342,9 @@
     // A list of video events that have occurred.
     private List<VideoEvent> videoEvents;
 
+    // The source where user initiated this call. ONE OF the CALL_SOURCE_* constants.
+    private int callSource = CALL_SOURCE_UNSPECIFIED;
+
     public ParcelableCallAnalytics(long startTimeMillis, long callDurationMillis, int callType,
             boolean isAdditionalCall, boolean isInterrupted, int callTechnologies,
             int callTerminationCode, boolean isEmergencyCall, String connectionService,
@@ -356,6 +382,7 @@
         isVideoCall = readByteAsBoolean(in);
         videoEvents = new LinkedList<>();
         in.readTypedList(videoEvents, VideoEvent.CREATOR);
+        callSource = in.readInt();
     }
 
     public void writeToParcel(Parcel out, int flags) {
@@ -373,6 +400,7 @@
         out.writeTypedList(eventTimings);
         writeBooleanAsByte(out, isVideoCall);
         out.writeTypedList(videoEvents);
+        out.writeInt(callSource);
     }
 
     /** {@hide} */
@@ -385,6 +413,11 @@
         this.videoEvents = videoEvents;
     }
 
+    /** {@hide} */
+    public void setCallSource(int callSource) {
+        this.callSource = callSource;
+    }
+
     public long getStartTimeMillis() {
         return startTimeMillis;
     }
@@ -443,6 +476,11 @@
         return videoEvents;
     }
 
+    /** {@hide} */
+    public int getCallSource() {
+        return callSource;
+    }
+
     @Override
     public int describeContents() {
         return 0;
diff --git a/telecomm/java/android/telecom/PhoneAccountHandle.java b/telecomm/java/android/telecom/PhoneAccountHandle.java
index 279804e..097e352 100644
--- a/telecomm/java/android/telecom/PhoneAccountHandle.java
+++ b/telecomm/java/android/telecom/PhoneAccountHandle.java
@@ -19,6 +19,7 @@
 import android.annotation.NonNull;
 import android.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
+import android.os.Build;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.Process;
@@ -43,7 +44,7 @@
 public final class PhoneAccountHandle implements Parcelable {
     @UnsupportedAppUsage
     private final ComponentName mComponentName;
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private final String mId;
     private final UserHandle mUserHandle;
 
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 48c1e24..4e22823 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -622,6 +622,18 @@
             "android.telecom.extra.USE_ASSISTED_DIALING";
 
     /**
+     * Optional extra for {@link #placeCall(Uri, Bundle)} containing an integer that specifies
+     * the source where user initiated this call. This data is used in metrics.
+     * Valid source are:
+     * {@link ParcelableCallAnalytics#CALL_SOURCE_UNSPECIFIED},
+     * {@link ParcelableCallAnalytics#CALL_SOURCE_EMERGENCY_DIALPAD},
+     * {@link ParcelableCallAnalytics#CALL_SOURCE_EMERGENCY_SHORTCUT}.
+     *
+     * @hide
+     */
+    public static final String EXTRA_CALL_SOURCE = "android.telecom.extra.CALL_SOURCE";
+
+    /**
      * The following 4 constants define how properties such as phone numbers and names are
      * displayed to the user.
      */
diff --git a/telephony/java/android/provider/Telephony.java b/telephony/java/android/provider/Telephony.java
index ed84788..722df67 100644
--- a/telephony/java/android/provider/Telephony.java
+++ b/telephony/java/android/provider/Telephony.java
@@ -30,6 +30,7 @@
 import android.database.Cursor;
 import android.database.sqlite.SqliteWrapper;
 import android.net.Uri;
+import android.os.Build;
 import android.telephony.Rlog;
 import android.telephony.ServiceState;
 import android.telephony.SmsMessage;
@@ -374,7 +375,7 @@
          * Return cursor for table query.
          * @hide
          */
-        @UnsupportedAppUsage
+        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
         public static Cursor query(ContentResolver cr, String[] projection,
                 String where, String orderBy) {
             return cr.query(CONTENT_URI, projection, where,
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 8703e65..ffbe7d3 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -107,13 +107,34 @@
 
    /**
     * Boolean indicating if the "Call barring" item is visible in the Call Settings menu.
-    * true means visible. false means gone.
-    * @hide
+    * If true, the "Call Barring" menu will be visible. If false, the menu will be gone.
+    *
+    * Disabled by default.
     */
     public static final String KEY_CALL_BARRING_VISIBILITY_BOOL =
             "call_barring_visibility_bool";
 
     /**
+     * Flag indicating whether or not changing the call barring password via the "Call Barring"
+     * settings menu is supported. If true, the option will be visible in the "Call
+     * Barring" settings menu. If false, the option will not be visible.
+     *
+     * Enabled by default.
+     */
+    public static final String KEY_CALL_BARRING_SUPPORTS_PASSWORD_CHANGE_BOOL =
+            "call_barring_supports_password_change_bool";
+
+    /**
+     * Flag indicating whether or not deactivating all call barring features via the "Call Barring"
+     * settings menu is supported. If true, the option will be visible in the "Call
+     * Barring" settings menu. If false, the option will not be visible.
+     *
+     * Enabled by default.
+     */
+    public static final String KEY_CALL_BARRING_SUPPORTS_DEACTIVATE_ALL_BOOL =
+            "call_barring_supports_deactivate_all_bool";
+
+    /**
      * Flag indicating whether the Phone app should ignore EVENT_SIM_NETWORK_LOCKED
      * events from the Sim.
      * If true, this will prevent the IccNetworkDepersonalizationPanel from being shown, and
@@ -2125,6 +2146,8 @@
 
         sDefaults.putBoolean(KEY_CARRIER_VOLTE_PROVISIONED_BOOL, false);
         sDefaults.putBoolean(KEY_CALL_BARRING_VISIBILITY_BOOL, false);
+        sDefaults.putBoolean(KEY_CALL_BARRING_SUPPORTS_PASSWORD_CHANGE_BOOL, true);
+        sDefaults.putBoolean(KEY_CALL_BARRING_SUPPORTS_DEACTIVATE_ALL_BOOL, true);
         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);
diff --git a/telephony/java/android/telephony/PhoneStateListener.java b/telephony/java/android/telephony/PhoneStateListener.java
index bd6a59d..498be96 100644
--- a/telephony/java/android/telephony/PhoneStateListener.java
+++ b/telephony/java/android/telephony/PhoneStateListener.java
@@ -23,6 +23,7 @@
 import android.os.Looper;
 import android.os.Message;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.IPhoneStateListener;
 
 import java.lang.ref.WeakReference;
@@ -778,8 +779,12 @@
         }
     }
 
+    /**
+     * @hide
+     */
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
     @UnsupportedAppUsage
-    IPhoneStateListener callback = new IPhoneStateListenerStub(this);
+    public final IPhoneStateListener callback = new IPhoneStateListenerStub(this);
 
     private void log(String s) {
         Rlog.d(LOG_TAG, s);
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index 2ee1a09..f2b73dc 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -353,9 +353,11 @@
         mIsDataRoamingFromRegistration = s.mIsDataRoamingFromRegistration;
         mIsUsingCarrierAggregation = s.mIsUsingCarrierAggregation;
         mChannelNumber = s.mChannelNumber;
-        mCellBandwidths = Arrays.copyOf(s.mCellBandwidths, s.mCellBandwidths.length);
+        mCellBandwidths = s.mCellBandwidths == null ? null :
+                Arrays.copyOf(s.mCellBandwidths, s.mCellBandwidths.length);
         mLteEarfcnRsrpBoost = s.mLteEarfcnRsrpBoost;
-        mNetworkRegistrationStates = new ArrayList<>(s.mNetworkRegistrationStates);
+        mNetworkRegistrationStates = s.mNetworkRegistrationStates == null ? null :
+                new ArrayList<>(s.mNetworkRegistrationStates);
     }
 
     /**
@@ -812,7 +814,9 @@
                 && mIsEmergencyOnly == s.mIsEmergencyOnly
                 && mIsDataRoamingFromRegistration == s.mIsDataRoamingFromRegistration
                 && mIsUsingCarrierAggregation == s.mIsUsingCarrierAggregation)
-                && mNetworkRegistrationStates.containsAll(s.mNetworkRegistrationStates);
+                && (mNetworkRegistrationStates == null ? s.mNetworkRegistrationStates == null :
+                        s.mNetworkRegistrationStates != null &&
+                        mNetworkRegistrationStates.containsAll(s.mNetworkRegistrationStates));
     }
 
     /**
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 119733e..b01d419 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -19,6 +19,7 @@
 import static android.net.NetworkPolicyManager.OVERRIDE_CONGESTED;
 import static android.net.NetworkPolicyManager.OVERRIDE_UNMETERED;
 
+import android.annotation.CallbackExecutor;
 import android.annotation.DurationMillisLong;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -40,6 +41,7 @@
 import android.net.INetworkPolicyManager;
 import android.net.NetworkCapabilities;
 import android.net.Uri;
+import android.os.Build;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
@@ -47,6 +49,7 @@
 import android.os.ServiceManager;
 import android.telephony.euicc.EuiccManager;
 import android.util.DisplayMetrics;
+import android.util.Log;
 
 import com.android.internal.telephony.IOnSubscriptionsChangedListener;
 import com.android.internal.telephony.ISub;
@@ -57,6 +60,7 @@
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
+import java.util.concurrent.Executor;
 import java.util.concurrent.TimeUnit;
 
 /**
@@ -188,7 +192,7 @@
      * The name_source is from the user
      * @hide
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     public static final int NAME_SOURCE_USER_INPUT = 2;
 
     /**
@@ -666,7 +670,7 @@
                 tr.addOnSubscriptionsChangedListener(pkgName, listener.callback);
             }
         } catch (RemoteException ex) {
-            // Should not happen
+            Log.e(LOG_TAG, "Remote exception ITelephonyRegistry " + ex);
         }
     }
 
@@ -684,7 +688,7 @@
                     + " listener=" + listener);
         }
         try {
-            // We use the TelephonyRegistry as its runs in the system and thus is always
+            // We use the TelephonyRegistry as it runs in the system and thus is always
             // available where as SubscriptionController could crash and not be available
             ITelephonyRegistry tr = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService(
                     "telephony.registry"));
@@ -692,7 +696,116 @@
                 tr.removeOnSubscriptionsChangedListener(pkgForDebug, listener.callback);
             }
         } catch (RemoteException ex) {
-            // Should not happen
+            Log.e(LOG_TAG, "Remote exception ITelephonyRegistry " + ex);
+        }
+    }
+
+    /**
+     * A listener class for monitoring changes to {@link SubscriptionInfo} records of opportunistic
+     * subscriptions.
+     * <p>
+     * Override the onOpportunisticSubscriptionsChanged method in the object that extends this
+     * or {@link #addOnOpportunisticSubscriptionsChangedListener(
+     * Executor, OnOpportunisticSubscriptionsChangedListener)}
+     * to register your listener and to unregister invoke
+     * {@link #removeOnOpportunisticSubscriptionsChangedListener(
+     * OnOpportunisticSubscriptionsChangedListener)}
+     * <p>
+     * Permissions android.Manifest.permission.READ_PHONE_STATE is required
+     * for #onOpportunisticSubscriptionsChanged to be invoked.
+     */
+    public static class OnOpportunisticSubscriptionsChangedListener {
+        private Executor mExecutor;
+        /**
+         * Callback invoked when there is any change to any SubscriptionInfo. Typically
+         * this method would invoke {@link #getActiveSubscriptionInfoList}
+         */
+        public void onOpportunisticSubscriptionsChanged() {
+            if (DBG) log("onOpportunisticSubscriptionsChanged: NOT OVERRIDDEN");
+        }
+
+        private void setExecutor(Executor executor) {
+            mExecutor = executor;
+        }
+
+        /**
+         * The callback methods need to be called on the handler thread where
+         * this object was created.  If the binder did that for us it'd be nice.
+         */
+        IOnSubscriptionsChangedListener callback = new IOnSubscriptionsChangedListener.Stub() {
+            @Override
+            public void onSubscriptionsChanged() {
+                if (DBG) log("onOpportunisticSubscriptionsChanged callback received.");
+                mExecutor.execute(() -> onOpportunisticSubscriptionsChanged());
+            }
+        };
+
+        private void log(String s) {
+            Rlog.d(LOG_TAG, s);
+        }
+    }
+
+    /**
+     * Register for changes to the list of opportunistic subscription records or to the
+     * individual records themselves. When a change occurs the onOpportunisticSubscriptionsChanged
+     * method of the listener will be invoked immediately if there has been a notification.
+     *
+     * @param listener an instance of {@link OnOpportunisticSubscriptionsChangedListener} with
+     *                 onOpportunisticSubscriptionsChanged overridden.
+     */
+    public void addOnOpportunisticSubscriptionsChangedListener(
+            @NonNull @CallbackExecutor Executor executor,
+            @NonNull OnOpportunisticSubscriptionsChangedListener listener) {
+        if (executor == null || listener == null) {
+            return;
+        }
+
+        String pkgName = mContext != null ? mContext.getOpPackageName() : "<unknown>";
+        if (DBG) {
+            logd("register addOnOpportunisticSubscriptionsChangedListener pkgName=" + pkgName
+                    + " listener=" + listener);
+        }
+
+        listener.setExecutor(executor);
+
+        try {
+            // We use the TelephonyRegistry as it runs in the system and thus is always
+            // available. Where as SubscriptionController could crash and not be available
+            ITelephonyRegistry tr = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService(
+                    "telephony.registry"));
+            if (tr != null) {
+                tr.addOnOpportunisticSubscriptionsChangedListener(pkgName, listener.callback);
+            }
+        } catch (RemoteException ex) {
+            Log.e(LOG_TAG, "Remote exception ITelephonyRegistry " + ex);
+        }
+    }
+
+    /**
+     * Unregister the {@link OnOpportunisticSubscriptionsChangedListener} that is currently
+     * listening opportunistic subscriptions change. This is not strictly necessary
+     * as the listener will automatically be unregistered if an attempt to invoke the listener
+     * fails.
+     *
+     * @param listener that is to be unregistered.
+     */
+    public void removeOnOpportunisticSubscriptionsChangedListener(
+            OnOpportunisticSubscriptionsChangedListener listener) {
+        String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>";
+        if (DBG) {
+            logd("unregister OnOpportunisticSubscriptionsChangedListener pkgForDebug="
+                    + pkgForDebug + " listener=" + listener);
+        }
+        try {
+            // We use the TelephonyRegistry as it runs in the system and thus is always
+            // available where as SubscriptionController could crash and not be available
+            ITelephonyRegistry tr = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService(
+                    "telephony.registry"));
+            if (tr != null) {
+                tr.removeOnSubscriptionsChangedListener(pkgForDebug, listener.callback);
+            }
+        } catch (RemoteException ex) {
+            Log.e(LOG_TAG, "Remote exception ITelephonyRegistry " + ex);
         }
     }
 
@@ -1177,6 +1290,15 @@
 
     }
 
+    /**
+     * Get an array of Subscription Ids for specified slot Index.
+     * @param slotIndex the slot Index.
+     * @return subscription Ids or null if the given slot Index is not valid.
+     */
+    public static int[] getSubscriptionIds(int slotIndex) {
+        return getSubId(slotIndex);
+    }
+
     /** @hide */
     @UnsupportedAppUsage
     public static int[] getSubId(int slotIndex) {
@@ -1468,12 +1590,14 @@
     }
 
     /**
-     * @return true if a valid subId else false
-     * @hide
+     * Checks if the supplied subscription ID is valid.
+     * Note: a valid subscription ID does not necessarily correspond to an active subscription.
+     *
+     * @param subscriptionId The subscription ID.
+     * @return true if the supplied subscriptionId is valid; false otherwise.
      */
-    @UnsupportedAppUsage
-    public static boolean isValidSubscriptionId(int subId) {
-        return subId > INVALID_SUBSCRIPTION_ID ;
+    public static boolean isValidSubscriptionId(int subscriptionId) {
+        return subscriptionId > INVALID_SUBSCRIPTION_ID;
     }
 
     /**
@@ -1487,7 +1611,7 @@
     }
 
     /** @hide */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     public static boolean isValidSlotIndex(int slotIndex) {
         return slotIndex >= 0 && slotIndex < TelephonyManager.getDefault().getSimCount();
     }
@@ -2007,20 +2131,21 @@
     }
 
     /**
-     * Get User downloaded Profiles.
+     * Get opportunistic data Profiles.
      *
-     *  Provide all available user downloaded profile on the phone.
-     *  @param slotId on which phone the switch will operate on
+     *  Provide all available user downloaded profiles on phone which are used only for
+     *  opportunistic data.
+     *  @param slotIndex slot on which the profiles are queried from.
      */
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
-    List<SubscriptionInfo> getOpportunisticSubscriptions(int slotId) {
+    public List<SubscriptionInfo> getOpportunisticSubscriptions(int slotIndex) {
         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);
+                subInfoList = iSub.getOpportunisticSubscriptions(slotIndex, pkgForDebug);
             }
         } catch (RemoteException ex) {
             // ignore it
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index abcdeed..b348623 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -39,6 +39,7 @@
 import android.net.Uri;
 import android.os.AsyncTask;
 import android.os.BatteryStats;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.PersistableBundle;
@@ -64,6 +65,7 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telecom.ITelecomService;
 import com.android.internal.telephony.CellNetworkScanResult;
+import com.android.internal.telephony.IAnas;
 import com.android.internal.telephony.IPhoneSubInfo;
 import com.android.internal.telephony.ITelephony;
 import com.android.internal.telephony.ITelephonyRegistry;
@@ -134,6 +136,22 @@
         static final int NEVER_USE = 2;
     }
 
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = {"NETWORK_SELECTION_MODE_"},
+            value = {
+                    NETWORK_SELECTION_MODE_UNKNOWN,
+                    NETWORK_SELECTION_MODE_AUTO,
+                    NETWORK_SELECTION_MODE_MANUAL})
+    public @interface NetworkSelectionMode {}
+
+    /** @hide */
+    public static final int NETWORK_SELECTION_MODE_UNKNOWN = 0;
+    /** @hide */
+    public static final int NETWORK_SELECTION_MODE_AUTO = 1;
+    /** @hide */
+    public static final int NETWORK_SELECTION_MODE_MANUAL = 2;
+
     /** The otaspMode passed to PhoneStateListener#onOtaspChanged */
     /** @hide */
     static public final int OTASP_UNINITIALIZED = 0;
@@ -685,7 +703,7 @@
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     @Deprecated
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     public static final String ACTION_PRECISE_DATA_CONNECTION_STATE_CHANGED =
             "android.intent.action.PRECISE_DATA_CONNECTION_STATE_CHANGED";
 
@@ -1673,7 +1691,7 @@
     }
 
     /** {@hide} */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private int getPhoneTypeFromProperty(int phoneId) {
         String type = getTelephonyProperty(phoneId,
                 TelephonyProperties.CURRENT_ACTIVE_PHONE, null);
@@ -4327,6 +4345,10 @@
         return ITelephonyRegistry.Stub.asInterface(ServiceManager.getService("telephony.registry"));
     }
 
+    private IAnas getIAnas() {
+        return IAnas.Stub.asInterface(ServiceManager.getService("ianas"));
+    }
+
     //
     //
     // PhoneStateListener
@@ -5785,6 +5807,31 @@
         return false;
     }
 
+   /**
+     * Get the network selection mode.
+     *
+     * <p>If this object has been created with {@link #createForSubscriptionId}, applies to the
+     * given subId. Otherwise, applies to {@link SubscriptionManager#getDefaultDataSubscriptionId()}
+
+     * @return the network selection mode.
+     *
+     * @hide
+     */
+    @NetworkSelectionMode
+    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+    public int getNetworkSelectionMode() {
+        int mode = NETWORK_SELECTION_MODE_UNKNOWN;
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony != null) {
+                mode = telephony.getNetworkSelectionMode(getSubId());
+            }
+        } catch (RemoteException ex) {
+            Rlog.e(TAG, "getNetworkSelectionMode RemoteException", ex);
+        }
+        return mode;
+    }
+
     /**
      * Set the preferred network type.
      * Used for device configuration by some CDMA operators.
@@ -6699,6 +6746,84 @@
     }
 
     /**
+     * Gets the roaming mode for CDMA phone.
+     *
+     * <p>If this object has been created with {@link #createForSubscriptionId}, applies to the
+     * given subId. Otherwise, applies to {@link SubscriptionManager#getDefaultDataSubscriptionId()}
+     *
+     * @return one of {@link #CDMA_ROAMING_MODE_RADIO_DEFAULT}, {@link #CDMA_ROAMING_MODE_HOME},
+     * {@link #CDMA_ROAMING_MODE_AFFILIATED}, {@link #CDMA_ROAMING_MODE_ANY}.
+     *
+     * @hide
+     */
+    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+    public int getCdmaRoamingMode() {
+        int mode = CDMA_ROAMING_MODE_RADIO_DEFAULT;
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony != null) {
+                mode = telephony.getCdmaRoamingMode(getSubId());
+            }
+        } catch (RemoteException ex) {
+            Log.e(TAG, "Error calling ITelephony#getCdmaRoamingMode", ex);
+        }
+        return mode;
+    }
+
+    /**
+     * Sets the roaming mode for CDMA phone to the given mode {@code mode}.
+     *
+     * <p>If this object has been created with {@link #createForSubscriptionId}, applies to the
+     * given subId. Otherwise, applies to {@link SubscriptionManager#getDefaultDataSubscriptionId()}
+     *
+     * @param mode should be one of {@link #CDMA_ROAMING_MODE_RADIO_DEFAULT},
+     * {@link #CDMA_ROAMING_MODE_HOME}, {@link #CDMA_ROAMING_MODE_AFFILIATED},
+     * {@link #CDMA_ROAMING_MODE_ANY}.
+     *
+     * @return {@code true} if successed.
+     *
+     * @hide
+     */
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+    public boolean setCdmaRoamingMode(int mode) {
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony != null) {
+                return telephony.setCdmaRoamingMode(getSubId(), mode);
+            }
+        } catch (RemoteException ex) {
+            Log.e(TAG, "Error calling ITelephony#setCdmaRoamingMode", ex);
+        }
+        return false;
+    }
+
+    /**
+     * Sets the subscription mode for CDMA phone to the given mode {@code mode}.
+     *
+     * @param mode CDMA subscription mode
+     *
+     * @return {@code true} if successed.
+     *
+     * @see Phone#CDMA_SUBSCRIPTION_UNKNOWN
+     * @see Phone#CDMA_SUBSCRIPTION_RUIM_SIM
+     * @see Phone#CDMA_SUBSCRIPTION_NV
+     *
+     * @hide
+     */
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+    public boolean setCdmaSubscriptionMode(int mode) {
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony != null) {
+                return telephony.setCdmaSubscriptionMode(getSubId(), mode);
+            }
+        } catch (RemoteException ex) {
+            Log.e(TAG, "Error calling ITelephony#setCdmaSubscriptionMode", ex);
+        }
+        return false;
+    }
+
+    /**
      * Enables/Disables the data roaming on the subscription.
      *
      * <p>If this object has been created with {@link #createForSubscriptionId}, applies to the
@@ -8193,7 +8318,6 @@
         return UNKNOWN_CARRIER_ID_LIST_VERSION;
     }
 
-
     /**
      * How many modems can have simultaneous data connections.
      * @hide
@@ -8211,4 +8335,62 @@
         }
         return 0;
     }
+
+    /**
+     * Enable or disable AlternativeNetworkAccessService.
+     *
+     * This method should be called to enable or disable
+     * AlternativeNetworkAccess service on the device.
+     *
+     * <p>
+     * Requires Permission:
+     *   {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
+     *
+     * @param enable enable(True) or disable(False)
+     * @return returns true if successfully set.
+     * @hide
+     */
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+    public boolean setAlternativeNetworkAccessState(boolean enable) {
+        String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>";
+        boolean ret = false;
+        try {
+            IAnas iAlternativeAccessService = getIAnas();
+            if (iAlternativeAccessService != null) {
+                ret = iAlternativeAccessService.setEnable(enable, pkgForDebug);
+            }
+        } catch (RemoteException ex) {
+            Rlog.e(TAG, "enableAlternativeNetworkAccess RemoteException", ex);
+        }
+
+        return ret;
+    }
+
+    /**
+     * is AlternativeNetworkAccessService enabled
+     *
+     * This method should be called to determine if the AlternativeNetworkAccessService is
+     * enabled
+     *
+     * <p>
+     * Requires Permission:
+     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+     * @hide
+     */
+    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+    public boolean isAlternativeNetworkAccessEnabled() {
+        String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>";
+        boolean isEnabled = false;
+
+        try {
+            IAnas iAlternativeAccessService = getIAnas();
+            if (iAlternativeAccessService != null) {
+                isEnabled = iAlternativeAccessService.isEnabled(pkgForDebug);
+            }
+        } catch (RemoteException ex) {
+            Rlog.e(TAG, "enableAlternativeNetworkAccess RemoteException", ex);
+        }
+
+        return isEnabled;
+    }
 }
diff --git a/telephony/java/com/android/internal/telephony/IAnas.aidl b/telephony/java/com/android/internal/telephony/IAnas.aidl
new file mode 100755
index 0000000..88d681a
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/IAnas.aidl
@@ -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.internal.telephony;
+
+
+interface IAnas {
+
+    /**
+    * Enable or disable Alternative Network Access service.
+    *
+    * This method should be called to enable or disable
+    * AlternativeNetworkAccess service on the device.
+    *
+    * <p>
+    * Requires Permission:
+    *   {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
+    * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+    *
+    * @param enable enable(True) or disable(False)
+    * @param callingPackage caller's package name
+    * @return returns true if successfully set.
+    */
+    boolean setEnable(boolean enable, String callingPackage);
+
+    /**
+     * is Alternative Network Access service enabled
+     *
+     * This method should be called to determine if the Alternative Network Access service is enabled
+    *
+    * <p>
+    * Requires Permission:
+    *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+    * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+    *
+    * @param callingPackage caller's package name
+    */
+    boolean isEnabled(String callingPackage);
+}
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index a7e5581..c0bccde 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -1530,6 +1530,34 @@
     void setDataRoamingEnabled(int subId, boolean isEnabled);
 
     /**
+     * Gets the roaming mode for the CDMA phone with the subscription id {@code subId}.
+     *
+     * @param the subscription id.
+     * @return the roaming mode for CDMA phone.
+     */
+    int getCdmaRoamingMode(int subId);
+
+    /**
+     * Sets the roaming mode on the CDMA phone with the subscription {@code subId} to the given
+     * roaming mode {@code mode}.
+     *
+     * @param subId the subscription id.
+     * @param mode the roaming mode should be set.
+     * @return {@code true} if successed.
+     */
+    boolean setCdmaRoamingMode(int subId, int mode);
+
+    /**
+     * Sets the subscription mode for CDMA phone with the subscription {@code subId} to the given
+     * subscription mode {@code mode}.
+     *
+     * @param subId the subscription id.
+     * @param mode the subscription mode should be set.
+     * @return {@code true} if successed.
+     */
+    boolean setCdmaSubscriptionMode(int subId, int mode);
+
+    /**
      * A test API to override carrier information including mccmnc, imsi, iccid, gid1, gid2,
      * plmn and spn. This would be handy for, eg, forcing a particular carrier id, carrier's config
      * (also any country or carrier overlays) to be loaded when using a test SIM with a call box.
@@ -1553,4 +1581,9 @@
      * @hide
      */
     int getNumberOfModemsWithSimultaneousDataConnections(int subId, String callingPackage);
+
+    /**
+     * Return the network selection mode on the subscription with id {@code subId}.
+     */
+     int getNetworkSelectionMode(int subId);
 }
diff --git a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
index e0e1a7b..43d56b3 100644
--- a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
@@ -32,6 +32,8 @@
 interface ITelephonyRegistry {
     void addOnSubscriptionsChangedListener(String pkg,
             IOnSubscriptionsChangedListener callback);
+    void addOnOpportunisticSubscriptionsChangedListener(String pkg,
+            IOnSubscriptionsChangedListener callback);
     void removeOnSubscriptionsChangedListener(String pkg,
             IOnSubscriptionsChangedListener callback);
     void listen(String pkg, IPhoneStateListener callback, int events, boolean notifyNow);
@@ -73,6 +75,7 @@
             int activationState, int activationType);
     void notifyOemHookRawEventForSubscriber(in int subId, in byte[] rawData);
     void notifySubscriptionInfoChanged();
+    void notifyOpportunisticSubscriptionInfoChanged();
     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/gsm/SmsCbConstants.java b/telephony/java/com/android/internal/telephony/gsm/SmsCbConstants.java
index 0fabc2f..541ca8d 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SmsCbConstants.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SmsCbConstants.java
@@ -118,71 +118,103 @@
     public static final int MESSAGE_ID_CMAS_ALERT_OPERATOR_DEFINED_USE
             = 0x111E; // 4382
 
-    /** CMAS Message Identifier for Presidential Level alerts for additional languages
-     *  for additional languages. */
+    /**
+     * CMAS Message Identifier for Presidential Level alerts for additional languages.
+     */
     public static final int MESSAGE_ID_CMAS_ALERT_PRESIDENTIAL_LEVEL_LANGUAGE
             = 0x111F; // 4383
 
-    /** CMAS Message Identifier for Extreme alerts, Urgency=Immediate, Certainty=Observed
-     *  for additional languages. */
+    /**
+     * CMAS Message Identifier for Extreme alerts, Urgency=Immediate, Certainty=Observed
+     * for additional languages.
+     */
     public static final int MESSAGE_ID_CMAS_ALERT_EXTREME_IMMEDIATE_OBSERVED_LANGUAGE
             = 0x1120; // 4384
 
-    /** CMAS Message Identifier for Extreme alerts, Urgency=Immediate, Certainty=Likely
-     *  for additional languages. */
+    /**
+     * CMAS Message Identifier for Extreme alerts, Urgency=Immediate, Certainty=Likely
+     *  for additional languages.
+     */
     public static final int MESSAGE_ID_CMAS_ALERT_EXTREME_IMMEDIATE_LIKELY_LANGUAGE
             = 0x1121; // 4385
 
-    /** CMAS Message Identifier for Extreme alerts, Urgency=Expected, Certainty=Observed
-     *  for additional languages. */
+    /**
+     * CMAS Message Identifier for Extreme alerts, Urgency=Expected, Certainty=Observed
+     * for additional languages.
+     */
     public static final int MESSAGE_ID_CMAS_ALERT_EXTREME_EXPECTED_OBSERVED_LANGUAGE
             = 0x1122; // 4386
 
-    /** CMAS Message Identifier for Extreme alerts, Urgency=Expected, Certainty=Likely
-     *  for additional languages. */
+    /**
+     * CMAS Message Identifier for Extreme alerts, Urgency=Expected, Certainty=Likely
+     * for additional languages.
+     */
     public static final int MESSAGE_ID_CMAS_ALERT_EXTREME_EXPECTED_LIKELY_LANGUAGE
             = 0x1123; // 4387
 
-    /** CMAS Message Identifier for Severe alerts, Urgency=Immediate, Certainty=Observed
-     *  for additional languages. */
+    /**
+     * CMAS Message Identifier for Severe alerts, Urgency=Immediate, Certainty=Observed
+     * for additional languages.
+     */
     public static final int MESSAGE_ID_CMAS_ALERT_SEVERE_IMMEDIATE_OBSERVED_LANGUAGE
             = 0x1124; // 4388
 
-    /** CMAS Message Identifier for Severe alerts, Urgency=Immediate, Certainty=Likely
-     *  for additional languages.*/
+    /**
+     * CMAS Message Identifier for Severe alerts, Urgency=Immediate, Certainty=Likely
+     * for additional languages.
+     */
     public static final int MESSAGE_ID_CMAS_ALERT_SEVERE_IMMEDIATE_LIKELY_LANGUAGE
             = 0x1125; // 4389
 
-    /** CMAS Message Identifier for Severe alerts, Urgency=Expected, Certainty=Observed
-     *  for additional languages. */
+    /**
+     * CMAS Message Identifier for Severe alerts, Urgency=Expected, Certainty=Observed
+     * for additional languages.
+     */
     public static final int MESSAGE_ID_CMAS_ALERT_SEVERE_EXPECTED_OBSERVED_LANGUAGE
             = 0x1126; // 4390
 
-    /** CMAS Message Identifier for Severe alerts, Urgency=Expected, Certainty=Likely
-     *  for additional languages.*/
+    /**
+     * CMAS Message Identifier for Severe alerts, Urgency=Expected, Certainty=Likely
+     * for additional languages.
+     */
     public static final int MESSAGE_ID_CMAS_ALERT_SEVERE_EXPECTED_LIKELY_LANGUAGE
             = 0x1127; // 4391
 
-    /** CMAS Message Identifier for Child Abduction Emergency (Amber Alert)
-     *  for additional languages. */
+    /**
+     * CMAS Message Identifier for Child Abduction Emergency (Amber Alert)
+     * for additional languages.
+     */
     public static final int MESSAGE_ID_CMAS_ALERT_CHILD_ABDUCTION_EMERGENCY_LANGUAGE
             = 0x1128; // 4392
 
-    /** CMAS Message Identifier for the Required Monthly Test
-     *  for additional languages. */
+    /** CMAS Message Identifier for the Required Monthly Test  for additional languages. */
     public static final int MESSAGE_ID_CMAS_ALERT_REQUIRED_MONTHLY_TEST_LANGUAGE
             = 0x1129; // 4393
 
-    /** CMAS Message Identifier for CMAS Exercise
-     *  for additional languages. */
+    /** CMAS Message Identifier for CMAS Exercise for additional languages. */
     public static final int MESSAGE_ID_CMAS_ALERT_EXERCISE_LANGUAGE
             = 0x112A; // 4394
 
-    /** CMAS Message Identifier for operator defined use
-     *  for additional languages. */
+    /** CMAS Message Identifier for operator defined use for additional languages. */
     public static final int MESSAGE_ID_CMAS_ALERT_OPERATOR_DEFINED_USE_LANGUAGE
             = 0x112B; // 4395
 
+    /** CMAS Message Identifier for CMAS Public Safety Alerts. */
+    public static final int MESSAGE_ID_CMAS_ALERT_PUBLIC_SAFETY
+            = 0x112C; // 4396
+
+    /** CMAS Message Identifier for CMAS Public Safety Alerts for additional languages. */
+    public static final int MESSAGE_ID_CMAS_ALERT_PUBLIC_SAFETY_LANGUAGE
+            = 0x112D; // 4397
+
+    /** CMAS Message Identifier for CMAS State/Local Test. */
+    public static final int MESSAGE_ID_CMAS_ALERT_STATE_LOCAL_TEST
+            = 0x112E; // 4398
+
+    /** CMAS Message Identifier for CMAS State/Local Test for additional languages. */
+    public static final int MESSAGE_ID_CMAS_ALERT_STATE_LOCAL_TEST_LANGUAGE
+            = 0x112F; // 4399
+
     /** End of CMAS Message Identifier range (including future extensions). */
     public static final int MESSAGE_ID_CMAS_LAST_IDENTIFIER
             = 0x112F; // 4399
diff --git a/test-mock/api/system-current.txt b/test-mock/api/system-current.txt
index 20401a5..3bd3d68 100644
--- a/test-mock/api/system-current.txt
+++ b/test-mock/api/system-current.txt
@@ -11,6 +11,7 @@
 
   public deprecated class MockPackageManager extends android.content.pm.PackageManager {
     method public void addOnPermissionsChangeListener(android.content.pm.PackageManager.OnPermissionsChangedListener);
+    method public boolean arePermissionsIndividuallyControlled();
     method public java.util.List<android.content.IntentFilter> getAllIntentFilters(java.lang.String);
     method public java.lang.String getDefaultBrowserPackageNameAsUser(int);
     method public java.util.List<android.content.pm.PackageInfo> getInstalledPackagesAsUser(int, int);
diff --git a/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java b/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java
index e509d2d..fd20f4a 100644
--- a/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java
+++ b/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java
@@ -154,6 +154,8 @@
             stdout.append(new String(buf, 0, bytesRead));
         }
         fis.close();
+        Log.i(TAG, "stdout");
+        Log.i(TAG, stdout.toString());
         return stdout.toString();
     }
 
@@ -202,7 +204,10 @@
 
     // TODO(aeubanks): figure out how to get scheduled bg-dexopt to run
     private static void runBackgroundDexOpt() throws IOException {
-        runShellCommand("cmd package bg-dexopt-job " + PACKAGE_NAME);
+        String result = runShellCommand("cmd package bg-dexopt-job " + PACKAGE_NAME);
+        if (!result.trim().equals("Success")) {
+            throw new IllegalStateException("Expected command success, received >" + result + "<");
+        }
     }
 
     // Set the time ahead of the last use time of the test app in days.
diff --git a/tests/SystemMemoryTest/README.txt b/tests/SystemMemoryTest/README.txt
index de5042c..8ffca15 100644
--- a/tests/SystemMemoryTest/README.txt
+++ b/tests/SystemMemoryTest/README.txt
@@ -13,8 +13,7 @@
 
 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
+  atest -v 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/host/src/com/android/tests/sysmem/host/Metrics.java b/tests/SystemMemoryTest/host/src/com/android/tests/sysmem/host/Metrics.java
index 7de092a..616983e 100644
--- a/tests/SystemMemoryTest/host/src/com/android/tests/sysmem/host/Metrics.java
+++ b/tests/SystemMemoryTest/host/src/com/android/tests/sysmem/host/Metrics.java
@@ -66,6 +66,18 @@
     }
 
     /**
+     * Writes the given <code>text</code> to a log with the given label.
+     */
+    private void logText(String label, String text) throws IOException {
+      File file = File.createTempFile(label, "txt");
+      PrintStream ps = new PrintStream(file);
+      ps.print(text);
+      try (FileInputStreamSource dataStream = new FileInputStreamSource(file)) {
+        logs.addTestLog(label, LogDataType.TEXT, dataStream);
+      }
+    }
+
+    /**
      * Returns the pid for the process with the given name.
      */
     private int getPidForProcess(String name)
@@ -111,13 +123,7 @@
 
         // 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);
-        }
+        logText(label + ".system_server.showmap", showmap);
 
         // Extract VSS, PSS and RSS from the showmap and output them as metrics.
         // The last lines of the showmap output looks something like:
@@ -140,6 +146,11 @@
             throw new MetricsException("unexpected showmap format", e);
         }
 
+        // Run debuggerd -j to get GC stats for system server and add it as a
+        // test log
+        String debuggerd = device.executeShellCommand("debuggerd -j " + pid);
+        logText(label + ".system_server.debuggerd", debuggerd);
+
         // TODO: Experiment with other additional metrics.
 
         // TODO: Consider launching an instrumentation to collect metrics from
diff --git a/tests/TtsTests/src/com/android/speech/tts/TextToSpeechTests.java b/tests/TtsTests/src/com/android/speech/tts/TextToSpeechTests.java
index 918873b..d9bb7db 100644
--- a/tests/TtsTests/src/com/android/speech/tts/TextToSpeechTests.java
+++ b/tests/TtsTests/src/com/android/speech/tts/TextToSpeechTests.java
@@ -28,6 +28,7 @@
 import org.mockito.invocation.InvocationOnMock;
 import org.mockito.stubbing.Answer;
 import org.mockito.stubbing.Stubber;
+import org.mockito.quality.Strictness;
 import junit.framework.Assert;
 
 import java.util.Locale;
@@ -210,12 +211,16 @@
     }
 
     public static abstract class CountDownBehaviour extends StubberImpl {
+        public CountDownBehaviour(Strictness strictness) {
+            super(strictness);
+        }
+
         /** Used to mock methods that return a result. */
         public abstract Stubber andReturn(Object result);
     }
 
     public static CountDownBehaviour doCountDown(final CountDownLatch latch) {
-        return new CountDownBehaviour() {
+        return new CountDownBehaviour(Strictness.WARN) {
             @Override
             public <T> T when(T mock) {
                 return Mockito.doAnswer(new Answer<Void>() {
@@ -229,7 +234,7 @@
 
             @Override
             public Stubber andReturn(final Object result) {
-                return new StubberImpl() {
+                return new StubberImpl(Strictness.WARN) {
                     @Override
                     public <T> T when(T mock) {
                         return Mockito.doAnswer(new Answer<Object>() {
diff --git a/tests/net/java/android/net/dhcp/DhcpLeaseRepositoryTest.java b/tests/net/java/android/net/dhcp/DhcpLeaseRepositoryTest.java
index 590bd67..7f8e7b5 100644
--- a/tests/net/java/android/net/dhcp/DhcpLeaseRepositoryTest.java
+++ b/tests/net/java/android/net/dhcp/DhcpLeaseRepositoryTest.java
@@ -32,6 +32,7 @@
 import static java.net.InetAddress.parseNumericAddress;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.net.IpPrefix;
 import android.net.MacAddress;
 import android.net.util.SharedLog;
@@ -107,7 +108,7 @@
             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);
+                    INET4_ANY /* relayAddr */, INETADDR_UNSPEC /* reqAddr */, hostname);
 
             assertNotNull(lease);
             assertEquals(newMac, lease.getHwAddr());
@@ -115,7 +116,7 @@
             assertTrue(format("Duplicate address allocated: %s in %s", lease.getNetAddr(), addrs),
                     addrs.add(lease.getNetAddr()));
 
-            mRepo.requestLease(null, newMac, null, lease.getNetAddr(), true, hostname);
+            requestLeaseSelecting(newMac, lease.getNetAddr(), hostname);
         }
     }
 
@@ -129,7 +130,7 @@
 
         try {
             mRepo.getOffer(null, TEST_MAC_2,
-                    null /* relayAddr */, null /* reqAddr */, HOSTNAME_NONE);
+                    INET4_ANY /* relayAddr */, INETADDR_UNSPEC /* reqAddr */, HOSTNAME_NONE);
             fail("Should be out of addresses");
         } catch (DhcpLeaseRepository.OutOfAddressesException e) {
             // Expected
@@ -145,8 +146,7 @@
         // 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);
+        final DhcpLease reqAddrIn28Lease = requestLeaseSelecting(TEST_MAC_1, reqAddrIn28);
         mRepo.markLeaseDeclined(declinedAddrIn28);
         mRepo.markLeaseDeclined(declinedFirstAddrIn28);
 
@@ -154,14 +154,12 @@
         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);
+        final DhcpLease reqAddrIn22Lease = requestLeaseSelecting(TEST_MAC_3, reqAddrIn22);
         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);
+        final DhcpLease reservedAddrLease = requestLeaseSelecting(TEST_MAC_2, reservedAddr);
 
         // Update from /22 to /28 and add another reserved address
         Set<Inet4Address> newReserved = new HashSet<>(TEST_EXCL_SET);
@@ -183,11 +181,11 @@
     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);
+                    INET4_ANY /* 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);
+                    INET4_ANY /* relayAddr */, INETADDR_UNSPEC /* reqAddr */, HOSTNAME_NONE);
             assertEquals(lease, newLease);
         }
     }
@@ -198,17 +196,16 @@
         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);
+                INET4_ANY /* relayAddr */, INETADDR_UNSPEC /* reqAddr */, 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);
+        requestLeaseSelecting(TEST_MAC_1, TEST_INETADDR_1, TEST_HOSTNAME_1);
 
         DhcpLease offer = mRepo.getOffer(CLIENTID_UNSPEC, TEST_MAC_1,
-                INETADDR_UNSPEC, INETADDR_UNSPEC, HOSTNAME_NONE);
+                INET4_ANY /* relayAddr */, INETADDR_UNSPEC /* reqAddr */, HOSTNAME_NONE);
         assertEquals(TEST_INETADDR_1, offer.getNetAddr());
         assertEquals(TEST_HOSTNAME_1, offer.getHostname());
     }
@@ -216,12 +213,12 @@
     @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);
+        mRepo.requestLease(clientId, TEST_MAC_1, INET4_ANY /* clientAddr */,
+                INET4_ANY /* relayAddr */, TEST_INETADDR_1 /* reqAddr */, false, TEST_HOSTNAME_1);
 
         // Different MAC, but same clientId
         DhcpLease offer = mRepo.getOffer(clientId, TEST_MAC_2,
-                INETADDR_UNSPEC, INETADDR_UNSPEC, HOSTNAME_NONE);
+                INET4_ANY /* relayAddr */, INETADDR_UNSPEC /* reqAddr */, HOSTNAME_NONE);
         assertEquals(TEST_INETADDR_1, offer.getNetAddr());
         assertEquals(TEST_HOSTNAME_1, offer.getHostname());
     }
@@ -230,12 +227,12 @@
     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);
+        mRepo.requestLease(clientId1, TEST_MAC_1, INET4_ANY /* clientAddr */,
+                INET4_ANY /* relayAddr */, TEST_INETADDR_1 /* reqAddr */, false, TEST_HOSTNAME_1);
 
         // Same MAC, different client ID
         DhcpLease offer = mRepo.getOffer(clientId2, TEST_MAC_1,
-                INETADDR_UNSPEC, INETADDR_UNSPEC, HOSTNAME_NONE);
+                INET4_ANY /* relayAddr */, INETADDR_UNSPEC /* reqAddr */, HOSTNAME_NONE);
         // Obtains a different address
         assertNotEquals(TEST_INETADDR_1, offer.getNetAddr());
         assertEquals(HOSTNAME_NONE, offer.getHostname());
@@ -244,58 +241,57 @@
 
     @Test
     public void testGetOffer_RequestedAddress() throws Exception {
-        DhcpLease offer = mRepo.getOffer(CLIENTID_UNSPEC, TEST_MAC_1, INET4_ANY,
-                TEST_INETADDR_1, TEST_HOSTNAME_1);
+        DhcpLease offer = mRepo.getOffer(CLIENTID_UNSPEC, TEST_MAC_1, INET4_ANY /* relayAddr */,
+                TEST_INETADDR_1 /* reqAddr */, 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);
+        requestLeaseSelecting(TEST_MAC_1, TEST_INETADDR_1);
+        DhcpLease offer = mRepo.getOffer(CLIENTID_UNSPEC, TEST_MAC_2, INET4_ANY /* relayAddr */,
+                TEST_INETADDR_1 /* reqAddr */, 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);
+        DhcpLease offer = mRepo.getOffer(CLIENTID_UNSPEC, TEST_MAC_1, INET4_ANY /* relayAddr */,
+                TEST_RESERVED_ADDR /* reqAddr */, 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);
+        DhcpLease offer = mRepo.getOffer(CLIENTID_UNSPEC, TEST_MAC_1, INET4_ANY /* relayAddr */,
+                invalidAddr /* reqAddr */, 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);
+        DhcpLease offer = mRepo.getOffer(CLIENTID_UNSPEC, TEST_MAC_1, INET4_ANY /* relayAddr */,
+                invalidAddr /* reqAddr */, HOSTNAME_NONE);
         assertNotEquals(invalidAddr, offer.getNetAddr());
     }
 
-    @Test(expected = DhcpLeaseRepository.InvalidAddressException.class)
+    @Test(expected = DhcpLeaseRepository.InvalidSubnetException.class)
     public void testGetOffer_RelayInInvalidSubnet() throws Exception {
-        mRepo.getOffer(CLIENTID_UNSPEC, TEST_MAC_1,
-                parseAddr4("192.168.254.2") /* relayAddr */, INETADDR_UNSPEC, HOSTNAME_NONE);
+        mRepo.getOffer(CLIENTID_UNSPEC, TEST_MAC_1, parseAddr4("192.168.254.2") /* relayAddr */,
+                INETADDR_UNSPEC /* reqAddr */, 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);
+        final DhcpLease lease1 = requestLeaseSelecting(TEST_MAC_1, TEST_INETADDR_1,
+                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);
+        final DhcpLease lease2 = requestLeaseSelecting(TEST_MAC_1, TEST_INETADDR_2,
+                TEST_HOSTNAME_2);
 
         assertEquals(TEST_INETADDR_1, lease1.getNetAddr());
         assertEquals(TEST_HOSTNAME_1, lease1.getHostname());
@@ -304,43 +300,43 @@
         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);
+        final DhcpLease lease3 = requestLeaseSelecting(TEST_MAC_2, TEST_INETADDR_1, 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);
+        requestLeaseSelecting(TEST_MAC_1, parseAddr4("192.168.254.5"));
     }
 
     @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);
+        requestLeaseSelecting(TEST_MAC_1, TEST_INETADDR_1);
+        requestLeaseSelecting(TEST_MAC_2, TEST_INETADDR_1);
     }
 
     @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);
+        requestLeaseSelecting(TEST_MAC_1, TEST_RESERVED_ADDR);
+    }
+
+    @Test(expected = DhcpLeaseRepository.InvalidSubnetException.class)
+    public void testRequestLease_SelectingRelayInInvalidSubnet() throws  Exception {
+        mRepo.requestLease(CLIENTID_UNSPEC, TEST_MAC_1, INET4_ANY /* clientAddr */,
+                parseAddr4("192.168.128.1") /* relayAddr */, TEST_INETADDR_1 /* reqAddr */,
+                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);
+        requestLeaseSelecting(TEST_MAC_1, TEST_INETADDR_1);
 
         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);
+        final DhcpLease lease = requestLeaseInitReboot(TEST_MAC_1, TEST_INETADDR_1);
         assertEquals(TEST_INETADDR_1, lease.getNetAddr());
         assertEquals(newTime + TEST_LEASE_TIME_MS, lease.getExpTime());
     }
@@ -348,18 +344,15 @@
     @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);
+        requestLeaseSelecting(TEST_MAC_1, TEST_INETADDR_1);
         // init-reboot with different requested address
-        mRepo.requestLease(
-                CLIENTID_UNSPEC, TEST_MAC_1, INET4_ANY, TEST_INETADDR_2, false, HOSTNAME_NONE);
+        requestLeaseInitReboot(TEST_MAC_1, TEST_INETADDR_2);
     }
 
     @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);
+        final DhcpLease lease = requestLeaseInitReboot(TEST_MAC_1, TEST_INETADDR_2);
         // 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)
@@ -368,22 +361,17 @@
 
     @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);
+        requestLeaseInitReboot(TEST_MAC_1, parseAddr4("192.168.254.2"));
     }
 
     @Test
     public void testRequestLease_Renewing() throws Exception {
-        mRepo.requestLease(CLIENTID_UNSPEC, TEST_MAC_1,
-                INET4_ANY /* clientAddr */, TEST_INETADDR_1 /* reqAddr */, true, HOSTNAME_NONE);
+        requestLeaseSelecting(TEST_MAC_1, TEST_INETADDR_1);
 
         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);
+        final DhcpLease lease = requestLeaseRenewing(TEST_MAC_1, TEST_INETADDR_1);
 
         assertEquals(TEST_INETADDR_1, lease.getNetAddr());
         assertEquals(newTime + TEST_LEASE_TIME_MS, lease.getExpTime());
@@ -393,9 +381,7 @@
     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);
+        final DhcpLease lease = requestLeaseRenewing(TEST_MAC_1, TEST_INETADDR_1);
         // Allows renewing an unknown address if available
         assertEquals(TEST_INETADDR_1, lease.getNetAddr());
         assertEquals(newTime + TEST_LEASE_TIME_MS, lease.getExpTime());
@@ -403,31 +389,24 @@
 
     @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);
+        requestLeaseSelecting(TEST_MAC_2, TEST_INETADDR_1);
+        requestLeaseRenewing(TEST_MAC_1, TEST_INETADDR_1);
     }
 
     @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);
+        requestLeaseRenewing(TEST_MAC_1, parseAddr4("192.168.254.2"));
     }
 
     @Test
     public void testReleaseLease() throws Exception {
-        DhcpLease lease1 = mRepo.requestLease(CLIENTID_UNSPEC, TEST_MAC_1, INET4_ANY,
-                TEST_INETADDR_1, true /* sidSet */, HOSTNAME_NONE);
+        final DhcpLease lease1 = requestLeaseSelecting(TEST_MAC_1, TEST_INETADDR_1);
 
         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);
-
+        final DhcpLease lease2 = requestLeaseSelecting(TEST_MAC_2, TEST_INETADDR_1);
         assertEquals(TEST_INETADDR_1, lease2.getNetAddr());
     }
 
@@ -440,15 +419,14 @@
     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);
+                    INET4_ANY /* relayAddr */, INETADDR_UNSPEC /* reqAddr */, HOSTNAME_NONE);
+
+            requestLeaseSelecting(mac, lease.getNetAddr());
             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);
+                    INET4_ANY /* relayAddr */, INETADDR_UNSPEC /* reqAddr */, HOSTNAME_NONE);
             assertEquals(lease.getNetAddr(), newLease.getNetAddr());
         }
     }
@@ -456,13 +434,13 @@
     @Test
     public void testMarkLeaseDeclined() throws Exception {
         final DhcpLease lease = mRepo.getOffer(CLIENTID_UNSPEC, TEST_MAC_1,
-                INETADDR_UNSPEC /* relayAddr */, INETADDR_UNSPEC /* reqAddr */, HOSTNAME_NONE);
+                INET4_ANY /* 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);
+                INET4_ANY /* relayAddr */, INETADDR_UNSPEC /* reqAddr */, HOSTNAME_NONE);
         assertNotEquals(lease.getNetAddr(), newLease.getNetAddr());
     }
 
@@ -475,22 +453,20 @@
         mRepo.markLeaseDeclined(TEST_INETADDR_2);
 
         // /28 should have 16 addresses, 14 w/o the first/last, 11 w/o excluded addresses
-        requestAddresses((byte)9);
+        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);
+                INET4_ANY /* relayAddr */, INETADDR_UNSPEC /* reqAddr */, TEST_HOSTNAME_1);
+        requestLeaseSelecting(TEST_MAC_1, firstLease.getNetAddr());
 
         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);
+                INET4_ANY /* relayAddr */, INETADDR_UNSPEC /* reqAddr */, TEST_HOSTNAME_2);
+        requestLeaseSelecting(TEST_MAC_2, secondLease.getNetAddr());
 
         // Now out of addresses
         try {
-            mRepo.getOffer(CLIENTID_UNSPEC, TEST_MAC_3, INETADDR_UNSPEC /* relayAddr */,
+            mRepo.getOffer(CLIENTID_UNSPEC, TEST_MAC_3, INET4_ANY /* relayAddr */,
                     INETADDR_UNSPEC /* reqAddr */, HOSTNAME_NONE);
             fail("Repository should be out of addresses and throw");
         } catch (DhcpLeaseRepository.OutOfAddressesException e) { /* expected */ }
@@ -501,6 +477,50 @@
         assertEquals(TEST_HOSTNAME_2, secondLease.getHostname());
     }
 
+    private DhcpLease requestLease(@NonNull MacAddress macAddr, @NonNull Inet4Address clientAddr,
+            @Nullable Inet4Address reqAddr, @Nullable String hostname, boolean sidSet)
+            throws DhcpLeaseRepository.DhcpLeaseException {
+        return mRepo.requestLease(CLIENTID_UNSPEC, macAddr, clientAddr, INET4_ANY /* relayAddr */,
+                reqAddr, sidSet, hostname);
+    }
+
+    /**
+     * Request a lease simulating a client in the SELECTING state.
+     */
+    private DhcpLease requestLeaseSelecting(@NonNull MacAddress macAddr,
+            @NonNull Inet4Address reqAddr, @Nullable String hostname)
+            throws DhcpLeaseRepository.DhcpLeaseException {
+        return requestLease(macAddr, INET4_ANY /* clientAddr */, reqAddr, hostname,
+                true /* sidSet */);
+    }
+
+    /**
+     * Request a lease simulating a client in the SELECTING state.
+     */
+    private DhcpLease requestLeaseSelecting(@NonNull MacAddress macAddr,
+            @NonNull Inet4Address reqAddr) throws DhcpLeaseRepository.DhcpLeaseException {
+        return requestLeaseSelecting(macAddr, reqAddr, HOSTNAME_NONE);
+    }
+
+    /**
+     * Request a lease simulating a client in the INIT-REBOOT state.
+     */
+    private DhcpLease requestLeaseInitReboot(@NonNull MacAddress macAddr,
+            @NonNull Inet4Address reqAddr) throws DhcpLeaseRepository.DhcpLeaseException {
+        return requestLease(macAddr, INET4_ANY /* clientAddr */, reqAddr, HOSTNAME_NONE,
+                false /* sidSet */);
+    }
+
+    /**
+     * Request a lease simulating a client in the RENEWING state.
+     */
+    private DhcpLease requestLeaseRenewing(@NonNull MacAddress macAddr,
+            @NonNull Inet4Address clientAddr) throws DhcpLeaseRepository.DhcpLeaseException {
+        // Renewing: clientAddr filled in, no reqAddr
+        return requestLease(macAddr, clientAddr, INETADDR_UNSPEC /* reqAddr */, HOSTNAME_NONE,
+                true /* sidSet */);
+    }
+
     private void assertNoLease(DhcpLease lease) {
         assertFalse("Leases contain " + lease, mRepo.getCommittedLeases().contains(lease));
     }
diff --git a/tests/net/java/android/net/dhcp/DhcpServerTest.java b/tests/net/java/android/net/dhcp/DhcpServerTest.java
index 66db5a8..45a50d9 100644
--- a/tests/net/java/android/net/dhcp/DhcpServerTest.java
+++ b/tests/net/java/android/net/dhcp/DhcpServerTest.java
@@ -216,8 +216,8 @@
     @Test
     public void testRequest_Selecting_Ack() throws Exception {
         when(mRepository.requestLease(isNull() /* clientId */, eq(TEST_CLIENT_MAC),
-                eq(INADDR_ANY) /* clientAddr */, eq(TEST_CLIENT_ADDR) /* reqAddr */,
-                eq(true) /* sidSet */, isNull() /* hostname */))
+                eq(INADDR_ANY) /* clientAddr */, eq(INADDR_ANY) /* relayAddr */,
+                eq(TEST_CLIENT_ADDR) /* reqAddr */, eq(true) /* sidSet */, isNull() /* hostname */))
                 .thenReturn(TEST_LEASE);
 
         final DhcpRequestPacket request = makeRequestSelectingPacket();
@@ -231,8 +231,8 @@
     @Test
     public void testRequest_Selecting_Nak() throws Exception {
         when(mRepository.requestLease(isNull(), eq(TEST_CLIENT_MAC),
-                eq(INADDR_ANY) /* clientAddr */, eq(TEST_CLIENT_ADDR) /* reqAddr */,
-                eq(true) /* sidSet */, isNull() /* hostname */))
+                eq(INADDR_ANY) /* clientAddr */, eq(INADDR_ANY) /* relayAddr */,
+                eq(TEST_CLIENT_ADDR) /* reqAddr */, eq(true) /* sidSet */, isNull() /* hostname */))
                 .thenThrow(new InvalidAddressException("Test error"));
 
         final DhcpRequestPacket request = makeRequestSelectingPacket();
@@ -248,7 +248,8 @@
         final DhcpRequestPacket request = makeRequestSelectingPacket();
         mServer.processPacket(request, 50000);
 
-        verify(mRepository, never()).requestLease(any(), any(), any(), any(), anyBoolean(), any());
+        verify(mRepository, never())
+                .requestLease(any(), any(), any(), any(), any(), anyBoolean(), any());
         verify(mDeps, never()).sendPacket(any(), any(), any());
     }
 
diff --git a/tests/net/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachineTest.java b/tests/net/java/android/net/ip/IpServerTest.java
similarity index 71%
rename from tests/net/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachineTest.java
rename to tests/net/java/android/net/ip/IpServerTest.java
index 5934653..cff0b54 100644
--- a/tests/net/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachineTest.java
+++ b/tests/net/java/android/net/ip/IpServerTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server.connectivity.tethering;
+package android.net.ip;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -37,9 +37,9 @@
 import static android.net.ConnectivityManager.TETHERING_BLUETOOTH;
 import static android.net.ConnectivityManager.TETHERING_USB;
 import static android.net.ConnectivityManager.TETHERING_WIFI;
-import static com.android.server.connectivity.tethering.IControlsTethering.STATE_AVAILABLE;
-import static com.android.server.connectivity.tethering.IControlsTethering.STATE_TETHERED;
-import static com.android.server.connectivity.tethering.IControlsTethering.STATE_UNAVAILABLE;
+import static android.net.ip.IpServer.STATE_AVAILABLE;
+import static android.net.ip.IpServer.STATE_TETHERED;
+import static android.net.ip.IpServer.STATE_UNAVAILABLE;
 
 import android.net.INetworkStatsService;
 import android.net.InterfaceConfiguration;
@@ -50,7 +50,6 @@
 import android.net.RouteInfo;
 import android.net.dhcp.DhcpServer;
 import android.net.dhcp.DhcpServingParams;
-import android.net.ip.RouterAdvertisementDaemon;
 import android.net.util.InterfaceParams;
 import android.net.util.InterfaceSet;
 import android.net.util.SharedLog;
@@ -74,7 +73,7 @@
 
 @RunWith(AndroidJUnit4.class)
 @SmallTest
-public class TetherInterfaceStateMachineTest {
+public class IpServerTest {
     private static final String IFACE_NAME = "testnet1";
     private static final String UPSTREAM_IFACE = "upstream0";
     private static final String UPSTREAM_IFACE2 = "upstream1";
@@ -85,39 +84,38 @@
 
     @Mock private INetworkManagementService mNMService;
     @Mock private INetworkStatsService mStatsService;
-    @Mock private IControlsTethering mTetherHelper;
+    @Mock private IpServer.Callback mCallback;
     @Mock private InterfaceConfiguration mInterfaceConfiguration;
     @Mock private SharedLog mSharedLog;
     @Mock private DhcpServer mDhcpServer;
     @Mock private RouterAdvertisementDaemon mRaDaemon;
-    @Mock private TetheringDependencies mTetheringDependencies;
+    @Mock private IpServer.Dependencies mDependencies;
 
     @Captor private ArgumentCaptor<DhcpServingParams> mDhcpParamsCaptor;
 
     private final TestLooper mLooper = new TestLooper();
     private final ArgumentCaptor<LinkProperties> mLinkPropertiesCaptor =
             ArgumentCaptor.forClass(LinkProperties.class);
-    private TetherInterfaceStateMachine mTestedSm;
+    private IpServer mIpServer;
 
     private void initStateMachine(int interfaceType) throws Exception {
         initStateMachine(interfaceType, false /* usingLegacyDhcp */);
     }
 
     private void initStateMachine(int interfaceType, boolean usingLegacyDhcp) throws Exception {
-        mTestedSm = new TetherInterfaceStateMachine(
+        mIpServer = new IpServer(
                 IFACE_NAME, mLooper.getLooper(), interfaceType, mSharedLog,
-                mNMService, mStatsService, mTetherHelper, usingLegacyDhcp,
-                mTetheringDependencies);
-        mTestedSm.start();
+                mNMService, mStatsService, mCallback, usingLegacyDhcp, mDependencies);
+        mIpServer.start();
         // Starting the state machine always puts us in a consistent state and notifies
         // the rest of the world that we've changed from an unknown to available state.
         mLooper.dispatchAll();
-        reset(mNMService, mStatsService, mTetherHelper);
+        reset(mNMService, mStatsService, mCallback);
         when(mNMService.getInterfaceConfig(IFACE_NAME)).thenReturn(mInterfaceConfiguration);
-        when(mTetheringDependencies.makeDhcpServer(
+        when(mDependencies.makeDhcpServer(
                 any(), any(), mDhcpParamsCaptor.capture(), any())).thenReturn(mDhcpServer);
-        when(mTetheringDependencies.getRouterAdvertisementDaemon(any())).thenReturn(mRaDaemon);
-        when(mTetheringDependencies.getInterfaceParams(IFACE_NAME)).thenReturn(TEST_IFACE_PARAMS);
+        when(mDependencies.getRouterAdvertisementDaemon(any())).thenReturn(mRaDaemon);
+        when(mDependencies.getInterfaceParams(IFACE_NAME)).thenReturn(TEST_IFACE_PARAMS);
 
         when(mRaDaemon.start()).thenReturn(true);
     }
@@ -130,11 +128,11 @@
     private void initTetheredStateMachine(int interfaceType, String upstreamIface,
             boolean usingLegacyDhcp) throws Exception {
         initStateMachine(interfaceType, usingLegacyDhcp);
-        dispatchCommand(TetherInterfaceStateMachine.CMD_TETHER_REQUESTED, STATE_TETHERED);
+        dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_TETHERED);
         if (upstreamIface != null) {
             dispatchTetherConnectionChanged(upstreamIface);
         }
-        reset(mNMService, mStatsService, mTetherHelper);
+        reset(mNMService, mStatsService, mCallback);
         when(mNMService.getInterfaceConfig(IFACE_NAME)).thenReturn(mInterfaceConfiguration);
     }
 
@@ -145,34 +143,34 @@
 
     @Test
     public void startsOutAvailable() {
-        mTestedSm = new TetherInterfaceStateMachine(IFACE_NAME, mLooper.getLooper(),
-                TETHERING_BLUETOOTH, mSharedLog, mNMService, mStatsService, mTetherHelper,
-                false /* usingLegacyDhcp */, mTetheringDependencies);
-        mTestedSm.start();
+        mIpServer = new IpServer(IFACE_NAME, mLooper.getLooper(),
+                TETHERING_BLUETOOTH, mSharedLog, mNMService, mStatsService, mCallback,
+                false /* usingLegacyDhcp */, mDependencies);
+        mIpServer.start();
         mLooper.dispatchAll();
-        verify(mTetherHelper).updateInterfaceState(
-                mTestedSm, STATE_AVAILABLE, TETHER_ERROR_NO_ERROR);
-        verify(mTetherHelper).updateLinkProperties(eq(mTestedSm), any(LinkProperties.class));
-        verifyNoMoreInteractions(mTetherHelper, mNMService, mStatsService);
+        verify(mCallback).updateInterfaceState(
+                mIpServer, STATE_AVAILABLE, TETHER_ERROR_NO_ERROR);
+        verify(mCallback).updateLinkProperties(eq(mIpServer), any(LinkProperties.class));
+        verifyNoMoreInteractions(mCallback, mNMService, mStatsService);
     }
 
     @Test
     public void shouldDoNothingUntilRequested() throws Exception {
         initStateMachine(TETHERING_BLUETOOTH);
         final int [] NOOP_COMMANDS = {
-            TetherInterfaceStateMachine.CMD_TETHER_UNREQUESTED,
-            TetherInterfaceStateMachine.CMD_IP_FORWARDING_ENABLE_ERROR,
-            TetherInterfaceStateMachine.CMD_IP_FORWARDING_DISABLE_ERROR,
-            TetherInterfaceStateMachine.CMD_START_TETHERING_ERROR,
-            TetherInterfaceStateMachine.CMD_STOP_TETHERING_ERROR,
-            TetherInterfaceStateMachine.CMD_SET_DNS_FORWARDERS_ERROR,
-            TetherInterfaceStateMachine.CMD_TETHER_CONNECTION_CHANGED
+            IpServer.CMD_TETHER_UNREQUESTED,
+            IpServer.CMD_IP_FORWARDING_ENABLE_ERROR,
+            IpServer.CMD_IP_FORWARDING_DISABLE_ERROR,
+            IpServer.CMD_START_TETHERING_ERROR,
+            IpServer.CMD_STOP_TETHERING_ERROR,
+            IpServer.CMD_SET_DNS_FORWARDERS_ERROR,
+            IpServer.CMD_TETHER_CONNECTION_CHANGED
         };
         for (int command : NOOP_COMMANDS) {
             // None of these commands should trigger us to request action from
             // the rest of the system.
             dispatchCommand(command);
-            verifyNoMoreInteractions(mNMService, mStatsService, mTetherHelper);
+            verifyNoMoreInteractions(mNMService, mStatsService, mCallback);
         }
     }
 
@@ -180,57 +178,57 @@
     public void handlesImmediateInterfaceDown() throws Exception {
         initStateMachine(TETHERING_BLUETOOTH);
 
-        dispatchCommand(TetherInterfaceStateMachine.CMD_INTERFACE_DOWN);
-        verify(mTetherHelper).updateInterfaceState(
-                mTestedSm, STATE_UNAVAILABLE, TETHER_ERROR_NO_ERROR);
-        verify(mTetherHelper).updateLinkProperties(eq(mTestedSm), any(LinkProperties.class));
-        verifyNoMoreInteractions(mNMService, mStatsService, mTetherHelper);
+        dispatchCommand(IpServer.CMD_INTERFACE_DOWN);
+        verify(mCallback).updateInterfaceState(
+                mIpServer, STATE_UNAVAILABLE, TETHER_ERROR_NO_ERROR);
+        verify(mCallback).updateLinkProperties(eq(mIpServer), any(LinkProperties.class));
+        verifyNoMoreInteractions(mNMService, mStatsService, mCallback);
     }
 
     @Test
     public void canBeTethered() throws Exception {
         initStateMachine(TETHERING_BLUETOOTH);
 
-        dispatchCommand(TetherInterfaceStateMachine.CMD_TETHER_REQUESTED, STATE_TETHERED);
-        InOrder inOrder = inOrder(mTetherHelper, mNMService);
+        dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_TETHERED);
+        InOrder inOrder = inOrder(mCallback, mNMService);
         inOrder.verify(mNMService).tetherInterface(IFACE_NAME);
-        inOrder.verify(mTetherHelper).updateInterfaceState(
-                mTestedSm, STATE_TETHERED, TETHER_ERROR_NO_ERROR);
-        inOrder.verify(mTetherHelper).updateLinkProperties(
-                eq(mTestedSm), any(LinkProperties.class));
-        verifyNoMoreInteractions(mNMService, mStatsService, mTetherHelper);
+        inOrder.verify(mCallback).updateInterfaceState(
+                mIpServer, STATE_TETHERED, TETHER_ERROR_NO_ERROR);
+        inOrder.verify(mCallback).updateLinkProperties(
+                eq(mIpServer), any(LinkProperties.class));
+        verifyNoMoreInteractions(mNMService, mStatsService, mCallback);
     }
 
     @Test
     public void canUnrequestTethering() throws Exception {
         initTetheredStateMachine(TETHERING_BLUETOOTH, null);
 
-        dispatchCommand(TetherInterfaceStateMachine.CMD_TETHER_UNREQUESTED);
-        InOrder inOrder = inOrder(mNMService, mStatsService, mTetherHelper);
+        dispatchCommand(IpServer.CMD_TETHER_UNREQUESTED);
+        InOrder inOrder = inOrder(mNMService, mStatsService, mCallback);
         inOrder.verify(mNMService).untetherInterface(IFACE_NAME);
         inOrder.verify(mNMService).setInterfaceConfig(eq(IFACE_NAME), any());
-        inOrder.verify(mTetherHelper).updateInterfaceState(
-                mTestedSm, STATE_AVAILABLE, TETHER_ERROR_NO_ERROR);
-        inOrder.verify(mTetherHelper).updateLinkProperties(
-                eq(mTestedSm), any(LinkProperties.class));
-        verifyNoMoreInteractions(mNMService, mStatsService, mTetherHelper);
+        inOrder.verify(mCallback).updateInterfaceState(
+                mIpServer, STATE_AVAILABLE, TETHER_ERROR_NO_ERROR);
+        inOrder.verify(mCallback).updateLinkProperties(
+                eq(mIpServer), any(LinkProperties.class));
+        verifyNoMoreInteractions(mNMService, mStatsService, mCallback);
     }
 
     @Test
     public void canBeTetheredAsUsb() throws Exception {
         initStateMachine(TETHERING_USB);
 
-        dispatchCommand(TetherInterfaceStateMachine.CMD_TETHER_REQUESTED, STATE_TETHERED);
-        InOrder inOrder = inOrder(mTetherHelper, mNMService);
+        dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_TETHERED);
+        InOrder inOrder = inOrder(mCallback, mNMService);
         inOrder.verify(mNMService).getInterfaceConfig(IFACE_NAME);
         inOrder.verify(mNMService).setInterfaceConfig(IFACE_NAME, mInterfaceConfiguration);
         inOrder.verify(mNMService).tetherInterface(IFACE_NAME);
-        inOrder.verify(mTetherHelper).updateInterfaceState(
-                mTestedSm, STATE_TETHERED, TETHER_ERROR_NO_ERROR);
-        inOrder.verify(mTetherHelper).updateLinkProperties(
-                eq(mTestedSm), mLinkPropertiesCaptor.capture());
+        inOrder.verify(mCallback).updateInterfaceState(
+                mIpServer, STATE_TETHERED, TETHER_ERROR_NO_ERROR);
+        inOrder.verify(mCallback).updateLinkProperties(
+                eq(mIpServer), mLinkPropertiesCaptor.capture());
         assertIPv4AddressAndDirectlyConnectedRoute(mLinkPropertiesCaptor.getValue());
-        verifyNoMoreInteractions(mNMService, mStatsService, mTetherHelper);
+        verifyNoMoreInteractions(mNMService, mStatsService, mCallback);
     }
 
     @Test
@@ -243,7 +241,7 @@
         InOrder inOrder = inOrder(mNMService);
         inOrder.verify(mNMService).enableNat(IFACE_NAME, UPSTREAM_IFACE);
         inOrder.verify(mNMService).startInterfaceForwarding(IFACE_NAME, UPSTREAM_IFACE);
-        verifyNoMoreInteractions(mNMService, mStatsService, mTetherHelper);
+        verifyNoMoreInteractions(mNMService, mStatsService, mCallback);
     }
 
     @Test
@@ -257,7 +255,7 @@
         inOrder.verify(mNMService).disableNat(IFACE_NAME, UPSTREAM_IFACE);
         inOrder.verify(mNMService).enableNat(IFACE_NAME, UPSTREAM_IFACE2);
         inOrder.verify(mNMService).startInterfaceForwarding(IFACE_NAME, UPSTREAM_IFACE2);
-        verifyNoMoreInteractions(mNMService, mStatsService, mTetherHelper);
+        verifyNoMoreInteractions(mNMService, mStatsService, mCallback);
     }
 
     @Test
@@ -300,18 +298,18 @@
     public void canUnrequestTetheringWithUpstream() throws Exception {
         initTetheredStateMachine(TETHERING_BLUETOOTH, UPSTREAM_IFACE);
 
-        dispatchCommand(TetherInterfaceStateMachine.CMD_TETHER_UNREQUESTED);
-        InOrder inOrder = inOrder(mNMService, mStatsService, mTetherHelper);
+        dispatchCommand(IpServer.CMD_TETHER_UNREQUESTED);
+        InOrder inOrder = inOrder(mNMService, mStatsService, mCallback);
         inOrder.verify(mStatsService).forceUpdate();
         inOrder.verify(mNMService).stopInterfaceForwarding(IFACE_NAME, UPSTREAM_IFACE);
         inOrder.verify(mNMService).disableNat(IFACE_NAME, UPSTREAM_IFACE);
         inOrder.verify(mNMService).untetherInterface(IFACE_NAME);
         inOrder.verify(mNMService).setInterfaceConfig(eq(IFACE_NAME), any());
-        inOrder.verify(mTetherHelper).updateInterfaceState(
-                mTestedSm, STATE_AVAILABLE, TETHER_ERROR_NO_ERROR);
-        inOrder.verify(mTetherHelper).updateLinkProperties(
-                eq(mTestedSm), any(LinkProperties.class));
-        verifyNoMoreInteractions(mNMService, mStatsService, mTetherHelper);
+        inOrder.verify(mCallback).updateInterfaceState(
+                mIpServer, STATE_AVAILABLE, TETHER_ERROR_NO_ERROR);
+        inOrder.verify(mCallback).updateLinkProperties(
+                eq(mIpServer), any(LinkProperties.class));
+        verifyNoMoreInteractions(mNMService, mStatsService, mCallback);
     }
 
     @Test
@@ -322,15 +320,15 @@
             if (shouldThrow) {
                 doThrow(RemoteException.class).when(mNMService).untetherInterface(IFACE_NAME);
             }
-            dispatchCommand(TetherInterfaceStateMachine.CMD_INTERFACE_DOWN);
-            InOrder usbTeardownOrder = inOrder(mNMService, mInterfaceConfiguration, mTetherHelper);
+            dispatchCommand(IpServer.CMD_INTERFACE_DOWN);
+            InOrder usbTeardownOrder = inOrder(mNMService, mInterfaceConfiguration, mCallback);
             usbTeardownOrder.verify(mInterfaceConfiguration).setInterfaceDown();
             usbTeardownOrder.verify(mNMService).setInterfaceConfig(
                     IFACE_NAME, mInterfaceConfiguration);
-            usbTeardownOrder.verify(mTetherHelper).updateInterfaceState(
-                    mTestedSm, STATE_UNAVAILABLE, TETHER_ERROR_NO_ERROR);
-            usbTeardownOrder.verify(mTetherHelper).updateLinkProperties(
-                    eq(mTestedSm), mLinkPropertiesCaptor.capture());
+            usbTeardownOrder.verify(mCallback).updateInterfaceState(
+                    mIpServer, STATE_UNAVAILABLE, TETHER_ERROR_NO_ERROR);
+            usbTeardownOrder.verify(mCallback).updateLinkProperties(
+                    eq(mIpServer), mLinkPropertiesCaptor.capture());
             assertNoAddressesNorRoutes(mLinkPropertiesCaptor.getValue());
         }
     }
@@ -340,15 +338,15 @@
         initStateMachine(TETHERING_USB);
 
         doThrow(RemoteException.class).when(mNMService).tetherInterface(IFACE_NAME);
-        dispatchCommand(TetherInterfaceStateMachine.CMD_TETHER_REQUESTED, STATE_TETHERED);
-        InOrder usbTeardownOrder = inOrder(mNMService, mInterfaceConfiguration, mTetherHelper);
+        dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_TETHERED);
+        InOrder usbTeardownOrder = inOrder(mNMService, mInterfaceConfiguration, mCallback);
         usbTeardownOrder.verify(mInterfaceConfiguration).setInterfaceDown();
         usbTeardownOrder.verify(mNMService).setInterfaceConfig(
                 IFACE_NAME, mInterfaceConfiguration);
-        usbTeardownOrder.verify(mTetherHelper).updateInterfaceState(
-                mTestedSm, STATE_AVAILABLE, TETHER_ERROR_TETHER_IFACE_ERROR);
-        usbTeardownOrder.verify(mTetherHelper).updateLinkProperties(
-                eq(mTestedSm), mLinkPropertiesCaptor.capture());
+        usbTeardownOrder.verify(mCallback).updateInterfaceState(
+                mIpServer, STATE_AVAILABLE, TETHER_ERROR_TETHER_IFACE_ERROR);
+        usbTeardownOrder.verify(mCallback).updateLinkProperties(
+                eq(mIpServer), mLinkPropertiesCaptor.capture());
         assertNoAddressesNorRoutes(mLinkPropertiesCaptor.getValue());
     }
 
@@ -358,13 +356,13 @@
 
         doThrow(RemoteException.class).when(mNMService).enableNat(anyString(), anyString());
         dispatchTetherConnectionChanged(UPSTREAM_IFACE);
-        InOrder usbTeardownOrder = inOrder(mNMService, mInterfaceConfiguration, mTetherHelper);
+        InOrder usbTeardownOrder = inOrder(mNMService, mInterfaceConfiguration, mCallback);
         usbTeardownOrder.verify(mInterfaceConfiguration).setInterfaceDown();
         usbTeardownOrder.verify(mNMService).setInterfaceConfig(IFACE_NAME, mInterfaceConfiguration);
-        usbTeardownOrder.verify(mTetherHelper).updateInterfaceState(
-                mTestedSm, STATE_AVAILABLE, TETHER_ERROR_ENABLE_NAT_ERROR);
-        usbTeardownOrder.verify(mTetherHelper).updateLinkProperties(
-                eq(mTestedSm), mLinkPropertiesCaptor.capture());
+        usbTeardownOrder.verify(mCallback).updateInterfaceState(
+                mIpServer, STATE_AVAILABLE, TETHER_ERROR_ENABLE_NAT_ERROR);
+        usbTeardownOrder.verify(mCallback).updateLinkProperties(
+                eq(mIpServer), mLinkPropertiesCaptor.capture());
         assertNoAddressesNorRoutes(mLinkPropertiesCaptor.getValue());
     }
 
@@ -372,11 +370,11 @@
     public void ignoresDuplicateUpstreamNotifications() throws Exception {
         initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE);
 
-        verifyNoMoreInteractions(mNMService, mStatsService, mTetherHelper);
+        verifyNoMoreInteractions(mNMService, mStatsService, mCallback);
 
         for (int i = 0; i < 5; i++) {
             dispatchTetherConnectionChanged(UPSTREAM_IFACE);
-            verifyNoMoreInteractions(mNMService, mStatsService, mTetherHelper);
+            verifyNoMoreInteractions(mNMService, mStatsService, mCallback);
         }
     }
 
@@ -401,11 +399,11 @@
         initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE, true /* usingLegacyDhcp */);
         dispatchTetherConnectionChanged(UPSTREAM_IFACE);
 
-        verify(mTetheringDependencies, never()).makeDhcpServer(any(), any(), any(), any());
+        verify(mDependencies, never()).makeDhcpServer(any(), any(), any(), any());
     }
 
     private void assertDhcpStarted(IpPrefix expectedPrefix) {
-        verify(mTetheringDependencies, times(1)).makeDhcpServer(
+        verify(mDependencies, times(1)).makeDhcpServer(
                 eq(mLooper.getLooper()), eq(TEST_IFACE_PARAMS), any(), eq(mSharedLog));
         verify(mDhcpServer, times(1)).start();
         final DhcpServingParams params = mDhcpParamsCaptor.getValue();
@@ -422,21 +420,21 @@
     /**
      * Send a command to the state machine under test, and run the event loop to idle.
      *
-     * @param command One of the TetherInterfaceStateMachine.CMD_* constants.
+     * @param command One of the IpServer.CMD_* constants.
      * @param arg1 An additional argument to pass.
      */
     private void dispatchCommand(int command, int arg1) {
-        mTestedSm.sendMessage(command, arg1);
+        mIpServer.sendMessage(command, arg1);
         mLooper.dispatchAll();
     }
 
     /**
      * Send a command to the state machine under test, and run the event loop to idle.
      *
-     * @param command One of the TetherInterfaceStateMachine.CMD_* constants.
+     * @param command One of the IpServer.CMD_* constants.
      */
     private void dispatchCommand(int command) {
-        mTestedSm.sendMessage(command);
+        mIpServer.sendMessage(command);
         mLooper.dispatchAll();
     }
 
@@ -447,7 +445,7 @@
      * @param upstreamIface String name of upstream interface (or null)
      */
     private void dispatchTetherConnectionChanged(String upstreamIface) {
-        mTestedSm.sendMessage(TetherInterfaceStateMachine.CMD_TETHER_CONNECTION_CHANGED,
+        mIpServer.sendMessage(IpServer.CMD_TETHER_CONNECTION_CHANGED,
                 new InterfaceSet(upstreamIface));
         mLooper.dispatchAll();
     }
diff --git a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java
index 102cb7c..99a5a69 100644
--- a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java
+++ b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java
@@ -41,9 +41,9 @@
 import android.net.NetworkUtils;
 import android.os.Binder;
 import android.os.ParcelFileDescriptor;
-import android.test.mock.MockContext;
 import android.support.test.filters.SmallTest;
 import android.system.Os;
+import android.test.mock.MockContext;
 
 import java.net.Socket;
 import java.util.Arrays;
@@ -121,6 +121,7 @@
     IpSecService.IpSecServiceConfiguration mMockIpSecSrvConfig;
     IpSecService mIpSecService;
     Network fakeNetwork = new Network(0xAB);
+    int mUid = Os.getuid();
 
     private static final IpSecAlgorithm AUTH_ALGO =
             new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, AUTH_KEY, AUTH_KEY.length * 4);
@@ -181,7 +182,7 @@
 
         verify(mMockNetd)
                 .ipSecDeleteSecurityAssociation(
-                        eq(spiResp.resourceId),
+                        eq(mUid),
                         anyString(),
                         anyString(),
                         eq(TEST_SPI),
@@ -189,8 +190,7 @@
                         anyInt());
 
         // Verify quota and RefcountedResource objects cleaned up
-        IpSecService.UserRecord userRecord =
-                mIpSecService.mUserResourceTracker.getUserRecord(Os.getuid());
+        IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid);
         assertEquals(0, userRecord.mSpiQuotaTracker.mCurrent);
         try {
             userRecord.mSpiRecords.getRefcountedResourceOrThrow(spiResp.resourceId);
@@ -209,8 +209,7 @@
                 mIpSecService.allocateSecurityParameterIndex(
                         mDestinationAddr, TEST_SPI, new Binder());
 
-        IpSecService.UserRecord userRecord =
-                mIpSecService.mUserResourceTracker.getUserRecord(Os.getuid());
+        IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid);
         IpSecService.RefcountedResource refcountedRecord =
                 userRecord.mSpiRecords.getRefcountedResourceOrThrow(spiResp.resourceId);
 
@@ -218,7 +217,7 @@
 
         verify(mMockNetd)
                 .ipSecDeleteSecurityAssociation(
-                        eq(spiResp.resourceId),
+                        eq(mUid),
                         anyString(),
                         anyString(),
                         eq(TEST_SPI),
@@ -270,7 +269,7 @@
 
         verify(mMockNetd)
                 .ipSecAddSecurityAssociation(
-                        eq(createTransformResp.resourceId),
+                        eq(mUid),
                         anyInt(),
                         anyString(),
                         anyString(),
@@ -305,7 +304,7 @@
 
         verify(mMockNetd)
                 .ipSecAddSecurityAssociation(
-                        eq(createTransformResp.resourceId),
+                        eq(mUid),
                         anyInt(),
                         anyString(),
                         anyString(),
@@ -361,13 +360,12 @@
 
         IpSecTransformResponse createTransformResp =
                 mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
-        IpSecService.UserRecord userRecord =
-                mIpSecService.mUserResourceTracker.getUserRecord(Os.getuid());
+        IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid);
         assertEquals(1, userRecord.mSpiQuotaTracker.mCurrent);
         mIpSecService.releaseSecurityParameterIndex(ipSecConfig.getSpiResourceId());
         verify(mMockNetd, times(0))
                 .ipSecDeleteSecurityAssociation(
-                        eq(createTransformResp.resourceId),
+                        eq(mUid),
                         anyString(),
                         anyString(),
                         eq(TEST_SPI),
@@ -389,7 +387,7 @@
 
         verify(mMockNetd, times(1))
                 .ipSecDeleteSecurityAssociation(
-                        eq(createTransformResp.resourceId),
+                        eq(mUid),
                         anyString(),
                         anyString(),
                         eq(TEST_SPI),
@@ -397,8 +395,7 @@
                         anyInt());
 
         // Verify quota and RefcountedResource objects cleaned up
-        IpSecService.UserRecord userRecord =
-                mIpSecService.mUserResourceTracker.getUserRecord(Os.getuid());
+        IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid);
         assertEquals(0, userRecord.mTransformQuotaTracker.mCurrent);
         assertEquals(1, userRecord.mSpiQuotaTracker.mCurrent);
 
@@ -433,8 +430,7 @@
         IpSecTransformResponse createTransformResp =
                 mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
 
-        IpSecService.UserRecord userRecord =
-                mIpSecService.mUserResourceTracker.getUserRecord(Os.getuid());
+        IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid);
         IpSecService.RefcountedResource refcountedRecord =
                 userRecord.mTransformRecords.getRefcountedResourceOrThrow(
                         createTransformResp.resourceId);
@@ -443,7 +439,7 @@
 
         verify(mMockNetd)
                 .ipSecDeleteSecurityAssociation(
-                        eq(createTransformResp.resourceId),
+                        eq(mUid),
                         anyString(),
                         anyString(),
                         eq(TEST_SPI),
@@ -477,7 +473,7 @@
         verify(mMockNetd)
                 .ipSecApplyTransportModeTransform(
                         eq(pfd.getFileDescriptor()),
-                        eq(resourceId),
+                        eq(mUid),
                         eq(IpSecManager.DIRECTION_OUT),
                         anyString(),
                         anyString(),
@@ -509,8 +505,7 @@
                 createAndValidateTunnel(mSourceAddr, mDestinationAddr, "blessedPackage");
 
         // Check that we have stored the tracking object, and retrieve it
-        IpSecService.UserRecord userRecord =
-                mIpSecService.mUserResourceTracker.getUserRecord(Os.getuid());
+        IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid);
         IpSecService.RefcountedResource refcountedRecord =
                 userRecord.mTunnelInterfaceRecords.getRefcountedResourceOrThrow(
                         createTunnelResp.resourceId);
@@ -530,8 +525,7 @@
         IpSecTunnelInterfaceResponse createTunnelResp =
                 createAndValidateTunnel(mSourceAddr, mDestinationAddr, "blessedPackage");
 
-        IpSecService.UserRecord userRecord =
-                mIpSecService.mUserResourceTracker.getUserRecord(Os.getuid());
+        IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid);
 
         mIpSecService.deleteTunnelInterface(createTunnelResp.resourceId, "blessedPackage");
 
@@ -551,8 +545,7 @@
         IpSecTunnelInterfaceResponse createTunnelResp =
                 createAndValidateTunnel(mSourceAddr, mDestinationAddr, "blessedPackage");
 
-        IpSecService.UserRecord userRecord =
-                mIpSecService.mUserResourceTracker.getUserRecord(Os.getuid());
+        IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid);
         IpSecService.RefcountedResource refcountedRecord =
                 userRecord.mTunnelInterfaceRecords.getRefcountedResourceOrThrow(
                         createTunnelResp.resourceId);
diff --git a/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java b/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java
index f025f41..4dc63f2 100644
--- a/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java
+++ b/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java
@@ -21,7 +21,9 @@
 import static android.Manifest.permission.CONNECTIVITY_INTERNAL;
 import static android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS;
 import static android.Manifest.permission.NETWORK_STACK;
-import static android.content.pm.ApplicationInfo.FLAG_SYSTEM;
+import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_OEM;
+import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_PRODUCT;
+import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_VENDOR;
 import static android.content.pm.PackageManager.GET_PERMISSIONS;
 
 import static org.junit.Assert.assertFalse;
@@ -34,6 +36,7 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
+import android.os.Build;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
 
@@ -48,6 +51,10 @@
 public class PermissionMonitorTest {
     private static final int MOCK_UID = 10001;
     private static final String[] MOCK_PACKAGE_NAMES = new String[] { "com.foo.bar" };
+    private static final String PARTITION_SYSTEM = "system";
+    private static final String PARTITION_OEM = "oem";
+    private static final String PARTITION_PRODUCT = "product";
+    private static final String PARTITION_VENDOR = "vendor";
 
     @Mock private Context mContext;
     @Mock private PackageManager mPackageManager;
@@ -62,39 +69,53 @@
         mPermissionMonitor = new PermissionMonitor(mContext, null);
     }
 
-    private void expectPermission(String[] permissions, boolean preinstalled) throws Exception {
-        final PackageInfo packageInfo = packageInfoWithPermissions(permissions, preinstalled);
+    private void expectPermission(String[] permissions, String partition,
+            int targetSdkVersion) throws Exception {
+        final PackageInfo packageInfo = packageInfoWithPermissions(permissions, partition);
+        packageInfo.applicationInfo.targetSdkVersion = targetSdkVersion;
         when(mPackageManager.getPackageInfoAsUser(
                 eq(MOCK_PACKAGE_NAMES[0]), eq(GET_PERMISSIONS), anyInt())).thenReturn(packageInfo);
     }
 
-    private PackageInfo packageInfoWithPermissions(String[] permissions, boolean preinstalled) {
+    private PackageInfo packageInfoWithPermissions(String[] permissions, String partition) {
         final PackageInfo packageInfo = new PackageInfo();
         packageInfo.requestedPermissions = permissions;
         packageInfo.applicationInfo = new ApplicationInfo();
-        packageInfo.applicationInfo.flags = preinstalled ? FLAG_SYSTEM : 0;
+        int privateFlags = 0;
+        switch (partition) {
+            case PARTITION_OEM:
+                privateFlags = PRIVATE_FLAG_OEM;
+                break;
+            case PARTITION_PRODUCT:
+                privateFlags = PRIVATE_FLAG_PRODUCT;
+                break;
+            case PARTITION_VENDOR:
+                privateFlags = PRIVATE_FLAG_VENDOR;
+                break;
+        }
+        packageInfo.applicationInfo.privateFlags = privateFlags;
         return packageInfo;
     }
 
     @Test
     public void testHasPermission() {
-        PackageInfo app = packageInfoWithPermissions(new String[] {}, false);
+        PackageInfo app = packageInfoWithPermissions(new String[] {}, PARTITION_SYSTEM);
         assertFalse(mPermissionMonitor.hasPermission(app, CHANGE_NETWORK_STATE));
         assertFalse(mPermissionMonitor.hasPermission(app, NETWORK_STACK));
         assertFalse(mPermissionMonitor.hasPermission(app, CONNECTIVITY_USE_RESTRICTED_NETWORKS));
         assertFalse(mPermissionMonitor.hasPermission(app, CONNECTIVITY_INTERNAL));
 
         app = packageInfoWithPermissions(new String[] {
-                CHANGE_NETWORK_STATE, NETWORK_STACK
-            }, false);
+            CHANGE_NETWORK_STATE, NETWORK_STACK
+        }, PARTITION_SYSTEM);
         assertTrue(mPermissionMonitor.hasPermission(app, CHANGE_NETWORK_STATE));
         assertTrue(mPermissionMonitor.hasPermission(app, NETWORK_STACK));
         assertFalse(mPermissionMonitor.hasPermission(app, CONNECTIVITY_USE_RESTRICTED_NETWORKS));
         assertFalse(mPermissionMonitor.hasPermission(app, CONNECTIVITY_INTERNAL));
 
         app = packageInfoWithPermissions(new String[] {
-                CONNECTIVITY_USE_RESTRICTED_NETWORKS, CONNECTIVITY_INTERNAL
-            }, false);
+            CONNECTIVITY_USE_RESTRICTED_NETWORKS, CONNECTIVITY_INTERNAL
+        }, PARTITION_SYSTEM);
         assertFalse(mPermissionMonitor.hasPermission(app, CHANGE_NETWORK_STATE));
         assertFalse(mPermissionMonitor.hasPermission(app, NETWORK_STACK));
         assertTrue(mPermissionMonitor.hasPermission(app, CONNECTIVITY_USE_RESTRICTED_NETWORKS));
@@ -102,35 +123,64 @@
     }
 
     @Test
-    public void testIsPreinstalledSystemApp() {
-        PackageInfo app = packageInfoWithPermissions(new String[] {}, false);
-        assertFalse(mPermissionMonitor.isPreinstalledSystemApp(app));
-
-        app = packageInfoWithPermissions(new String[] {}, true);
-        assertTrue(mPermissionMonitor.isPreinstalledSystemApp(app));
+    public void testIsVendorApp() {
+        PackageInfo app = packageInfoWithPermissions(new String[] {}, PARTITION_SYSTEM);
+        assertFalse(mPermissionMonitor.isVendorApp(app.applicationInfo));
+        app = packageInfoWithPermissions(new String[] {}, PARTITION_OEM);
+        assertTrue(mPermissionMonitor.isVendorApp(app.applicationInfo));
+        app = packageInfoWithPermissions(new String[] {}, PARTITION_PRODUCT);
+        assertTrue(mPermissionMonitor.isVendorApp(app.applicationInfo));
+        app = packageInfoWithPermissions(new String[] {}, PARTITION_VENDOR);
+        assertTrue(mPermissionMonitor.isVendorApp(app.applicationInfo));
     }
 
     @Test
     public void testHasUseBackgroundNetworksPermission() throws Exception {
-        expectPermission(new String[] { CHANGE_NETWORK_STATE }, false);
+        expectPermission(new String[] { CHANGE_NETWORK_STATE },
+            PARTITION_SYSTEM, Build.VERSION_CODES.P);
+        assertTrue(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));
+        expectPermission(new String[] { NETWORK_STACK }, PARTITION_SYSTEM, Build.VERSION_CODES.P);
+        assertTrue(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));
+        expectPermission(new String[] { CONNECTIVITY_INTERNAL },
+            PARTITION_SYSTEM, Build.VERSION_CODES.P);
+        assertTrue(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));
+        expectPermission(new String[] { CONNECTIVITY_USE_RESTRICTED_NETWORKS },
+            PARTITION_SYSTEM, Build.VERSION_CODES.P);
         assertTrue(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));
 
-        expectPermission(new String[] { NETWORK_STACK, CONNECTIVITY_INTERNAL }, false);
+        expectPermission(new String[] { CHANGE_NETWORK_STATE },
+            PARTITION_VENDOR, Build.VERSION_CODES.P);
+        assertTrue(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));
+        expectPermission(new String[] { NETWORK_STACK },
+            PARTITION_VENDOR, Build.VERSION_CODES.P);
+        assertTrue(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));
+        expectPermission(new String[] { CONNECTIVITY_INTERNAL },
+            PARTITION_VENDOR, Build.VERSION_CODES.P);
+        assertTrue(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));
+        expectPermission(new String[] { CONNECTIVITY_USE_RESTRICTED_NETWORKS },
+            PARTITION_VENDOR, Build.VERSION_CODES.P);
         assertTrue(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));
 
-        // TODO : make this false when b/31479477 is fixed
-        expectPermission(new String[] {}, true);
-        assertTrue(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));
-        expectPermission(new String[] { CHANGE_WIFI_STATE }, true);
-        assertTrue(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));
-
-        expectPermission(new String[] { NETWORK_STACK, CONNECTIVITY_INTERNAL }, true);
-        assertTrue(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));
-
-        expectPermission(new String[] {}, false);
+        expectPermission(new String[] {}, PARTITION_SYSTEM, Build.VERSION_CODES.P);
         assertFalse(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));
+        expectPermission(new String[] { CHANGE_WIFI_STATE },
+            PARTITION_SYSTEM, Build.VERSION_CODES.P);
+        assertFalse(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));
+        expectPermission(new String[] {}, PARTITION_VENDOR, Build.VERSION_CODES.P);
+        assertTrue(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));
+        expectPermission(new String[] { CHANGE_WIFI_STATE },
+            PARTITION_VENDOR, Build.VERSION_CODES.P);
+        assertTrue(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));
 
-        expectPermission(new String[] { CHANGE_WIFI_STATE }, false);
+        expectPermission(new String[] {}, PARTITION_SYSTEM, Build.VERSION_CODES.Q);
+        assertFalse(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));
+        expectPermission(new String[] { CHANGE_WIFI_STATE },
+            PARTITION_SYSTEM, Build.VERSION_CODES.Q);
+        assertFalse(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));
+        expectPermission(new String[] {}, PARTITION_VENDOR, Build.VERSION_CODES.Q);
+        assertFalse(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));
+        expectPermission(new String[] { CHANGE_WIFI_STATE },
+            PARTITION_VENDOR, Build.VERSION_CODES.Q);
         assertFalse(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));
     }
 }
diff --git a/tests/net/java/com/android/server/connectivity/TetheringTest.java b/tests/net/java/com/android/server/connectivity/TetheringTest.java
index 0d3b8e4..40d5544 100644
--- a/tests/net/java/com/android/server/connectivity/TetheringTest.java
+++ b/tests/net/java/com/android/server/connectivity/TetheringTest.java
@@ -75,6 +75,7 @@
 import android.net.NetworkState;
 import android.net.NetworkUtils;
 import android.net.RouteInfo;
+import android.net.ip.IpServer;
 import android.net.ip.RouterAdvertisementDaemon;
 import android.net.util.InterfaceParams;
 import android.net.util.NetworkConstants;
@@ -99,10 +100,8 @@
 import com.android.internal.util.StateMachine;
 import com.android.internal.util.test.BroadcastInterceptingContext;
 import com.android.internal.util.test.FakeSettingsProvider;
-import com.android.server.connectivity.tethering.IControlsTethering;
 import com.android.server.connectivity.tethering.IPv6TetheringCoordinator;
 import com.android.server.connectivity.tethering.OffloadHardwareInterface;
-import com.android.server.connectivity.tethering.TetherInterfaceStateMachine;
 import com.android.server.connectivity.tethering.TetheringDependencies;
 import com.android.server.connectivity.tethering.UpstreamNetworkMonitor;
 
@@ -190,7 +189,7 @@
 
     public class MockTetheringDependencies extends TetheringDependencies {
         StateMachine upstreamNetworkMonitorMasterSM;
-        ArrayList<TetherInterfaceStateMachine> ipv6CoordinatorNotifyList;
+        ArrayList<IpServer> ipv6CoordinatorNotifyList;
         int isTetheringSupportedCalls;
 
         public void reset() {
@@ -213,29 +212,35 @@
 
         @Override
         public IPv6TetheringCoordinator getIPv6TetheringCoordinator(
-                ArrayList<TetherInterfaceStateMachine> notifyList, SharedLog log) {
+                ArrayList<IpServer> notifyList, SharedLog log) {
             ipv6CoordinatorNotifyList = notifyList;
             return mIPv6TetheringCoordinator;
         }
 
         @Override
-        public RouterAdvertisementDaemon getRouterAdvertisementDaemon(InterfaceParams ifParams) {
-            return mRouterAdvertisementDaemon;
-        }
+        public IpServer.Dependencies getIpServerDependencies() {
+            return new IpServer.Dependencies() {
+                @Override
+                public RouterAdvertisementDaemon getRouterAdvertisementDaemon(
+                        InterfaceParams ifParams) {
+                    return mRouterAdvertisementDaemon;
+                }
 
-        @Override
-        public INetd getNetdService() {
-            return mNetd;
-        }
+                @Override
+                public InterfaceParams getInterfaceParams(String ifName) {
+                    final String[] ifaces = new String[] {
+                            TEST_USB_IFNAME, TEST_WLAN_IFNAME, TEST_MOBILE_IFNAME };
+                    final int index = ArrayUtils.indexOf(ifaces, ifName);
+                    assertTrue("Non-mocked interface: " + ifName, index >= 0);
+                    return new InterfaceParams(ifName, index + IFINDEX_OFFSET,
+                            MacAddress.ALL_ZEROS_ADDRESS);
+                }
 
-        @Override
-        public InterfaceParams getInterfaceParams(String ifName) {
-            final String[] ifaces = new String[] { TEST_USB_IFNAME, TEST_WLAN_IFNAME,
-                    TEST_MOBILE_IFNAME };
-            final int index = ArrayUtils.indexOf(ifaces, ifName);
-            assertTrue("Non-mocked interface: " + ifName, index >= 0);
-            return new InterfaceParams(ifName, index + IFINDEX_OFFSET,
-                    MacAddress.ALL_ZEROS_ADDRESS);
+                @Override
+                public INetd getNetdService() {
+                    return mNetd;
+                }
+            };
         }
 
         @Override
@@ -458,9 +463,9 @@
         sendWifiApStateChanged(WIFI_AP_STATE_ENABLED);
         mLooper.dispatchAll();
 
-        // If, and only if, Tethering received an interface status changed
-        // then it creates a TetherInterfaceStateMachine and sends out a
-        // broadcast indicating that the interface is "available".
+        // If, and only if, Tethering received an interface status changed then
+        // it creates a IpServer and sends out a broadcast indicating that the
+        // interface is "available".
         if (emulateInterfaceStatusChanged) {
             assertEquals(1, mTetheringDependencies.isTetheringSupportedCalls);
             verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
@@ -557,18 +562,18 @@
     }
 
     /**
-     * Send CMD_IPV6_TETHER_UPDATE to TISMs as would be done by IPv6TetheringCoordinator.
+     * Send CMD_IPV6_TETHER_UPDATE to IpServers as would be done by IPv6TetheringCoordinator.
      */
     private void sendIPv6TetherUpdates(NetworkState upstreamState) {
         // IPv6TetheringCoordinator must have been notified of downstream
         verify(mIPv6TetheringCoordinator, times(1)).addActiveDownstream(
                 argThat(sm -> sm.linkProperties().getInterfaceName().equals(TEST_USB_IFNAME)),
-                eq(IControlsTethering.STATE_TETHERED));
+                eq(IpServer.STATE_TETHERED));
 
-        for (TetherInterfaceStateMachine tism :
+        for (IpServer ipSrv :
                 mTetheringDependencies.ipv6CoordinatorNotifyList) {
             NetworkState ipv6OnlyState = buildMobileUpstreamState(false, true, false);
-            tism.sendMessage(TetherInterfaceStateMachine.CMD_IPV6_TETHER_UPDATE, 0, 0,
+            ipSrv.sendMessage(IpServer.CMD_IPV6_TETHER_UPDATE, 0, 0,
                     upstreamState.linkProperties.isIPv6Provisioned()
                             ? ipv6OnlyState.linkProperties
                             : null);
@@ -812,7 +817,7 @@
 
         // We verify get/set called thrice here: once for setup and twice during
         // teardown because all events happen over the course of the single
-        // dispatchAll() above. Note that once the TISM IPv4 address config
+        // dispatchAll() above. Note that once the IpServer IPv4 address config
         // code is refactored the two calls during shutdown will revert to one.
         verify(mNMService, times(2)).getInterfaceConfig(TEST_WLAN_IFNAME);
         verify(mNMService, times(3))
diff --git a/tools/aapt2/Diagnostics.h b/tools/aapt2/Diagnostics.h
index 50e8b33..30deb55 100644
--- a/tools/aapt2/Diagnostics.h
+++ b/tools/aapt2/Diagnostics.h
@@ -133,11 +133,19 @@
   void Log(Level level, DiagMessageActual& actual_msg) override {
     actual_msg.source.path = source_.path;
     diag_->Log(level, actual_msg);
+    if (level == Level::Error) {
+      error = true;
+    }
+  }
+
+  bool HadError() {
+    return error;
   }
 
  private:
   Source source_;
   IDiagnostics* diag_;
+  bool error = false;
 
   DISALLOW_COPY_AND_ASSIGN(SourcePathDiagnostics);
 };
diff --git a/tools/aapt2/compile/XmlIdCollector.cpp b/tools/aapt2/compile/XmlIdCollector.cpp
index d61a15a..2199d00 100644
--- a/tools/aapt2/compile/XmlIdCollector.cpp
+++ b/tools/aapt2/compile/XmlIdCollector.cpp
@@ -21,6 +21,7 @@
 
 #include "ResourceUtils.h"
 #include "ResourceValues.h"
+#include "text/Unicode.h"
 #include "xml/XmlDom.h"
 
 namespace aapt {
@@ -35,8 +36,9 @@
  public:
   using xml::Visitor::Visit;
 
-  explicit IdCollector(std::vector<SourcedResourceName>* out_symbols)
-      : out_symbols_(out_symbols) {}
+  explicit IdCollector(std::vector<SourcedResourceName>* out_symbols,
+                       SourcePathDiagnostics* source_diag) : out_symbols_(out_symbols),
+                                                             source_diag_(source_diag) {}
 
   void Visit(xml::Element* element) override {
     for (xml::Attribute& attr : element->attributes) {
@@ -44,12 +46,16 @@
       bool create = false;
       if (ResourceUtils::ParseReference(attr.value, &name, &create, nullptr)) {
         if (create && name.type == ResourceType::kId) {
-          auto iter = std::lower_bound(out_symbols_->begin(),
-                                       out_symbols_->end(), name, cmp_name);
-          if (iter == out_symbols_->end() || iter->name != name) {
-            out_symbols_->insert(iter,
-                                 SourcedResourceName{name.ToResourceName(),
-                                                     element->line_number});
+          if (!text::IsValidResourceEntryName(name.entry)) {
+            source_diag_->Error(DiagMessage(element->line_number)
+                                   << "id '" << name << "' has an invalid entry name");
+          } else {
+            auto iter = std::lower_bound(out_symbols_->begin(),
+                                         out_symbols_->end(), name, cmp_name);
+            if (iter == out_symbols_->end() || iter->name != name) {
+              out_symbols_->insert(iter, SourcedResourceName{name.ToResourceName(),
+                                                             element->line_number});
+            }
           }
         }
       }
@@ -60,15 +66,17 @@
 
  private:
   std::vector<SourcedResourceName>* out_symbols_;
+  SourcePathDiagnostics* source_diag_;
 };
 
 }  // namespace
 
 bool XmlIdCollector::Consume(IAaptContext* context, xml::XmlResource* xmlRes) {
   xmlRes->file.exported_symbols.clear();
-  IdCollector collector(&xmlRes->file.exported_symbols);
+  SourcePathDiagnostics source_diag(xmlRes->file.source, context->GetDiagnostics());
+  IdCollector collector(&xmlRes->file.exported_symbols, &source_diag);
   xmlRes->root->Accept(&collector);
-  return true;
+  return !source_diag.HadError();
 }
 
 }  // namespace aapt
diff --git a/tools/aapt2/compile/XmlIdCollector_test.cpp b/tools/aapt2/compile/XmlIdCollector_test.cpp
index 98da56d..d49af3b 100644
--- a/tools/aapt2/compile/XmlIdCollector_test.cpp
+++ b/tools/aapt2/compile/XmlIdCollector_test.cpp
@@ -64,4 +64,14 @@
   EXPECT_TRUE(doc->file.exported_symbols.empty());
 }
 
+TEST(XmlIdCollectorTest, ErrorOnInvalidIds) {
+  std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
+
+  std::unique_ptr<xml::XmlResource> doc =
+      test::BuildXmlDom("<View foo=\"@+id/foo$bar\"/>");
+
+  XmlIdCollector collector;
+  ASSERT_FALSE(collector.Consume(context.get(), doc.get()));
+}
+
 }  // namespace aapt
diff --git a/tools/aapt2/link/ManifestFixer.cpp b/tools/aapt2/link/ManifestFixer.cpp
index c5c78d9..fa6538d 100644
--- a/tools/aapt2/link/ManifestFixer.cpp
+++ b/tools/aapt2/link/ManifestFixer.cpp
@@ -252,6 +252,7 @@
   xml::XmlNodeAction component_action;
   component_action.Action(RequiredNameIsJavaClassName);
   component_action["intent-filter"] = intent_filter_action;
+  component_action["preferred"] = intent_filter_action;
   component_action["meta-data"] = meta_data_action;
 
   // Manifest actions.
@@ -414,6 +415,8 @@
   application_action["provider"]["grant-uri-permission"];
   application_action["provider"]["path-permission"];
 
+  manifest_action["package"] = manifest_action;
+
   return true;
 }
 
diff --git a/tools/aapt2/util/Files.cpp b/tools/aapt2/util/Files.cpp
index 7cd023b..73105e16 100644
--- a/tools/aapt2/util/Files.cpp
+++ b/tools/aapt2/util/Files.cpp
@@ -102,12 +102,25 @@
 #endif
 
 bool mkdirs(const std::string& path) {
-  constexpr const mode_t mode = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP;
+  #ifdef _WIN32
+  // Start after the drive path if present. Calling mkdir with only the drive will cause an error.
+  size_t current_pos = 1u;
+  if (path.size() >= 3 && path[1] == ':' &&
+        (path[2] == '\\' || path[2] == '/')) {
+    current_pos = 3u;
+  }
+ #else
   // Start after the first character so that we don't consume the root '/'.
   // This is safe to do with unicode because '/' will never match with a continuation character.
   size_t current_pos = 1u;
+ #endif
+  constexpr const mode_t mode = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP;
   while ((current_pos = path.find(sDirSep, current_pos)) != std::string::npos) {
     std::string parent_path = path.substr(0, current_pos);
+    if (parent_path.empty()) {
+      continue;
+    }
+
     int result = ::android::base::utf8::mkdir(parent_path.c_str(), mode);
     if (result < 0 && errno != EEXIST) {
       return false;
diff --git a/tools/aosp/aosp_sha.sh b/tools/aosp/aosp_sha.sh
index 29bf74c..e50c70d 100755
--- a/tools/aosp/aosp_sha.sh
+++ b/tools/aosp/aosp_sha.sh
@@ -1,18 +1,24 @@
 #!/bin/bash
-LOCAL_DIR="$( dirname ${BASH_SOURCE} )"
+LOCAL_DIR="$( dirname "${BASH_SOURCE}" )"
 
-if git branch -vv | grep "^*" | grep "\[aosp/master" > /dev/null; then
+if git branch -vv | grep -q -P "^\*[^\[]+\[aosp/"; 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
+    count=0
+    while read -r file ; do
+        if (( count == 0 )); then
+            echo
+        fi
         echo -e "\033[0;31mThe source of truth for '$file' is in AOSP.\033[0m"
+        (( count++ ))
+    done < <(git show --name-only --pretty=format: $1 | grep -- "$2")
+    if (( count != 0 )); then
         echo
-        echo "If your change contains no confidential details, please upload and merge"
-        echo "this change at https://android-review.googlesource.com/."
+        echo "If your change contains no confidential details (such as security fixes), please"
+        echo "upload and merge this change at https://android-review.googlesource.com/."
         echo
         exit 77
-    done
+    fi
 fi
diff --git a/tools/hiddenapi/generate_hiddenapi_lists.py b/tools/hiddenapi/generate_hiddenapi_lists.py
index 4a0931a..6c46e67 100755
--- a/tools/hiddenapi/generate_hiddenapi_lists.py
+++ b/tools/hiddenapi/generate_hiddenapi_lists.py
@@ -59,6 +59,8 @@
 def read_lines(filename):
     """Reads entire file and return it as a list of lines.
 
+    Lines which begin with a hash are ignored.
+
     Args:
         filename (string): Path to the file to read from.
 
@@ -66,7 +68,7 @@
         list: Lines of the loaded file as a list of strings.
     """
     with open(filename, 'r') as f:
-        return f.readlines()
+        return filter(lambda line: not line.startswith('#'), f.readlines())
 
 def write_lines(filename, lines):
     """Writes list of lines into a file, overwriting the file it it exists.
diff --git a/tools/hiddenapi/sort_api.sh b/tools/hiddenapi/sort_api.sh
index 1c6eb1b..bdcc807 100755
--- a/tools/hiddenapi/sort_api.sh
+++ b/tools/hiddenapi/sort_api.sh
@@ -11,8 +11,14 @@
 readarray A < "$source_list"
 # Sort
 IFS=$'\n'
+# Stash away comments
+C=( $(grep -E '^#' <<< "${A[*]}") )
+A=( $(grep -v -E '^#' <<< "${A[*]}") )
+# Sort entries
 A=( $(LC_COLLATE=C sort -f <<< "${A[*]}") )
 A=( $(uniq <<< "${A[*]}") )
+# Concatenate comments and entries
+A=( ${C[*]} ${A[*]} )
 unset IFS
 # Dump array back into the file
 printf '%s\n' "${A[@]}" > "$dest_list"
diff --git a/tools/processors/unsupportedappusage/Android.bp b/tools/processors/unsupportedappusage/Android.bp
new file mode 100644
index 0000000..1aca3ed
--- /dev/null
+++ b/tools/processors/unsupportedappusage/Android.bp
@@ -0,0 +1,25 @@
+
+java_library_host {
+    name: "unsupportedappusage-annotation-processor",
+    java_resources: [
+        "META-INF/**/*",
+    ],
+    srcs: [
+        "src/**/*.java",
+    ],
+    static_libs: [
+        "guava",
+        "unsupportedappusage-annotation"
+    ],
+    openjdk9: {
+        javacflags: [
+            "--add-modules=jdk.compiler",
+            "--add-exports jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED",
+            "--add-exports jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED",
+            "--add-exports jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED",
+            "--add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED",
+        ],
+    },
+
+    use_tools_jar: true,
+}
diff --git a/tools/processors/unsupportedappusage/META-INF/services/javax.annotation.processing.Processor b/tools/processors/unsupportedappusage/META-INF/services/javax.annotation.processing.Processor
new file mode 100644
index 0000000..4a969d3
--- /dev/null
+++ b/tools/processors/unsupportedappusage/META-INF/services/javax.annotation.processing.Processor
@@ -0,0 +1 @@
+android.processor.unsupportedappusage.UnsupportedAppUsageProcessor
diff --git a/tools/processors/unsupportedappusage/src/android/processor/unsupportedappusage/SignatureBuilder.java b/tools/processors/unsupportedappusage/src/android/processor/unsupportedappusage/SignatureBuilder.java
new file mode 100644
index 0000000..ef29146
--- /dev/null
+++ b/tools/processors/unsupportedappusage/src/android/processor/unsupportedappusage/SignatureBuilder.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.processor.unsupportedappusage;
+
+import static javax.lang.model.element.ElementKind.PACKAGE;
+import static javax.tools.Diagnostic.Kind.ERROR;
+import static javax.tools.Diagnostic.Kind.WARNING;
+
+import android.annotation.UnsupportedAppUsage;
+
+import com.google.common.base.Strings;
+import com.google.common.collect.ImmutableMap;
+import com.sun.tools.javac.code.Type;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import javax.annotation.processing.Messager;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.PackageElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.ArrayType;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.TypeKind;
+import javax.lang.model.type.TypeMirror;
+
+/**
+ * Builds a dex signature for a given method or field.
+ */
+public class SignatureBuilder {
+
+    private static final Map<TypeKind, String> TYPE_MAP = ImmutableMap.<TypeKind, String>builder()
+            .put(TypeKind.BOOLEAN, "Z")
+            .put(TypeKind.BYTE, "B")
+            .put(TypeKind.CHAR, "C")
+            .put(TypeKind.DOUBLE, "D")
+            .put(TypeKind.FLOAT, "F")
+            .put(TypeKind.INT, "I")
+            .put(TypeKind.LONG, "J")
+            .put(TypeKind.SHORT, "S")
+            .put(TypeKind.VOID, "V")
+            .build();
+
+    private final Messager mMessager;
+
+    /**
+     * Exception used internally when we can't build a signature. Whenever this is thrown, an error
+     * will also be written to the Messager.
+     */
+    private class SignatureBuilderException extends Exception {
+        public SignatureBuilderException(String message) {
+            super(message);
+        }
+        public void report(Element offendingElement) {
+            mMessager.printMessage(ERROR, getMessage(), offendingElement);
+        }
+    }
+
+    public SignatureBuilder(Messager messager) {
+        mMessager = messager;
+    }
+
+    /**
+     * Returns a list of enclosing elements for the given element, with the package first, and
+     * excluding the element itself.
+     */
+    private List<Element> getEnclosingElements(Element e) {
+        List<Element> enclosing = new ArrayList<>();
+        e = e.getEnclosingElement(); // don't include the element itself.
+        while (e != null) {
+            enclosing.add(e);
+            e = e.getEnclosingElement();
+        }
+        Collections.reverse(enclosing);
+        return enclosing;
+    }
+
+    /**
+     * Get the dex signature for a clazz, in format "Lpackage/name/Outer$Inner;"
+     */
+    private String getClassSignature(TypeElement clazz) {
+        StringBuilder sb = new StringBuilder("L");
+        for (Element enclosing : getEnclosingElements(clazz)) {
+            if (enclosing.getKind() == PACKAGE) {
+                sb.append(((PackageElement) enclosing)
+                        .getQualifiedName()
+                        .toString()
+                        .replace('.', '/'));
+                sb.append('/');
+            } else {
+                sb.append(enclosing.getSimpleName()).append('$');
+            }
+
+        }
+        return sb
+                .append(clazz.getSimpleName())
+                .append(";")
+                .toString();
+    }
+
+    /**
+     * Returns the type signature for a given type. For primitive types, a single character.
+     * For classes, the class signature. For arrays, a "[" preceeding the component type.
+     */
+    private String getTypeSignature(TypeMirror type) throws SignatureBuilderException {
+        String sig = TYPE_MAP.get(type.getKind());
+        if (sig != null) {
+            return sig;
+        }
+        switch (type.getKind()) {
+            case ARRAY:
+                return "[" + getTypeSignature(((ArrayType) type).getComponentType());
+            case DECLARED:
+                Element declaring = ((DeclaredType) type).asElement();
+                if (!(declaring instanceof TypeElement)) {
+                    throw new SignatureBuilderException(
+                            "Can't handle declared type of kind " + declaring.getKind());
+                }
+                return getClassSignature((TypeElement) declaring);
+            case TYPEVAR:
+                Type.TypeVar typeVar = (Type.TypeVar) type;
+                if (typeVar.getLowerBound().getKind() != TypeKind.NULL) {
+                    return getTypeSignature(typeVar.getLowerBound());
+                } else if (typeVar.getUpperBound().getKind() != TypeKind.NULL) {
+                    return getTypeSignature(typeVar.getUpperBound());
+                } else {
+                    throw new SignatureBuilderException("Can't handle typevar with no bound");
+                }
+
+            default:
+                throw new SignatureBuilderException("Can't handle type of kind " + type.getKind());
+        }
+    }
+
+    /**
+     * Get the signature for an executable, either a method or a constructor.
+     *
+     * @param name "<init>" for  constructor, else the method name
+     * @param method The executable element in question.
+     */
+    private String getExecutableSignature(CharSequence name, ExecutableElement method)
+            throws SignatureBuilderException {
+        StringBuilder sig = new StringBuilder();
+        sig.append(getClassSignature((TypeElement) method.getEnclosingElement()))
+                .append("->")
+                .append(name)
+                .append("(");
+        for (VariableElement param : method.getParameters()) {
+            sig.append(getTypeSignature(param.asType()));
+        }
+        sig.append(")")
+                .append(getTypeSignature(method.getReturnType()));
+        return sig.toString();
+    }
+
+    private String buildMethodSignature(ExecutableElement method) throws SignatureBuilderException {
+        return getExecutableSignature(method.getSimpleName(), method);
+    }
+
+    private String buildConstructorSignature(ExecutableElement cons)
+            throws SignatureBuilderException {
+        return getExecutableSignature("<init>", cons);
+    }
+
+    private String buildFieldSignature(VariableElement field) throws SignatureBuilderException {
+        StringBuilder sig = new StringBuilder();
+        sig.append(getClassSignature((TypeElement) field.getEnclosingElement()))
+                .append("->")
+                .append(field.getSimpleName())
+                .append(":")
+                .append(getTypeSignature(field.asType()))
+        ;
+        return sig.toString();
+    }
+
+    public String buildSignature(Element element) {
+        UnsupportedAppUsage uba = element.getAnnotation(UnsupportedAppUsage.class);
+        try {
+            String signature;
+            switch (element.getKind()) {
+                case METHOD:
+                    signature = buildMethodSignature((ExecutableElement) element);
+                    break;
+                case CONSTRUCTOR:
+                    signature = buildConstructorSignature((ExecutableElement) element);
+                    break;
+                case FIELD:
+                    signature = buildFieldSignature((VariableElement) element);
+                    break;
+                default:
+                    return null;
+            }
+            // if we have an expected signature on the annotation, warn if it doesn't match.
+            if (!Strings.isNullOrEmpty(uba.expectedSignature())) {
+                if (!signature.equals(uba.expectedSignature())) {
+                    mMessager.printMessage(
+                            WARNING,
+                            String.format("Expected signature doesn't match generated signature.\n"
+                                            + " Expected:  %s\n Generated: %s",
+                                    uba.expectedSignature(), signature),
+                            element);
+                }
+            }
+            return signature;
+        } catch (SignatureBuilderException problem) {
+            problem.report(element);
+            return null;
+        }
+    }
+}
diff --git a/tools/processors/unsupportedappusage/src/android/processor/unsupportedappusage/UnsupportedAppUsageProcessor.java b/tools/processors/unsupportedappusage/src/android/processor/unsupportedappusage/UnsupportedAppUsageProcessor.java
new file mode 100644
index 0000000..1d4c435
--- /dev/null
+++ b/tools/processors/unsupportedappusage/src/android/processor/unsupportedappusage/UnsupportedAppUsageProcessor.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.processor.unsupportedappusage;
+
+import static javax.tools.StandardLocation.CLASS_OUTPUT;
+
+import android.annotation.UnsupportedAppUsage;
+
+import com.google.common.base.Joiner;
+import com.sun.tools.javac.model.JavacElements;
+import com.sun.tools.javac.tree.JCTree;
+import com.sun.tools.javac.util.Pair;
+import com.sun.tools.javac.util.Position;
+
+import java.io.IOException;
+import java.io.PrintStream;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.stream.Stream;
+
+import javax.annotation.processing.AbstractProcessor;
+import javax.annotation.processing.RoundEnvironment;
+import javax.annotation.processing.SupportedAnnotationTypes;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.TypeElement;
+
+/**
+ * Annotation processor for {@link UnsupportedAppUsage} annotations.
+ *
+ * This processor currently outputs two things:
+ * 1. A greylist.txt containing dex signatures of all annotated elements.
+ * 2. A CSV file with a mapping of dex signatures to corresponding source positions.
+ *
+ * The first will be used at a later stage of the build to add access flags to the dex file. The
+ * second is used for automating updates to the annotations themselves.
+ */
+@SupportedAnnotationTypes({"android.annotation.UnsupportedAppUsage"})
+public class UnsupportedAppUsageProcessor extends AbstractProcessor {
+
+    // Package name for writing output. Output will be written to the "class output" location within
+    // this package.
+    private static final String PACKAGE = "unsupportedappusage";
+    private static final String INDEX_CSV = "unsupportedappusage_index.csv";
+
+    @Override
+    public SourceVersion getSupportedSourceVersion() {
+        return SourceVersion.latest();
+    }
+
+    /**
+     * Write the contents of a stream to a text file, with one line per item.
+     */
+    private void writeToFile(String name,
+            String headerLine,
+            Stream<?> contents) throws IOException {
+        PrintStream out = new PrintStream(processingEnv.getFiler().createResource(
+                CLASS_OUTPUT,
+                PACKAGE,
+                name)
+                .openOutputStream());
+        out.println(headerLine);
+        contents.forEach(o -> out.println(o));
+        if (out.checkError()) {
+            throw new IOException("Error when writing to " + name);
+        }
+        out.close();
+    }
+
+    /**
+     * Find the annotation mirror for the @UnsupportedAppUsage annotation on the given element.
+     */
+    private AnnotationMirror getUnsupportedAppUsageAnnotationMirror(Element e) {
+        for (AnnotationMirror m : e.getAnnotationMirrors()) {
+            TypeElement type = (TypeElement) m.getAnnotationType().asElement();
+            if (type.getQualifiedName().toString().equals(
+                    UnsupportedAppUsage.class.getCanonicalName())) {
+                return m;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Returns a CSV header line for the columns returned by
+     * {@link #getAnnotationIndex(String, Element)}.
+     */
+    private String getCsvHeaders() {
+        return Joiner.on(',').join(
+                "signature",
+                "file",
+                "startline",
+                "startcol",
+                "endline",
+                "endcol"
+        );
+    }
+
+    /**
+     * Maps an annotated element to the source position of the @UnsupportedAppUsage annotation
+     * attached to it. It returns CSV in the format:
+     *   dex-signature,filename,start-line,start-col,end-line,end-col
+     *
+     * The positions refer to the annotation itself, *not* the annotated member. This can therefore
+     * be used to read just the annotation from the file, and to perform in-place edits on it.
+     *
+     * @param signature the dex signature for the element.
+     * @param annotatedElement The annotated element
+     * @return A single line of CSV text
+     */
+    private String getAnnotationIndex(String signature, Element annotatedElement) {
+        JavacElements javacElem = (JavacElements) processingEnv.getElementUtils();
+        AnnotationMirror unsupportedAppUsage =
+                getUnsupportedAppUsageAnnotationMirror(annotatedElement);
+        Pair<JCTree, JCTree.JCCompilationUnit> pair =
+                javacElem.getTreeAndTopLevel(annotatedElement, unsupportedAppUsage, null);
+        Position.LineMap lines = pair.snd.lineMap;
+        return Joiner.on(",").join(
+                signature,
+                pair.snd.getSourceFile().getName(),
+                lines.getLineNumber(pair.fst.pos().getStartPosition()),
+                lines.getColumnNumber(pair.fst.pos().getStartPosition()),
+                lines.getLineNumber(pair.fst.pos().getEndPosition(pair.snd.endPositions)),
+                lines.getColumnNumber(pair.fst.pos().getEndPosition(pair.snd.endPositions)));
+    }
+
+    /**
+     * This is the main entry point in the processor, called by the compiler.
+     */
+    @Override
+    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+        Set<? extends Element> annotated = roundEnv.getElementsAnnotatedWith(
+                UnsupportedAppUsage.class);
+        if (annotated.size() == 0) {
+            return true;
+        }
+        // build signatures for each annotated member, and put them in a map of signature to member
+        Map<String, Element> signatureMap = new TreeMap<>();
+        SignatureBuilder sb = new SignatureBuilder(processingEnv.getMessager());
+        for (Element e : annotated) {
+            String sig = sb.buildSignature(e);
+            if (sig != null) {
+                signatureMap.put(sig, e);
+            }
+        }
+        try {
+            writeToFile(INDEX_CSV,
+                    getCsvHeaders(),
+                    signatureMap.entrySet()
+                            .stream()
+                            .map(e -> getAnnotationIndex(e.getKey() ,e.getValue())));
+        } catch (IOException e) {
+            throw new RuntimeException("Failed to write output", e);
+        }
+        return true;
+    }
+}
diff --git a/tools/stats_log_api_gen/Collation.cpp b/tools/stats_log_api_gen/Collation.cpp
index 40ee490..4245700 100644
--- a/tools/stats_log_api_gen/Collation.cpp
+++ b/tools/stats_log_api_gen/Collation.cpp
@@ -184,16 +184,6 @@
     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++) {
@@ -205,9 +195,11 @@
       print_error(field, "Unkown type for field: %s\n", field->name().c_str());
       errorCount++;
       continue;
-    } else if (javaType == JAVA_TYPE_OBJECT) {
+    } else if (javaType == JAVA_TYPE_OBJECT &&
+               atomDecl->code < PULL_ATOM_START_ID) {
       // Allow attribution chain, but only at position 1.
-      print_error(field, "Message type not allowed for field: %s\n",
+      print_error(field,
+                  "Message type not allowed for field in pushed atoms: %s\n",
                   field->name().c_str());
       errorCount++;
       continue;
@@ -243,12 +235,19 @@
     java_type_t javaType = java_type(field);
 
     AtomField atField(field->name(), javaType);
+    // Generate signature for pushed atoms
+    if (atomDecl->code < PULL_ATOM_START_ID) {
+      if (javaType == JAVA_TYPE_ENUM) {
+        // All enums are treated as ints when it comes to function signatures.
+        signature->push_back(JAVA_TYPE_INT);
+        collate_enums(*field->enum_type(), &atField);
+      } else {
+        signature->push_back(javaType);
+      }
+    }
     if (javaType == JAVA_TYPE_ENUM) {
       // All enums are treated as ints when it comes to function signatures.
-      signature->push_back(JAVA_TYPE_INT);
       collate_enums(*field->enum_type(), &atField);
-    } else {
-      signature->push_back(javaType);
     }
     atomDecl->fields.push_back(atField);
 
diff --git a/tools/stats_log_api_gen/Collation.h b/tools/stats_log_api_gen/Collation.h
index ccdd145..31b8b07 100644
--- a/tools/stats_log_api_gen/Collation.h
+++ b/tools/stats_log_api_gen/Collation.h
@@ -34,6 +34,8 @@
 using google::protobuf::Descriptor;
 using google::protobuf::FieldDescriptor;
 
+const int PULL_ATOM_START_ID = 10000;
+
 /**
  * The types for atom parameters.
  */
diff --git a/tools/stats_log_api_gen/main.cpp b/tools/stats_log_api_gen/main.cpp
index 8038a3a..9915479 100644
--- a/tools/stats_log_api_gen/main.cpp
+++ b/tools/stats_log_api_gen/main.cpp
@@ -18,8 +18,6 @@
 namespace android {
 namespace stats_log_api_gen {
 
-const int PULL_ATOM_START_ID = 1000;
-
 int maxPushedAtomId = 2;
 
 using android::os::statsd::Atom;
@@ -235,6 +233,10 @@
                                  chainField.name.c_str(), chainField.name.c_str());
                     }
                 }
+            } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
+                fprintf(out, ", const std::map<int, int64_t>& arg%d_1, "
+                             "const std::map<int, char const*>& arg%d_2, "
+                             "const std::map<int, float>& arg%d_3", argIndex, argIndex, argIndex);
             } else {
                 fprintf(out, ", %s arg%d", cpp_type_name(*arg), argIndex);
             }
@@ -277,6 +279,30 @@
                 fprintf(out, "        event.end();\n");
                 fprintf(out, "    }\n");
                 fprintf(out, "    event.end();\n\n");
+            } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
+                    fprintf(out, "    event.begin();\n\n");
+                    fprintf(out, "    for (const auto& it : arg%d_1) {\n", argIndex);
+                    fprintf(out, "         event.begin();\n");
+                    fprintf(out, "         event << it.first;\n");
+                    fprintf(out, "         event << it.second;\n");
+                    fprintf(out, "         event.end();\n");
+                    fprintf(out, "    }\n");
+
+                    fprintf(out, "    for (const auto& it : arg%d_2) {\n", argIndex);
+                    fprintf(out, "         event.begin();\n");
+                    fprintf(out, "         event << it.first;\n");
+                    fprintf(out, "         event << it.second;\n");
+                    fprintf(out, "         event.end();\n");
+                    fprintf(out, "    }\n");
+
+                    fprintf(out, "    for (const auto& it : arg%d_3) {\n", argIndex);
+                    fprintf(out, "         event.begin();\n");
+                    fprintf(out, "         event << it.first;\n");
+                    fprintf(out, "         event << it.second;\n");
+                    fprintf(out, "         event.end();\n");
+                    fprintf(out, "    }\n");
+
+                    fprintf(out, "    event.end();\n\n");
             } else {
                 if (*arg == JAVA_TYPE_STRING) {
                     fprintf(out, "    if (arg%d == NULL) {\n", argIndex);
@@ -300,7 +326,7 @@
        signature != atoms.signatures.end(); signature++) {
        int argIndex;
 
-       fprintf(out, "int \n");
+       fprintf(out, "int\n");
        fprintf(out, "stats_write(int32_t code");
        argIndex = 1;
        for (vector<java_type_t>::const_iterator arg = signature->begin();
@@ -317,6 +343,10 @@
                                 chainField.name.c_str(), chainField.name.c_str());
                    }
                }
+           } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
+                fprintf(out, ", const std::map<int, int64_t>& arg%d_1, "
+                             "const std::map<int, char const*>& arg%d_2, "
+                             "const std::map<int, float>& arg%d_3", argIndex, argIndex, argIndex);
            } else {
                fprintf(out, ", %s arg%d", cpp_type_name(*arg), argIndex);
            }
@@ -343,6 +373,8 @@
                                 chainField.name.c_str(), chainField.name.c_str());
                    }
                }
+           } else  if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
+                fprintf(out, ", arg%d_1, arg%d_2, arg%d_3", argIndex, argIndex, argIndex);
            } else {
                fprintf(out, ", arg%d", argIndex);
            }
@@ -496,6 +528,11 @@
                          chainField.name.c_str(), chainField.name.c_str());
                 }
             }
+        } else if (field->javaType == JAVA_TYPE_KEY_VALUE_PAIR) {
+            fprintf(out, ", const std::map<int, int64_t>& %s_int"
+                         ", const std::map<int, char const*>& %s_str"
+                         ", const std::map<int, float>& %s_float",
+                         field->name.c_str(), field->name.c_str(), field->name.c_str());
         } else {
             fprintf(out, ", %s %s", cpp_type_name(field->javaType), field->name.c_str());
         }
@@ -508,7 +545,7 @@
     const AtomDecl &attributionDecl) {
     for (set<vector<java_type_t>>::const_iterator signature = signatures.begin();
             signature != signatures.end(); signature++) {
-        fprintf(out, "int %s(int32_t code ", method_name.c_str());
+        fprintf(out, "int %s(int32_t code", method_name.c_str());
         int argIndex = 1;
         for (vector<java_type_t>::const_iterator arg = signature->begin();
             arg != signature->end(); arg++) {
@@ -523,6 +560,10 @@
                             chainField.name.c_str(), chainField.name.c_str());
                     }
                 }
+            } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
+                fprintf(out, ", const std::map<int, int64_t>& arg%d_1, "
+                             "const std::map<int, char const*>& arg%d_2, "
+                             "const std::map<int, float>& arg%d_3", argIndex, argIndex, argIndex);
             } else {
                 fprintf(out, ", %s arg%d", cpp_type_name(*arg), argIndex);
             }
@@ -637,6 +678,8 @@
         field != atom.fields.end(); field++) {
         if (field->javaType == JAVA_TYPE_ATTRIBUTION_CHAIN) {
             fprintf(out, ", android.os.WorkSource workSource");
+        } else if (field->javaType == JAVA_TYPE_KEY_VALUE_PAIR) {
+            fprintf(out, ", SparseArray<Object> value_map");
         } else {
             fprintf(out, ", %s %s", java_type_name(field->javaType), field->name.c_str());
         }
@@ -658,6 +701,8 @@
                     fprintf(out, ", %s[] %s",
                         java_type_name(chainField.javaType), chainField.name.c_str());
                 }
+            } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
+                fprintf(out, ", SparseArray<Object> value_map");
             } else {
                 fprintf(out, ", %s arg%d", java_type_name(*arg), argIndex);
             }
@@ -746,6 +791,7 @@
     fprintf(out, "package android.util;\n");
     fprintf(out, "\n");
     fprintf(out, "import android.os.WorkSource;\n");
+    fprintf(out, "import android.util.SparseArray;\n");
     fprintf(out, "import java.util.ArrayList;\n");
     fprintf(out, "\n");
     fprintf(out, "\n");
@@ -837,6 +883,8 @@
     switch (type) {
         case JAVA_TYPE_INT:
             return "jintArray";
+        case JAVA_TYPE_FLOAT:
+            return "jfloatArray";
         case JAVA_TYPE_STRING:
             return "jobjectArray";
         default:
@@ -873,6 +921,9 @@
             case JAVA_TYPE_ATTRIBUTION_CHAIN:
               result += "_AttributionChain";
               break;
+            case JAVA_TYPE_KEY_VALUE_PAIR:
+              result += "_KeyValuePairs";
+              break;
             default:
                 result += "_UNKNOWN";
                 break;
@@ -914,6 +965,8 @@
                 result += "[";
                 result += java_type_signature(chainField.javaType);
             }
+        } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
+            result += "Landroid/util/SparseArray;";
         } else {
             result += java_type_signature(*arg);
         }
@@ -922,6 +975,43 @@
     return result;
 }
 
+static void write_key_value_map_jni(FILE* out) {
+   fprintf(out, "    std::map<int, int64_t> int64_t_map;\n");
+   fprintf(out, "    std::map<int, float> float_map;\n");
+   fprintf(out, "    std::map<int, char const*> string_map;\n\n");
+
+   fprintf(out, "    jclass jmap_class = env->FindClass(\"android/util/SparseArray\");\n");
+
+   fprintf(out, "    jmethodID jget_size_method = env->GetMethodID(jmap_class, \"size\", \"()I\");\n");
+   fprintf(out, "    jmethodID jget_key_method = env->GetMethodID(jmap_class, \"keyAt\", \"(I)I\");\n");
+   fprintf(out, "    jmethodID jget_value_method = env->GetMethodID(jmap_class, \"valueAt\", \"(I)Ljava/lang/Object;\");\n\n");
+
+
+   fprintf(out, "    std::vector<std::unique_ptr<ScopedUtfChars>> scoped_ufs;\n\n");
+
+   fprintf(out, "    jclass jlong_class = env->FindClass(\"java/lang/Long\");\n");
+   fprintf(out, "    jclass jfloat_class = env->FindClass(\"java/lang/Float\");\n");
+   fprintf(out, "    jclass jstring_class = env->FindClass(\"java/lang/String\");\n");
+   fprintf(out, "    jmethodID jget_long_method = env->GetMethodID(jlong_class, \"longValue\", \"()J\");\n");
+   fprintf(out, "    jmethodID jget_float_method = env->GetMethodID(jfloat_class, \"floatValue\", \"()F\");\n\n");
+
+   fprintf(out, "    jint jsize = env->CallIntMethod(value_map, jget_size_method);\n");
+   fprintf(out, "    for(int i = 0; i < jsize; i++) {\n");
+   fprintf(out, "        jint key = env->CallIntMethod(value_map, jget_key_method, i);\n");
+   fprintf(out, "        jobject jvalue_obj = env->CallObjectMethod(value_map, jget_value_method, i);\n");
+   fprintf(out, "        if (jvalue_obj == NULL) { continue; }\n");
+   fprintf(out, "        if (env->IsInstanceOf(jvalue_obj, jlong_class)) {\n");
+   fprintf(out, "            int64_t_map[key] = env->CallLongMethod(jvalue_obj, jget_long_method);\n");
+   fprintf(out, "        } else if (env->IsInstanceOf(jvalue_obj, jfloat_class)) {\n");
+   fprintf(out, "            float_map[key] = env->CallFloatMethod(jvalue_obj, jget_float_method);\n");
+   fprintf(out, "        } else if (env->IsInstanceOf(jvalue_obj, jstring_class)) {\n");
+   fprintf(out, "            std::unique_ptr<ScopedUtfChars> utf(new ScopedUtfChars(env, (jstring)jvalue_obj));\n");
+   fprintf(out, "            if (utf->c_str() != NULL) { string_map[key] = utf->c_str(); }\n");
+   fprintf(out, "            scoped_ufs.push_back(std::move(utf));\n");
+   fprintf(out, "        }\n");
+   fprintf(out, "    }\n");
+}
+
 static int
 write_stats_log_jni(FILE* out, const string& java_method_name, const string& cpp_method_name,
     const set<vector<java_type_t>>& signatures, const AtomDecl &attributionDecl)
@@ -942,6 +1032,8 @@
                     fprintf(out, ", %s %s", jni_array_type_name(chainField.javaType),
                         chainField.name.c_str());
                 }
+            } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
+                fprintf(out, ", jobject value_map");
             } else {
                 fprintf(out, ", %s arg%d", jni_type_name(*arg), argIndex);
             }
@@ -954,6 +1046,7 @@
         // Prepare strings
         argIndex = 1;
         bool hadStringOrChain = false;
+        bool isKeyValuePairAtom = false;
         for (vector<java_type_t>::const_iterator arg = signature->begin();
                 arg != signature->end(); arg++) {
             if (*arg == JAVA_TYPE_STRING) {
@@ -1006,18 +1099,23 @@
                     }
                     fprintf(out, "\n");
                 }
+            } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
+                isKeyValuePairAtom = true;
             }
             argIndex++;
         }
         // Emit this to quiet the unused parameter warning if there were no strings or attribution
         // chains.
-        if (!hadStringOrChain) {
+        if (!hadStringOrChain && !isKeyValuePairAtom) {
             fprintf(out, "    (void)env;\n");
         }
+        if (isKeyValuePairAtom) {
+            write_key_value_map_jni(out);
+        }
 
         // stats_write call
         argIndex = 1;
-        fprintf(out, "   int ret =  android::util::%s(code", cpp_method_name.c_str());
+        fprintf(out, "\n    int ret =  android::util::%s(code", cpp_method_name.c_str());
         for (vector<java_type_t>::const_iterator arg = signature->begin();
                 arg != signature->end(); arg++) {
             if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
@@ -1030,6 +1128,8 @@
                         fprintf(out, ", %s_vec", chainField.name.c_str());
                     }
                 }
+            } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
+                fprintf(out, ", int64_t_map, string_map, float_map");
             } else {
                 const char *argName = (*arg == JAVA_TYPE_STRING) ? "str" : "arg";
                 fprintf(out, ", (%s)%s%d", cpp_type_name(*arg), argName, argIndex);
@@ -1063,6 +1163,7 @@
             }
             argIndex++;
         }
+
         fprintf(out, "    return ret;\n");
 
         fprintf(out, "}\n");
diff --git a/tools/validatekeymaps/Android.bp b/tools/validatekeymaps/Android.bp
index 6fb278c..819e75b 100644
--- a/tools/validatekeymaps/Android.bp
+++ b/tools/validatekeymaps/Android.bp
@@ -15,6 +15,7 @@
     ],
 
     static_libs: [
+        "libbase",
         "libinput",
         "libutils",
         "libcutils",
diff --git a/tools/validatekeymaps/Main.cpp b/tools/validatekeymaps/Main.cpp
index bbfcba6..f31f771 100644
--- a/tools/validatekeymaps/Main.cpp
+++ b/tools/validatekeymaps/Main.cpp
@@ -18,7 +18,6 @@
 #include <input/KeyLayoutMap.h>
 #include <input/VirtualKeyMap.h>
 #include <utils/PropertyMap.h>
-#include <utils/String8.h>
 
 #include <stdarg.h>
 #include <stdio.h>
@@ -98,7 +97,7 @@
 
     case FILETYPE_KEYLAYOUT: {
         sp<KeyLayoutMap> map;
-        status_t status = KeyLayoutMap::load(String8(filename), &map);
+        status_t status = KeyLayoutMap::load(filename, &map);
         if (status) {
             error("Error %d parsing key layout file.\n\n", status);
             return false;
@@ -108,7 +107,7 @@
 
     case FILETYPE_KEYCHARACTERMAP: {
         sp<KeyCharacterMap> map;
-        status_t status = KeyCharacterMap::load(String8(filename),
+        status_t status = KeyCharacterMap::load(filename,
                 KeyCharacterMap::FORMAT_ANY, &map);
         if (status) {
             error("Error %d parsing key character map file.\n\n", status);
@@ -130,7 +129,7 @@
 
     case FILETYPE_VIRTUALKEYDEFINITION: {
         VirtualKeyMap* map;
-        status_t status = VirtualKeyMap::load(String8(filename), &map);
+        status_t status = VirtualKeyMap::load(filename, &map);
         if (status) {
             error("Error %d parsing virtual key definition file.\n\n", status);
             return false;
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareAgentNetworkSpecifier.java b/wifi/java/android/net/wifi/aware/WifiAwareAgentNetworkSpecifier.java
index 7c99c49..1426383 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareAgentNetworkSpecifier.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareAgentNetworkSpecifier.java
@@ -48,7 +48,7 @@
     private MessageDigest mDigester;
 
     public WifiAwareAgentNetworkSpecifier() {
-        // do nothing, already initialized to empty
+        initialize();
     }
 
     public WifiAwareAgentNetworkSpecifier(WifiAwareNetworkSpecifier ns) {
diff --git a/wifi/java/android/net/wifi/hotspot2/ProvisioningCallback.java b/wifi/java/android/net/wifi/hotspot2/ProvisioningCallback.java
index ef9c59f..bb02dec 100644
--- a/wifi/java/android/net/wifi/hotspot2/ProvisioningCallback.java
+++ b/wifi/java/android/net/wifi/hotspot2/ProvisioningCallback.java
@@ -85,15 +85,21 @@
     public static final int OSU_FAILURE_SOAP_MESSAGE_EXCHANGE = 11;
 
     /**
-     * The reason code for provisioning failure when a redirect server fails to start.
+     * The reason code for provisioning failure when a redirect listener fails to start.
      */
-    public static final int OSU_FAILURE_START_REDIRECT_SERVER = 12;
+    public static final int OSU_FAILURE_START_REDIRECT_LISTENER = 12;
+
+    /**
+     * The reason code for provisioning failure when a redirect listener timed out to receive a HTTP
+     * redirect response.
+     */
+    public static final int OSU_FAILURE_TIMED_OUT_REDIRECT_LISTENER = 13;
 
     /**
      * 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;
+    public static final int OSU_FAILURE_NO_OSU_ACTIVITY_FOUND = 14;
 
     /**
      * The status code for provisioning flow to indicate connecting to OSU AP
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
index 57f3973..5a4c898 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
@@ -30,6 +30,7 @@
 import android.net.wifi.p2p.nsd.WifiP2pUpnpServiceInfo;
 import android.net.wifi.p2p.nsd.WifiP2pUpnpServiceResponse;
 import android.os.Binder;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
@@ -488,7 +489,7 @@
      * @hide - hide this because it takes in a parameter of type IWifiP2pManager, which
      * is a system private class.
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     public WifiP2pManager(IWifiP2pManager service) {
         mService = service;
     }
diff --git a/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java b/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java
index 3517984..3b9f93e 100644
--- a/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java
@@ -18,14 +18,14 @@
 
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.assertFalse;
 
-import android.os.Parcel;
 import android.net.MacAddress;
 import android.net.wifi.WifiConfiguration.NetworkSelectionStatus;
-import android.net.wifi.WifiInfo;
+import android.os.Parcel;
+import android.support.test.filters.SmallTest;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -33,6 +33,7 @@
 /**
  * Unit tests for {@link android.net.wifi.WifiConfiguration}.
  */
+@SmallTest
 public class WifiConfigurationTest {
 
     @Before
diff --git a/wifi/tests/src/android/net/wifi/WifiSsidTest.java b/wifi/tests/src/android/net/wifi/WifiSsidTest.java
index e5794c5..b58f2c7 100644
--- a/wifi/tests/src/android/net/wifi/WifiSsidTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiSsidTest.java
@@ -19,14 +19,16 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
+import android.support.test.filters.SmallTest;
+
 import org.junit.Test;
 
 import java.nio.charset.StandardCharsets;
-import java.util.Arrays;
 
 /**
  * Unit tests for {@link android.net.wifi.WifiSsid}.
  */
+@SmallTest
 public class WifiSsidTest {
 
     private static final String TEST_SSID = "Test SSID";
diff --git a/wifi/tests/src/android/net/wifi/aware/WifiAwareAgentNetworkSpecifierTest.java b/wifi/tests/src/android/net/wifi/aware/WifiAwareAgentNetworkSpecifierTest.java
index 0515e06..657e5a7 100644
--- a/wifi/tests/src/android/net/wifi/aware/WifiAwareAgentNetworkSpecifierTest.java
+++ b/wifi/tests/src/android/net/wifi/aware/WifiAwareAgentNetworkSpecifierTest.java
@@ -18,6 +18,7 @@
 
 import static org.hamcrest.core.IsEqual.equalTo;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 
 import android.os.Parcel;
 import android.support.test.filters.SmallTest;
@@ -60,6 +61,13 @@
                 WifiAwareAgentNetworkSpecifier.CREATOR.createFromParcel(parcelR);
 
         assertEquals(dut, rereadDut);
+
+        // Ensure that individual network specifiers are satisfied by both the original & marshaled
+        // |WifiAwareNetworkAgentSpecifier instances.
+        for (WifiAwareNetworkSpecifier ns : nsSet) {
+            assertTrue(dut.satisfiesAwareNetworkSpecifier(ns));
+            assertTrue(rereadDut.satisfiesAwareNetworkSpecifier(ns));
+        }
     }
 
     /**
diff --git a/wifi/tests/src/android/net/wifi/p2p/WifiP2pDeviceTest.java b/wifi/tests/src/android/net/wifi/p2p/WifiP2pDeviceTest.java
index e492475..80f00a4 100644
--- a/wifi/tests/src/android/net/wifi/p2p/WifiP2pDeviceTest.java
+++ b/wifi/tests/src/android/net/wifi/p2p/WifiP2pDeviceTest.java
@@ -19,11 +19,14 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
+import android.support.test.filters.SmallTest;
+
 import org.junit.Test;
 
 /**
  * Unit test harness for {@link android.net.wifi.p2p.WifiP2pDevice}
  */
+@SmallTest
 public class WifiP2pDeviceTest {
 
     /**
diff --git a/wifi/tests/src/android/net/wifi/p2p/WifiP2pManagerTest.java b/wifi/tests/src/android/net/wifi/p2p/WifiP2pManagerTest.java
index e8e4dc2..2132b41 100644
--- a/wifi/tests/src/android/net/wifi/p2p/WifiP2pManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/p2p/WifiP2pManagerTest.java
@@ -21,6 +21,7 @@
 
 import android.content.Context;
 import android.os.test.TestLooper;
+import android.support.test.filters.SmallTest;
 
 import libcore.junit.util.ResourceLeakageDetector;
 
@@ -33,6 +34,7 @@
 /**
  * Unit test harness for WifiP2pManager.
  */
+@SmallTest
 public class WifiP2pManagerTest {
     private WifiP2pManager mDut;
     private TestLooper mTestLooper;
diff --git a/wifi/tests/src/android/net/wifi/rtt/WifiRttManagerTest.java b/wifi/tests/src/android/net/wifi/rtt/WifiRttManagerTest.java
index ccb9031..8997ae9 100644
--- a/wifi/tests/src/android/net/wifi/rtt/WifiRttManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/rtt/WifiRttManagerTest.java
@@ -31,6 +31,7 @@
 import android.os.IBinder;
 import android.os.Parcel;
 import android.os.test.TestLooper;
+import android.support.test.filters.SmallTest;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -45,6 +46,7 @@
 /**
  * Unit test harness for WifiRttManager class.
  */
+@SmallTest
 public class WifiRttManagerTest {
     private WifiRttManager mDut;
     private TestLooper mMockLooper;