Merge "Unhide Paint.getTextRunAdvances"
diff --git a/Android.bp b/Android.bp
index cb7f7a2..ca1c614 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1084,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",
@@ -1144,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",
     ],
@@ -1205,22 +1193,12 @@
     ],
     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"
-
 stubs_defaults {
     name: "metalava-api-stubs-default",
     srcs: [
@@ -1254,21 +1232,45 @@
     ],
 }
 
+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",
 }
@@ -1276,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",
@@ -1289,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",
@@ -1304,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 " +
@@ -1330,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 " +
@@ -1363,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 " +
@@ -1389,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 " +
@@ -1403,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 ",
@@ -1416,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 " +
@@ -1442,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",
@@ -1466,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 {
@@ -1496,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 {
diff --git a/api/current.txt b/api/current.txt
index c6557b9..1eecc2d 100755
--- a/api/current.txt
+++ b/api/current.txt
@@ -2905,6 +2905,7 @@
     field public static final deprecated int FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY = 8; // 0x8
     field public static final int FLAG_REQUEST_FILTER_KEY_EVENTS = 32; // 0x20
     field public static final int FLAG_REQUEST_FINGERPRINT_GESTURES = 512; // 0x200
+    field public static final int FLAG_REQUEST_SHORTCUT_WARNING_DIALOG_SPOKEN_FEEDBACK = 1024; // 0x400
     field public static final int FLAG_REQUEST_TOUCH_EXPLORATION_MODE = 4; // 0x4
     field public static final int FLAG_RETRIEVE_INTERACTIVE_WINDOWS = 64; // 0x40
     field public int eventTypes;
@@ -36595,9 +36596,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 {
@@ -36700,7 +36701,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";
   }
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/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 2c07431..6ab4dd9 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -132,6 +132,7 @@
         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.
@@ -229,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:
@@ -2175,8 +2196,8 @@
 /**
  * Pulls the statistics of calls to Binder.
  *
- * Binder stats are cumulative from boot unless somebody reset the data using
- * > adb shell dumpsys binder_calls_stats --reset
+ * Binder stats will be reset every time the data is pulled. It means it can only be pulled by one
+ * config on the device.
  *
  * Next tag: 14
  */
diff --git a/cmds/statsd/src/external/StatsPullerManager.cpp b/cmds/statsd/src/external/StatsPullerManager.cpp
index dbc13dc..f6ba0b6 100644
--- a/cmds/statsd/src/external/StatsPullerManager.cpp
+++ b/cmds/statsd/src/external/StatsPullerManager.cpp
@@ -168,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},
diff --git a/config/hiddenapi-light-greylist.txt b/config/hiddenapi-light-greylist.txt
index 5d37c5f..8c347fc 100644
--- a/config/hiddenapi-light-greylist.txt
+++ b/config/hiddenapi-light-greylist.txt
@@ -2222,13 +2222,6 @@
 Lcom/android/org/conscrypt/AbstractConscryptSocket;->setUseSessionTickets(Z)V
 Lcom/android/org/conscrypt/ConscryptFileDescriptorSocket;->setHostname(Ljava/lang/String;)V
 Lcom/android/org/conscrypt/ConscryptFileDescriptorSocket;->setUseSessionTickets(Z)V
-Lcom/android/org/conscrypt/ConscryptSocketBase;->getHostname()Ljava/lang/String;
-Lcom/android/org/conscrypt/ConscryptSocketBase;->getHostnameOrIP()Ljava/lang/String;
-Lcom/android/org/conscrypt/ConscryptSocketBase;->getSoWriteTimeout()I
-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/OpenSSLKey;-><init>(J)V
 Lcom/android/org/conscrypt/OpenSSLKey;->fromPrivateKey(Ljava/security/PrivateKey;)Lcom/android/org/conscrypt/OpenSSLKey;
 Lcom/android/org/conscrypt/OpenSSLKey;->getNativeRef()Lcom/android/org/conscrypt/NativeRef$EVP_PKEY;
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index 9a061b0..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;
@@ -446,7 +447,7 @@
     @UnsupportedAppUsage
     private AccessibilityServiceInfo mInfo;
 
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private IBinder mWindowToken;
 
     private WindowManager mWindowManager;
diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
index 759443d..aa0275a 100644
--- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
+++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
@@ -314,6 +314,12 @@
      */
     public static final int FLAG_REQUEST_FINGERPRINT_GESTURES = 0x00000200;
 
+    /**
+     * This flag requests that accessibility shortcut warning dialog has spoken feedback when
+     * dialog is shown.
+     */
+    public static final int FLAG_REQUEST_SHORTCUT_WARNING_DIALOG_SPOKEN_FEEDBACK = 0x00000400;
+
     /** {@hide} */
     public static final int FLAG_FORCE_DIRECT_BOOT_AWARE = 0x00010000;
 
@@ -414,6 +420,7 @@
      * @see #FLAG_RETRIEVE_INTERACTIVE_WINDOWS
      * @see #FLAG_ENABLE_ACCESSIBILITY_VOLUME
      * @see #FLAG_REQUEST_ACCESSIBILITY_BUTTON
+     * @see #FLAG_REQUEST_SHORTCUT_WARNING_DIALOG_SPOKEN_FEEDBACK
      */
     public int flags;
 
@@ -1050,6 +1057,8 @@
                 return "FLAG_REQUEST_ACCESSIBILITY_BUTTON";
             case FLAG_REQUEST_FINGERPRINT_GESTURES:
                 return "FLAG_REQUEST_FINGERPRINT_GESTURES";
+            case FLAG_REQUEST_SHORTCUT_WARNING_DIALOG_SPOKEN_FEEDBACK:
+                return "FLAG_REQUEST_SHORTCUT_WARNING_DIALOG_SPOKEN_FEEDBACK";
             default:
                 return null;
         }
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 7b86646..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
@@ -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);
         }
@@ -6385,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;
@@ -7097,7 +7100,7 @@
 
     // ------------------ Internal API ------------------
 
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     final void setParent(Activity parent) {
         mParent = parent;
     }
@@ -7208,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 0e884d6..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());
@@ -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/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/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/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 491af60..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;
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/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/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/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/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/Context.java b/core/java/android/content/Context.java
index 80e79a3..2ae3ae6 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -327,6 +327,15 @@
     public static final int BIND_ADJUST_WITH_ACTIVITY = 0x0080;
 
     /**
+     * Flag for {@link #bindService}: If binding from something better than perceptible,
+     * still set the adjust below perceptible. This would be used for bound services that can
+     * afford to be evicted when under extreme memory pressure, but should be restarted as soon
+     * as possible.
+     * @hide
+     */
+    public static final int BIND_ADJUST_BELOW_PERCEPTIBLE = 0x0100;
+
+    /**
      * @hide Flag for {@link #bindService}: allows binding to a service provided
      * by an instant app. Note that the caller may not have access to the instant
      * app providing the service which is a violation of the instant app sandbox.
@@ -3407,7 +3416,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 +3440,7 @@
      *
      * @hide
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     public static final String COUNTRY_DETECTOR = "country_detector";
 
     /**
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/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/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 316ace1..8fab7bb 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;
@@ -960,6 +961,10 @@
          * If the installer is the device owner or the affiliated profile owner, there will be no
          * user intervention.
          *
+         * @param statusReceiver Called when the state of the session changes. Intents
+         *                       sent to this receiver contain {@link #EXTRA_STATUS}. Refer to the
+         *                       individual status codes on how to handle them.
+         *
          * @throws SecurityException if streams opened through
          *             {@link #openWrite(String, long, long)} are still open.
          *
@@ -986,7 +991,9 @@
          * that new properties are added to the session with a new API revision. In this case the
          * callers need to be updated.
          *
-         * @param statusReceiver Callbacks called when the state of the session changes.
+         * @param statusReceiver Called when the state of the session changes. Intents
+         *                       sent to this receiver contain {@link #EXTRA_STATUS}. Refer to the
+         *                       individual status codes on how to handle them.
          *
          * @hide
          */
@@ -1091,7 +1098,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 +1111,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 +1442,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/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java
index 20e1454e..b5b4432 100644
--- a/core/java/android/content/pm/PackageManagerInternal.java
+++ b/core/java/android/content/pm/PackageManagerInternal.java
@@ -136,24 +136,6 @@
     public abstract void setVoiceInteractionPackagesProvider(PackagesProvider provider);
 
     /**
-     * Sets the SMS packages provider.
-     * @param provider The packages provider.
-     */
-    public abstract void setSmsAppPackagesProvider(PackagesProvider provider);
-
-    /**
-     * Sets the dialer packages provider.
-     * @param provider The packages provider.
-     */
-    public abstract void setDialerAppPackagesProvider(PackagesProvider provider);
-
-    /**
-     * Sets the sim call manager packages provider.
-     * @param provider The packages provider.
-     */
-    public abstract void setSimCallManagerPackagesProvider(PackagesProvider provider);
-
-    /**
      * Sets the Use Open Wifi packages provider.
      * @param provider The packages provider.
      */
@@ -166,26 +148,28 @@
     public abstract void setSyncAdapterPackagesprovider(SyncAdapterPackagesProvider provider);
 
     /**
-     * Requests granting of the default permissions to the current default SMS app.
-     * @param packageName The default SMS package name.
-     * @param userId The user for which to grant the permissions.
+     * Called when the package for the default dialer changed
+     *
+     * @param packageName the new dialer package
+     * @param userId user for which the change was made
      */
-    public abstract void grantDefaultPermissionsToDefaultSmsApp(String packageName, int userId);
+    public void onDefaultDialerAppChanged(String packageName, int userId) {}
 
     /**
-     * Requests granting of the default permissions to the current default dialer app.
-     * @param packageName The default dialer package name.
-     * @param userId The user for which to grant the permissions.
+     * Called when the package for the default SMS handler changed
+     *
+     * @param packageName the new sms package
+     * @param userId user for which the change was made
      */
-    public abstract void grantDefaultPermissionsToDefaultDialerApp(String packageName, int userId);
+    public void onDefaultSmsAppChanged(String packageName, int userId) {}
 
     /**
-     * Requests granting of the default permissions to the current default sim call manager.
-     * @param packageName The default sim call manager package name.
-     * @param userId The user for which to grant the permissions.
+     * Called when the package for the default sim call manager changed
+     *
+     * @param packageName the new sms package
+     * @param userId user for which the change was made
      */
-    public abstract void grantDefaultPermissionsToDefaultSimCallManager(String packageName,
-            int userId);
+    public void onDefaultSimCallManagerAppChanged(String packageName, int userId) {}
 
     /**
      * Requests granting of the default permissions to the current default Use Open Wifi app.
@@ -446,8 +430,8 @@
          *
          * @param packageName The package to check for
          * @param uid the uid in which the package is running
-         * @return {@link USER_TRUSTED} if the user has trusted the package, {@link USER_BLOCKED}
-         * if user has blocked requests from the package, {@link USER_DEFAULT} if the user response
+         * @return {@link #USER_TRUSTED} if the user has trusted the package, {@link #USER_BLOCKED}
+         * if user has blocked requests from the package, {@link #USER_DEFAULT} if the user response
          * is not yet available
          */
         int getPackageTrustedToInstallApps(String packageName, int uid);
@@ -561,7 +545,7 @@
     /**
      * Returns a list without a change observer.
      *
-     * {@see #getPackageList(PackageListObserver)}
+     * @see #getPackageList(PackageListObserver)
      */
     public @NonNull PackageList getPackageList() {
         return getPackageList(null);
@@ -590,7 +574,16 @@
     /**
      * Returns a package object for the disabled system package name.
      */
-    public abstract @Nullable PackageParser.Package getDisabledPackage(@NonNull String packageName);
+    public abstract @Nullable PackageParser.Package getDisabledSystemPackage(
+            @NonNull String packageName);
+
+    /**
+     * Returns the package name for the disabled system package.
+     *
+     * This is equivalent to
+     * {@link #getDisabledSystemPackage(String)}.{@link PackageParser.Package#packageName}
+     */
+    public abstract @Nullable String getDisabledSystemPackageName(@NonNull String packageName);
 
     /**
      * Returns whether or not the component is the resolver activity.
@@ -619,7 +612,7 @@
      * Access may be limited based upon whether the calling or target applications
      * are instant applications.
      *
-     * @see #canAccessInstantApps(int)
+     * @see #canAccessInstantApps
      */
     public abstract boolean filterAppAccess(
             @Nullable PackageParser.Package pkg, int callingUid, int userId);
@@ -635,6 +628,9 @@
     public abstract void updatePermissionFlagsTEMP(@NonNull String permName,
             @NonNull String packageName, int flagMask, int flagValues, int userId);
 
+    /** Returns whether the given package was signed by the platform */
+    public abstract boolean isPlatformSigned(String pkg);
+
     /**
      * Returns true if it's still safe to restore data backed up from this app's version
      * that was signed with restoringFromSigHash.
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 6d49362..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;
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/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/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/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/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 ae0855a..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;
@@ -385,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/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/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/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/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/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/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/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/Settings.java b/core/java/android/provider/Settings.java
index 026195e..4c7f0f3 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -363,6 +363,21 @@
             "android.settings.MANAGE_UNKNOWN_APP_SOURCES";
 
     /**
+     * Activity Action: Show the "Open by Default" page in a particular application's details page.
+     * <p>
+     * In some cases, a matching Activity may not exist, so ensure you safeguard against this.
+     * <p>
+     * Input: The Intent's data URI specifies the application package name
+     * to be shown, with the "package" scheme. That is "package:com.my.app".
+     * <p>
+     * Output: Nothing.
+     * @hide
+     */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_APP_OPEN_BY_DEFAULT_SETTINGS =
+            "com.android.settings.APP_OPEN_BY_DEFAULT_SETTINGS";
+
+    /**
      * Activity Action: Show trusted credentials settings, opening to the user tab,
      * to allow management of installed credentials.
      * <p>
@@ -809,21 +824,6 @@
             "android.settings.APPLICATION_DETAILS_SETTINGS";
 
     /**
-     * Activity Action: Show the "Open by Default" page in a particular application's details page.
-     * <p>
-     * In some cases, a matching Activity may not exist, so ensure you safeguard against this.
-     * <p>
-     * Input: The Intent's data URI specifies the application package name
-     * to be shown, with the "package" scheme. That is "package:com.my.app".
-     * <p>
-     * Output: Nothing.
-     * @hide
-     */
-    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
-    public static final String ACTION_APPLICATION_DETAILS_SETTINGS_OPEN_BY_DEFAULT_PAGE =
-            "android.settings.APPLICATION_DETAILS_SETTINGS_OPEN_BY_DEFAULT_PAGE";
-
-    /**
      * Activity Action: Show list of applications that have been running
      * foreground services (to the user "running in the background").
      * <p>
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/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index 3319c9e..d7fe15d 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -280,7 +280,7 @@
 
     private final Object mLock = new Object();
 
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private Handler mHandler;
 
     /** @hide */
diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java
index f2fa45d..e819c96 100644
--- a/core/java/android/service/notification/ZenModeConfig.java
+++ b/core/java/android/service/notification/ZenModeConfig.java
@@ -1551,7 +1551,9 @@
             if (component != null) {
                 component.writeToProto(proto, ZenRuleProto.COMPONENT);
             }
-            // TODO:  write zenPolicy to proto (b/115370281)
+            if (zenPolicy != null) {
+                zenPolicy.writeToProto(proto, ZenRuleProto.ZEN_POLICY);
+            }
             proto.end(token);
         }
 
diff --git a/core/java/android/service/notification/ZenPolicy.java b/core/java/android/service/notification/ZenPolicy.java
index 88825f0..1ccf529 100644
--- a/core/java/android/service/notification/ZenPolicy.java
+++ b/core/java/android/service/notification/ZenPolicy.java
@@ -21,6 +21,7 @@
 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;
@@ -852,6 +853,34 @@
     }
 
     /**
+     * @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
      */
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/StaticLayout.java b/core/java/android/text/StaticLayout.java
index 5adb1ca..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;
@@ -1293,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 bf2d600..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;
 
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index 0476cf8..ff6e86e 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -45,6 +45,7 @@
         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/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/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/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/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/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/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/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index c51c5e2..508509a 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -336,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.
diff --git a/core/java/android/view/inputmethod/InputMethodSubtype.java b/core/java/android/view/inputmethod/InputMethodSubtype.java
index a7d7a8d..14c879e 100644
--- a/core/java/android/view/inputmethod/InputMethodSubtype.java
+++ b/core/java/android/view/inputmethod/InputMethodSubtype.java
@@ -28,7 +28,7 @@
 import android.text.TextUtils;
 import android.util.Slog;
 
-import com.android.internal.inputmethod.InputMethodUtils;
+import com.android.internal.inputmethod.SubtypeLocaleUtils;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -384,7 +384,7 @@
             if (!TextUtils.isEmpty(mSubtypeLanguageTag)) {
                 mCachedLocaleObj = Locale.forLanguageTag(mSubtypeLanguageTag);
             } else {
-                mCachedLocaleObj = InputMethodUtils.constructLocaleFromString(mSubtypeLocale);
+                mCachedLocaleObj = SubtypeLocaleUtils.constructLocaleFromString(mSubtypeLocale);
             }
             return mCachedLocaleObj;
         }
diff --git a/core/java/android/view/textservice/SpellCheckerSubtype.java b/core/java/android/view/textservice/SpellCheckerSubtype.java
index 026610e..d904d467 100644
--- a/core/java/android/view/textservice/SpellCheckerSubtype.java
+++ b/core/java/android/view/textservice/SpellCheckerSubtype.java
@@ -25,7 +25,7 @@
 import android.text.TextUtils;
 import android.util.Slog;
 
-import com.android.internal.inputmethod.InputMethodUtils;
+import com.android.internal.inputmethod.SubtypeLocaleUtils;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -228,7 +228,7 @@
         if (!TextUtils.isEmpty(mSubtypeLanguageTag)) {
             return Locale.forLanguageTag(mSubtypeLanguageTag);
         }
-        return InputMethodUtils.constructLocaleFromString(mSubtypeLocale);
+        return SubtypeLocaleUtils.constructLocaleFromString(mSubtypeLocale);
     }
 
     /**
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/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/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/accessibility/AccessibilityShortcutController.java b/core/java/com/android/internal/accessibility/AccessibilityShortcutController.java
index 90712fd..e83e79b 100644
--- a/core/java/com/android/internal/accessibility/AccessibilityShortcutController.java
+++ b/core/java/com/android/internal/accessibility/AccessibilityShortcutController.java
@@ -16,6 +16,10 @@
 
 package com.android.internal.accessibility;
 
+import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
+
+import static com.android.internal.util.ArrayUtils.convertToLongArray;
+
 import android.accessibilityservice.AccessibilityServiceInfo;
 import android.app.ActivityManager;
 import android.app.ActivityThread;
@@ -34,23 +38,23 @@
 import android.os.UserHandle;
 import android.os.Vibrator;
 import android.provider.Settings;
+import android.speech.tts.TextToSpeech;
+import android.speech.tts.Voice;
 import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.Slog;
 import android.view.Window;
 import android.view.WindowManager;
 import android.view.accessibility.AccessibilityManager;
-
 import android.widget.Toast;
+
 import com.android.internal.R;
+import com.android.internal.util.function.pooled.PooledLambda;
 
 import java.util.Collections;
+import java.util.Locale;
 import java.util.Map;
 
-import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
-
-import static com.android.internal.util.ArrayUtils.convertToLongArray;
-
 /**
  * Class to help manage the accessibility shortcut
  */
@@ -70,6 +74,7 @@
     private static Map<ComponentName, ToggleableFrameworkFeatureInfo> sFrameworkShortcutFeaturesMap;
 
     private final Context mContext;
+    private final Handler mHandler;
     private AlertDialog mAlertDialog;
     private boolean mIsShortcutEnabled;
     private boolean mEnabledOnLockScreen;
@@ -123,6 +128,7 @@
 
     public AccessibilityShortcutController(Context context, Handler handler, int initialUserId) {
         mContext = context;
+        mHandler = handler;
         mUserId = initialUserId;
 
         // Keep track of state of shortcut settings
@@ -189,22 +195,6 @@
         final int userId = ActivityManager.getCurrentUser();
         final int dialogAlreadyShown = Settings.Secure.getIntForUser(
                 cr, Settings.Secure.ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN, 0, userId);
-        // Use USAGE_ASSISTANCE_ACCESSIBILITY for TVs to ensure that TVs play the ringtone as they
-        // have less ways of providing feedback like vibration.
-        final int audioAttributesUsage = hasFeatureLeanback()
-                ? AudioAttributes.USAGE_ASSISTANCE_ACCESSIBILITY
-                : AudioAttributes.USAGE_NOTIFICATION_EVENT;
-
-        // Play a notification tone
-        final Ringtone tone =
-                RingtoneManager.getRingtone(mContext, Settings.System.DEFAULT_NOTIFICATION_URI);
-        if (tone != null) {
-            tone.setAudioAttributes(new AudioAttributes.Builder()
-                .setUsage(audioAttributesUsage)
-                .build());
-            tone.play();
-        }
-
         // Play a notification vibration
         Vibrator vibrator = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE);
         if ((vibrator != null) && vibrator.hasVibrator()) {
@@ -223,6 +213,9 @@
             if (mAlertDialog == null) {
                 return;
             }
+            if (!performTtsPrompt(mAlertDialog)) {
+                playNotificationTone();
+            }
             Window w = mAlertDialog.getWindow();
             WindowManager.LayoutParams attr = w.getAttributes();
             attr.type = TYPE_KEYGUARD_DIALOG;
@@ -231,6 +224,7 @@
             Settings.Secure.putIntForUser(
                     cr, Settings.Secure.ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN, 1, userId);
         } else {
+            playNotificationTone();
             if (mAlertDialog != null) {
                 mAlertDialog.dismiss();
                 mAlertDialog = null;
@@ -344,6 +338,102 @@
         return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK);
     }
 
+    private void playNotificationTone() {
+        // Use USAGE_ASSISTANCE_ACCESSIBILITY for TVs to ensure that TVs play the ringtone as they
+        // have less ways of providing feedback like vibration.
+        final int audioAttributesUsage = hasFeatureLeanback()
+                ? AudioAttributes.USAGE_ASSISTANCE_ACCESSIBILITY
+                : AudioAttributes.USAGE_NOTIFICATION_EVENT;
+
+        // Play a notification tone
+        final Ringtone tone = mFrameworkObjectProvider.getRingtone(mContext,
+                Settings.System.DEFAULT_NOTIFICATION_URI);
+        if (tone != null) {
+            tone.setAudioAttributes(new AudioAttributes.Builder()
+                    .setUsage(audioAttributesUsage)
+                    .build());
+            tone.play();
+        }
+    }
+
+    private boolean performTtsPrompt(AlertDialog alertDialog) {
+        final AccessibilityServiceInfo serviceInfo = getInfoForTargetService();
+        if (serviceInfo == null) {
+            return false;
+        }
+        if ((serviceInfo.flags & AccessibilityServiceInfo
+                .FLAG_REQUEST_SHORTCUT_WARNING_DIALOG_SPOKEN_FEEDBACK) == 0) {
+            return false;
+        }
+        final TtsPrompt tts = new TtsPrompt();
+        alertDialog.setOnDismissListener(dialog -> tts.dismiss());
+        return true;
+    }
+
+    /**
+     * Class to wrap TextToSpeech for shortcut dialog spoken feedback.
+     */
+    private class TtsPrompt implements TextToSpeech.OnInitListener {
+        private final CharSequence mText;
+        private boolean mDismiss;
+        private TextToSpeech mTts;
+
+        TtsPrompt() {
+            mText = mContext.getString(R.string.accessibility_shortcut_spoken_feedback);
+            mTts = mFrameworkObjectProvider.getTextToSpeech(mContext, this);
+        }
+
+        /**
+         * Releases the resources used by the TextToSpeech, when dialog dismiss.
+         */
+        public void dismiss() {
+            mDismiss = true;
+            mHandler.sendMessage(PooledLambda.obtainMessage(TextToSpeech::shutdown, mTts));
+        }
+
+        @Override
+        public void onInit(int status) {
+            if (status != TextToSpeech.SUCCESS) {
+                Slog.d(TAG, "Tts init fail, status=" + Integer.toString(status));
+                playNotificationTone();
+                return;
+            }
+            mHandler.sendMessage(PooledLambda.obtainMessage(TtsPrompt::play, this));
+        }
+
+        private void play() {
+            if (mDismiss) {
+                return;
+            }
+            int status = TextToSpeech.ERROR;
+            if (setLanguage(Locale.getDefault())) {
+                status = mTts.speak(mText, TextToSpeech.QUEUE_FLUSH, null, null);
+            }
+            if (status != TextToSpeech.SUCCESS) {
+                Slog.d(TAG, "Tts play fail");
+                playNotificationTone();
+            }
+        }
+
+        /**
+         * @return false if tts language is not available
+         */
+        private boolean setLanguage(final Locale locale) {
+            int status = mTts.isLanguageAvailable(locale);
+            if (status == TextToSpeech.LANG_MISSING_DATA
+                    || status == TextToSpeech.LANG_NOT_SUPPORTED) {
+                return false;
+            }
+            mTts.setLanguage(locale);
+            Voice voice = mTts.getVoice();
+            if (voice == null || (voice.getFeatures() != null && voice.getFeatures()
+                    .contains(TextToSpeech.Engine.KEY_FEATURE_NOT_INSTALLED))) {
+                return false;
+            }
+            return true;
+        }
+    }
+
     /**
      * Immutable class to hold info about framework features that can be controlled by shortcut
      */
@@ -406,5 +496,23 @@
         public Context getSystemUiContext() {
             return ActivityThread.currentActivityThread().getSystemUiContext();
         }
+
+        /**
+         * @param ctx A context for TextToSpeech
+         * @param listener TextToSpeech initialization callback
+         * @return TextToSpeech instance
+         */
+        public TextToSpeech getTextToSpeech(Context ctx, TextToSpeech.OnInitListener listener) {
+            return new TextToSpeech(ctx, listener);
+        }
+
+        /**
+         * @param ctx context for ringtone
+         * @param uri ringtone uri
+         * @return Ringtone instance
+         */
+        public Ringtone getRingtone(Context ctx, Uri uri) {
+            return RingtoneManager.getRingtone(ctx, uri);
+        }
     }
 }
diff --git a/core/java/com/android/internal/inputmethod/SubtypeLocaleUtils.java b/core/java/com/android/internal/inputmethod/SubtypeLocaleUtils.java
new file mode 100644
index 0000000..9ea4fa2
--- /dev/null
+++ b/core/java/com/android/internal/inputmethod/SubtypeLocaleUtils.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.inputmethod;
+
+import android.annotation.Nullable;
+import android.text.TextUtils;
+
+import java.util.Locale;
+
+/**
+ * A utility class to handle {@link Locale} related logic for
+ * {@link android.view.inputmethod.InputMethodSubtype} and
+ * {@link android.view.textservice.SpellCheckerSubtype}.
+ */
+public class SubtypeLocaleUtils {
+    /**
+     * Maintains deprecated logic about how subtype locales specified in XML resources have been
+     * parsed.
+     *
+     * <p>This logic is kept basically for compatibility purpose.  Consider relying on languageTag
+     * attribute instead.</p>
+     *
+     * @param localeStr string representation that is specified in the locale attribute
+     * @return {@link Locale} object parsed from {@code localeStr}. {@code null} for unexpected
+     *         format
+     *
+     * @attr ref android.R.styleable#InputMethod_Subtype_imeSubtypeLocale
+     * @attr ref android.R.styleable#InputMethod_Subtype_languageTag
+     * @attr ref android.R.styleable#SpellChecker_Subtype_languageTag
+     * @attr ref android.R.styleable#SpellChecker_Subtype_subtypeLocale
+     */
+    @Nullable
+    public static Locale constructLocaleFromString(String localeStr) {
+        if (TextUtils.isEmpty(localeStr)) {
+            return null;
+        }
+        // TODO: Use {@link Locale#toLanguageTag()} and {@link Locale#forLanguageTag(languageTag)}.
+        String[] localeParams = localeStr.split("_", 3);
+        if (localeParams.length >= 1 && "tl".equals(localeParams[0])) {
+            // Convert a locale whose language is "tl" to one whose language is "fil".
+            // For example, "tl_PH" will get converted to "fil_PH".
+            // Versions of Android earlier than Lollipop did not support three letter language
+            // codes, and used "tl" (Tagalog) as the language string for "fil" (Filipino).
+            // On Lollipop and above, the current three letter version must be used.
+            localeParams[0] = "fil";
+        }
+        // The length of localeStr is guaranteed to always return a 1 <= value <= 3
+        // because localeStr is not empty.
+        if (localeParams.length == 1) {
+            return new Locale(localeParams[0]);
+        } else if (localeParams.length == 2) {
+            return new Locale(localeParams[0], localeParams[1]);
+        } else if (localeParams.length == 3) {
+            return new Locale(localeParams[0], localeParams[1], localeParams[2]);
+        }
+        return null;
+    }
+}
diff --git a/core/java/com/android/internal/view/IInputConnectionWrapper.java b/core/java/com/android/internal/view/IInputConnectionWrapper.java
index 6f9c87a..ececba1 100644
--- a/core/java/com/android/internal/view/IInputConnectionWrapper.java
+++ b/core/java/com/android/internal/view/IInputConnectionWrapper.java
@@ -19,6 +19,7 @@
 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;
@@ -68,7 +69,7 @@
 
     @GuardedBy("mLock")
     @Nullable
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private InputConnection mInputConnection;
 
     private Looper mMainLooper;
diff --git a/core/java/com/android/internal/widget/PointerLocationView.java b/core/java/com/android/internal/widget/PointerLocationView.java
index 0b37d57..4773e16 100644
--- a/core/java/com/android/internal/widget/PointerLocationView.java
+++ b/core/java/com/android/internal/widget/PointerLocationView.java
@@ -840,7 +840,11 @@
                 scale *= 10;
             }
             value = (float) (Math.rint(value * scale) / scale);
-            
+
+            // Corner case: (int)-0.1 will become zero, so the negative sign gets lost
+            if ((int) value == 0 && value < 0) {
+                append("-");
+            }
             append((int) value);
 
             if (precision != 0) {
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.bp b/core/jni/Android.bp
index bb8ee14..762b430 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -230,7 +230,6 @@
     static_libs: [
         "libgif",
         "libseccomp_policy",
-        "libselinux",
         "libgrallocusage",
         "libscrypt_static",
     ],
diff --git a/core/proto/android/service/notification.proto b/core/proto/android/service/notification.proto
index ccbd027..8836c2e 100644
--- a/core/proto/android/service/notification.proto
+++ b/core/proto/android/service/notification.proto
@@ -200,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.
@@ -212,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/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 9ab55d6..814973d 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -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" />
@@ -4112,7 +4116,7 @@
     <!-- Allows an application to directly open the "Open by default" page inside a package's
          Details screen.
          @hide <p>Not for use by third-party applications. -->
-    <permission android:name="android.permission.OPEN_APPLICATION_DETAILS_OPEN_BY_DEFAULT_PAGE"
+    <permission android:name="android.permission.OPEN_APP_OPEN_BY_DEFAULT_SETTINGS"
                 android:protectionLevel="signature" />
 
     <!-- Allows hidden API checks to be disabled when starting a process.
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 2de2b9e..65b8807 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -3606,6 +3606,8 @@
             <flag name="flagRequestAccessibilityButton" value="0x00000100" />
             <!-- Has flag {@link android.accessibilityservice.AccessibilityServiceInfo#FLAG_REQUEST_FINGERPRINT_GESTURES}. -->
             <flag name="flagRequestFingerprintGestures" value="0x00000200" />
+            <!-- Has flag {@link android.accessibilityservice.AccessibilityServiceInfo#FLAG_REQUEST_SHORTCUT_WARNING_DIALOG_SPOKEN_FEEDBACK}. -->
+            <flag name="flagRequestShortcutWarningDialogSpokenFeedback" value="0x00000400" />
         </attr>
         <!-- Component name of an activity that allows the user to modify
              the settings for this service. This setting cannot be changed at runtime. -->
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 365e4a4..1a5b7b6 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -4334,6 +4334,9 @@
     <string name="accessibility_shortcut_disabling_service">Accessibility Shortcut turned
         <xliff:g id="service_name" example="TalkBack">%1$s</xliff:g> off</string>
 
+    <!-- Text spoken when accessibility shortcut warning dialog is shown. [CHAR LIMIT=none] -->
+    <string name="accessibility_shortcut_spoken_feedback">Use Accessibility Shortcut again to start the current accessibility feature</string>
+
     <!-- Text appearing in a prompt at the top of UI allowing the user to select a target service or feature to be assigned to the Accessibility button in the navigation bar. -->
     <string name="accessibility_button_prompt_text">Choose a feature to use when you tap the Accessibility button:</string>
 
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 7b6e064..7b8eced 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3083,6 +3083,7 @@
   <java-symbol type="string" name="color_inversion_feature_name" />
   <java-symbol type="string" name="color_correction_feature_name" />
   <java-symbol type="string" name="config_defaultAccessibilityService" />
+  <java-symbol type="string" name="accessibility_shortcut_spoken_feedback" />
 
   <!-- Accessibility Button -->
   <java-symbol type="layout" name="accessibility_button_chooser" />
diff --git a/core/tests/coretests/src/android/graphics/TypefaceSystemFallbackTest.java b/core/tests/coretests/src/android/graphics/TypefaceSystemFallbackTest.java
index 1c4039b..3ce2589 100644
--- a/core/tests/coretests/src/android/graphics/TypefaceSystemFallbackTest.java
+++ b/core/tests/coretests/src/android/graphics/TypefaceSystemFallbackTest.java
@@ -44,7 +44,7 @@
 import java.nio.charset.Charset;
 import java.nio.file.Files;
 import java.nio.file.StandardCopyOption;
-import java.util.HashSet;
+import java.util.ArrayList;
 import java.util.Locale;
 
 @SmallTest
@@ -112,7 +112,7 @@
 
     private static void buildSystemFallback(String xml,
             ArrayMap<String, Typeface> fontMap, ArrayMap<String, FontFamily[]> fallbackMap) {
-        final HashSet<Font> availableFonts = new HashSet<>();
+        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) {
@@ -127,7 +127,7 @@
     public void testBuildSystemFallback() {
         final ArrayMap<String, Typeface> fontMap = new ArrayMap<>();
         final ArrayMap<String, FontFamily[]> fallbackMap = new ArrayMap<>();
-        final HashSet<Font> availableFonts = new HashSet<>();
+        final ArrayList<Font> availableFonts = new ArrayList<>();
 
         final FontConfig.Alias[] aliases = SystemFonts.buildSystemFallback(SYSTEM_FONTS_XML,
                 SYSTEM_FONT_DIR, fallbackMap, availableFonts);
diff --git a/core/tests/coretests/src/android/text/FontFallbackSetup.java b/core/tests/coretests/src/android/text/FontFallbackSetup.java
index 355be61..898e78c 100644
--- a/core/tests/coretests/src/android/text/FontFallbackSetup.java
+++ b/core/tests/coretests/src/android/text/FontFallbackSetup.java
@@ -33,7 +33,7 @@
 import java.nio.charset.Charset;
 import java.nio.file.Files;
 import java.nio.file.StandardCopyOption;
-import java.util.HashSet;
+import java.util.ArrayList;
 
 public class FontFallbackSetup implements AutoCloseable {
     private final String[] mTestFontFiles;
@@ -76,7 +76,7 @@
         }
 
         final ArrayMap<String, FontFamily[]> fallbackMap = new ArrayMap<>();
-        final HashSet<Font> availableFonts = new HashSet<>();
+        final ArrayList<Font> availableFonts = new ArrayList<>();
         final FontConfig.Alias[] aliases = SystemFonts.buildSystemFallback(testFontsXml,
                 mTestFontsDir, fallbackMap, availableFonts);
         Typeface.initSystemDefaultTypefaces(mFontMap, fallbackMap, aliases);
diff --git a/core/tests/coretests/src/com/android/internal/accessibility/AccessibilityShortcutControllerTest.java b/core/tests/coretests/src/com/android/internal/accessibility/AccessibilityShortcutControllerTest.java
index f3e10e0..a302657 100644
--- a/core/tests/coretests/src/com/android/internal/accessibility/AccessibilityShortcutControllerTest.java
+++ b/core/tests/coretests/src/com/android/internal/accessibility/AccessibilityShortcutControllerTest.java
@@ -16,6 +16,31 @@
 
 package com.android.internal.accessibility;
 
+import static android.provider.Settings.Secure.ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN;
+import static android.provider.Settings.Secure.ACCESSIBILITY_SHORTCUT_ENABLED;
+import static android.provider.Settings.Secure.ACCESSIBILITY_SHORTCUT_ON_LOCK_SCREEN;
+import static android.provider.Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+
+import static org.junit.Assert.fail;
+import static org.mockito.AdditionalMatchers.aryEq;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.Matchers.anyBoolean;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyObject;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
+
 import android.accessibilityservice.AccessibilityServiceInfo;
 import android.app.AlertDialog;
 import android.content.ComponentName;
@@ -25,11 +50,14 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.res.Resources;
+import android.media.Ringtone;
 import android.os.Handler;
+import android.os.Message;
 import android.os.Vibrator;
 import android.provider.Settings;
+import android.speech.tts.TextToSpeech;
+import android.speech.tts.Voice;
 import android.support.test.runner.AndroidJUnit4;
-
 import android.test.mock.MockContentResolver;
 import android.text.TextUtils;
 import android.view.Window;
@@ -37,9 +65,10 @@
 import android.view.accessibility.AccessibilityManager;
 import android.view.accessibility.IAccessibilityManager;
 import android.widget.Toast;
+
 import com.android.internal.R;
-import com.android.internal.util.test.FakeSettingsProvider;
 import com.android.internal.accessibility.AccessibilityShortcutController.FrameworkObjectProvider;
+import com.android.internal.util.test.FakeSettingsProvider;
 
 import org.junit.After;
 import org.junit.Before;
@@ -48,31 +77,12 @@
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
 
 import java.lang.reflect.Field;
 import java.util.Collections;
 import java.util.Map;
 
-import static android.provider.Settings.Secure.ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN;
-import static android.provider.Settings.Secure.ACCESSIBILITY_SHORTCUT_ENABLED;
-import static android.provider.Settings.Secure.ACCESSIBILITY_SHORTCUT_ON_LOCK_SCREEN;
-import static android.provider.Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE;
-import static junit.framework.Assert.assertEquals;
-import static junit.framework.Assert.assertFalse;
-import static junit.framework.Assert.assertTrue;
-
-import static org.junit.Assert.fail;
-import static org.mockito.AdditionalMatchers.aryEq;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Matchers.anyBoolean;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyObject;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyZeroInteractions;
-import static org.mockito.Mockito.when;
 
 @RunWith(AndroidJUnit4.class)
 public class AccessibilityShortcutControllerTest {
@@ -102,6 +112,9 @@
     private @Mock Vibrator mVibrator;
     private @Mock ApplicationInfo mApplicationInfo;
     private @Mock PackageManager mPackageManager;
+    private @Mock TextToSpeech mTextToSpeech;
+    private @Mock Voice mVoice;
+    private @Mock Ringtone mRingtone;
 
     private MockContentResolver mContentResolver;
     private WindowManager.LayoutParams mLayoutParams = new WindowManager.LayoutParams();
@@ -137,6 +150,9 @@
         when(mFrameworkObjectProvider.makeToastFromText(eq(mContext), anyObject(), anyInt()))
                 .thenReturn(mToast);
         when(mFrameworkObjectProvider.getSystemUiContext()).thenReturn(mContext);
+        when(mFrameworkObjectProvider.getTextToSpeech(eq(mContext), any()))
+                .thenReturn(mTextToSpeech);
+        when(mFrameworkObjectProvider.getRingtone(eq(mContext), any())).thenReturn(mRingtone);
 
         when(mResources.getString(anyInt())).thenReturn("Howdy %s");
         when(mResources.getIntArray(anyInt())).thenReturn(VIBRATOR_PATTERN_INT);
@@ -172,6 +188,8 @@
             throw new RuntimeException("Unable to set mWindowAttributes", e);
         }
         when(mAlertDialog.getWindow()).thenReturn(window);
+
+        when(mTextToSpeech.getVoice()).thenReturn(mVoice);
     }
 
     @After
@@ -308,8 +326,10 @@
                 mContentResolver, ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN, 0));
         verify(mResources).getString(R.string.accessibility_shortcut_toogle_warning);
         verify(mAlertDialog).show();
-        verify(mAccessibilityManagerService).getInstalledAccessibilityServiceList(anyInt());
+        verify(mAccessibilityManagerService, atLeastOnce()).getInstalledAccessibilityServiceList(
+                anyInt());
         verify(mAccessibilityManagerService, times(0)).performAccessibilityShortcut();
+        verify(mFrameworkObjectProvider, times(0)).getTextToSpeech(any(), any());
     }
 
     @Test
@@ -434,6 +454,49 @@
         verify(mAccessibilityManagerService).performAccessibilityShortcut();
     }
 
+    @Test
+    public void testOnAccessibilityShortcut_showsWarningDialog_shouldTtsSpokenPrompt() {
+        configureShortcutEnabled(ENABLED_EXCEPT_LOCK_SCREEN);
+        configureValidShortcutService();
+        configureTtsSpokenPromptEnabled();
+        configureHandlerCallbackInvocation();
+        AccessibilityShortcutController accessibilityShortcutController = getController();
+        Settings.Secure.putInt(mContentResolver, ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN, 0);
+        accessibilityShortcutController.performAccessibilityShortcut();
+
+        verify(mAlertDialog).show();
+        ArgumentCaptor<TextToSpeech.OnInitListener> onInitCap = ArgumentCaptor.forClass(
+                TextToSpeech.OnInitListener.class);
+        verify(mFrameworkObjectProvider).getTextToSpeech(any(), onInitCap.capture());
+        onInitCap.getValue().onInit(TextToSpeech.SUCCESS);
+        verify(mTextToSpeech).speak(any(), eq(TextToSpeech.QUEUE_FLUSH), any(), any());
+        ArgumentCaptor<DialogInterface.OnDismissListener> onDismissCap = ArgumentCaptor.forClass(
+                DialogInterface.OnDismissListener.class);
+        verify(mAlertDialog).setOnDismissListener(onDismissCap.capture());
+        onDismissCap.getValue().onDismiss(mAlertDialog);
+        verify(mTextToSpeech).shutdown();
+        verify(mRingtone, times(0)).play();
+    }
+
+    @Test
+    public void testOnAccessibilityShortcut_showsWarningDialog_ttsInitFail_noSpokenPrompt() {
+        configureShortcutEnabled(ENABLED_EXCEPT_LOCK_SCREEN);
+        configureValidShortcutService();
+        configureTtsSpokenPromptEnabled();
+        configureHandlerCallbackInvocation();
+        AccessibilityShortcutController accessibilityShortcutController = getController();
+        Settings.Secure.putInt(mContentResolver, ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN, 0);
+        accessibilityShortcutController.performAccessibilityShortcut();
+
+        verify(mAlertDialog).show();
+        ArgumentCaptor<TextToSpeech.OnInitListener> onInitCap = ArgumentCaptor.forClass(
+                TextToSpeech.OnInitListener.class);
+        verify(mFrameworkObjectProvider).getTextToSpeech(any(), onInitCap.capture());
+        onInitCap.getValue().onInit(TextToSpeech.ERROR);
+        verify(mTextToSpeech, times(0)).speak(any(), anyInt(), any(), any());
+        verify(mRingtone).play();
+    }
+
     private void configureNoShortcutService() {
         Settings.Secure.putString(mContentResolver, ACCESSIBILITY_SHORTCUT_TARGET_SERVICE, "");
     }
@@ -481,6 +544,19 @@
                 mContentResolver, ACCESSIBILITY_SHORTCUT_ON_LOCK_SCREEN, lockscreen ? 1 : 0);
     }
 
+    private void configureTtsSpokenPromptEnabled() {
+        mServiceInfo.flags |= AccessibilityServiceInfo
+                .FLAG_REQUEST_SHORTCUT_WARNING_DIALOG_SPOKEN_FEEDBACK;
+    }
+
+    private void configureHandlerCallbackInvocation() {
+        doAnswer((InvocationOnMock invocation) -> {
+            Message m = (Message) invocation.getArguments()[0];
+            m.getCallback().run();
+            return true;
+        }).when(mHandler).sendMessageAtTime(any(), anyLong());
+    }
+
     private AccessibilityShortcutController getController() {
         AccessibilityShortcutController accessibilityShortcutController =
                 new AccessibilityShortcutController(mContext, mHandler, 0);
diff --git a/core/tests/coretests/src/com/android/internal/inputmethod/SubtypeLocaleUtilsTest.java b/core/tests/coretests/src/com/android/internal/inputmethod/SubtypeLocaleUtilsTest.java
new file mode 100644
index 0000000..8179328
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/inputmethod/SubtypeLocaleUtilsTest.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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 static org.junit.Assert.assertEquals;
+
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Locale;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class SubtypeLocaleUtilsTest {
+    private static final Locale LOCALE_EN = new Locale("en");
+    private static final Locale LOCALE_EN_US = new Locale("en", "US");
+    private static final Locale LOCALE_EN_GB = new Locale("en", "GB");
+    private static final Locale LOCALE_EN_IN = new Locale("en", "IN");
+    private static final Locale LOCALE_FIL = new Locale("fil");
+    private static final Locale LOCALE_FIL_PH = new Locale("fil", "PH");
+    private static final Locale LOCALE_JA = new Locale("ja");
+    private static final Locale LOCALE_JA_JP = new Locale("ja", "JP");
+    private static final Locale LOCALE_TH = new Locale("ht");
+    private static final Locale LOCALE_TH_TH = new Locale("ht", "TH");
+    private static final Locale LOCALE_TH_TH_TH = new Locale("ht", "TH", "TH");
+
+    @Test
+    public void testConstructLocaleFromString() throws Exception {
+        assertEquals(new Locale("en"), SubtypeLocaleUtils.constructLocaleFromString("en"));
+        assertEquals(new Locale("en", "US"), SubtypeLocaleUtils.constructLocaleFromString("en_US"));
+        assertEquals(new Locale("en", "US", "POSIX"),
+                SubtypeLocaleUtils.constructLocaleFromString("en_US_POSIX"));
+
+        // Special rewrite rule for "tl" for versions of Android earlier than Lollipop that did not
+        // support three letter language codes, and used "tl" (Tagalog) as the language string for
+        // "fil" (Filipino).
+        assertEquals(new Locale("fil"), SubtypeLocaleUtils.constructLocaleFromString("tl"));
+        assertEquals(new Locale("fil", "PH"),
+                SubtypeLocaleUtils.constructLocaleFromString("tl_PH"));
+        assertEquals(new Locale("fil", "PH", "POSIX"),
+                SubtypeLocaleUtils.constructLocaleFromString("tl_PH_POSIX"));
+
+        // So far rejecting an invalid/unexpected locale string is out of the scope of this method.
+        assertEquals(new Locale("a"), SubtypeLocaleUtils.constructLocaleFromString("a"));
+        assertEquals(new Locale("a b c"), SubtypeLocaleUtils.constructLocaleFromString("a b c"));
+        assertEquals(new Locale("en-US"), SubtypeLocaleUtils.constructLocaleFromString("en-US"));
+    }
+}
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 616a8d6..114c228 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -281,6 +281,7 @@
         <permission name="android.permission.MANAGE_FINGERPRINT"/>
         <permission name="android.permission.MODIFY_PHONE_STATE"/>
         <permission name="android.permission.READ_SEARCH_INDEXABLES"/>
+        <permission name="android.permission.WRITE_SETTINGS_HOMEPAGE_DATA"/>
     </privapp-permissions>
 
     <privapp-permissions package="com.android.sharedstoragebackup">
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/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/Typeface.java b/graphics/java/android/graphics/Typeface.java
index 5aa09ce..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;
@@ -1076,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 a337773..7efe522 100644
--- a/graphics/java/android/graphics/drawable/Icon.java
+++ b/graphics/java/android/graphics/drawable/Icon.java
@@ -34,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;
@@ -101,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;
@@ -118,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
@@ -174,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);
@@ -189,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);
@@ -203,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);
diff --git a/graphics/java/android/graphics/fonts/Font.java b/graphics/java/android/graphics/fonts/Font.java
index 8aa4845..1458c66 100644
--- a/graphics/java/android/graphics/fonts/Font.java
+++ b/graphics/java/android/graphics/fonts/Font.java
@@ -119,7 +119,7 @@
 
         private @Nullable ByteBuffer mBuffer;
         private @Nullable File mFile;
-        private @NonNull LocaleList mLocaleList = LocaleList.getEmptyLocaleList();
+        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;
@@ -150,7 +150,7 @@
          * @hide
          */
         public Builder(@NonNull ByteBuffer buffer, @NonNull File path,
-                @NonNull LocaleList localeList) {
+                @NonNull String localeList) {
             this(buffer);
             mFile = path;
             mLocaleList = localeList;
@@ -457,7 +457,7 @@
     private final boolean mItalic;
     private final @IntRange(from = 0) int mTtcIndex;
     private final @Nullable FontVariationAxis[] mAxes;
-    private final @NonNull LocaleList mLocaleList;
+    private final @NonNull String mLocaleList;
 
     /**
      * Use Builder instead
@@ -465,7 +465,7 @@
     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,
-            @NonNull LocaleList localeList) {
+            @NonNull String localeList) {
         mBuffer = buffer;
         mFile = file;
         mWeight = weight;
@@ -546,7 +546,7 @@
      * @return a locale list
      */
     public @NonNull LocaleList getLocaleList() {
-        return mLocaleList;
+        return LocaleList.forLanguageTags(mLocaleList);
     }
 
     /** @hide */
@@ -580,7 +580,7 @@
             + ", italic=" + mItalic
             + ", ttcIndex=" + mTtcIndex
             + ", axes=" + FontVariationAxis.toFontVariationSettings(mAxes)
-            + ", localeList=" + mLocaleList.toLanguageTags()
+            + ", localeList=" + mLocaleList
             + ", buffer=" + mBuffer
             + "}";
     }
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 1c957b8..f4a2199 100644
--- a/graphics/java/android/graphics/fonts/SystemFonts.java
+++ b/graphics/java/android/graphics/fonts/SystemFonts.java
@@ -19,7 +19,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.graphics.FontListParser;
-import android.os.LocaleList;
 import android.text.FontConfig;
 import android.util.ArrayMap;
 import android.util.Log;
@@ -54,7 +53,7 @@
 
     private static final Map<String, FontFamily[]> sSystemFallbackMap;
     private static final FontConfig.Alias[] sAliases;
-    private static final Set<Font> sAvailableFonts;
+    private static final List<Font> sAvailableFonts;
 
     /**
      * Returns all available font files in the system.
@@ -63,7 +62,9 @@
      * @return an array of system fonts
      */
     public static @NonNull Set<Font> getAvailableFonts() {
-        return sAvailableFonts;
+        HashSet<Font> set = new HashSet<>();
+        set.addAll(sAvailableFonts);
+        return set;
     }
 
     /**
@@ -114,7 +115,7 @@
             @NonNull ArrayMap<String, ArrayList<FontFamily>> fallbackMap,
             @NonNull Map<String, ByteBuffer> cache,
             @NonNull String fontDir,
-            @NonNull HashSet<Font> availableFonts) {
+            @NonNull ArrayList<Font> availableFonts) {
 
         final String languageTags = xmlFamily.getLanguages();
         final int variant = xmlFamily.getVariant();
@@ -170,13 +171,12 @@
             @FontConfig.Family.Variant int variant,
             @NonNull Map<String, ByteBuffer> cache,
             @NonNull String fontDir,
-            @NonNull HashSet<Font> availableFonts) {
+            @NonNull ArrayList<Font> availableFonts) {
         if (fonts.size() == 0) {
             return null;
         }
 
         FontFamily.Builder b = null;
-        final LocaleList localeList = LocaleList.forLanguageTags(languageTags);
         for (int i = 0; i < fonts.size(); i++) {
             final FontConfig.Font fontConfig = fonts.get(i);
             final String fullPath = fontDir + fontConfig.getFontName();
@@ -194,7 +194,7 @@
 
             final Font font;
             try {
-                font = new Font.Builder(buffer, new File(fullPath), localeList)
+                font = new Font.Builder(buffer, new File(fullPath), languageTags)
                         .setWeight(fontConfig.getWeight())
                         .setItalic(fontConfig.isItalic())
                         .setTtcIndex(fontConfig.getTtcIndex())
@@ -228,7 +228,7 @@
     public static FontConfig.Alias[] buildSystemFallback(@NonNull String xmlPath,
             @NonNull String fontDir,
             @NonNull ArrayMap<String, FontFamily[]> fallbackMap,
-            @NonNull HashSet<Font> availableFonts) {
+            @NonNull ArrayList<Font> availableFonts) {
         try {
             final FileInputStream fontsIn = new FileInputStream(xmlPath);
             final FontConfig fontConfig = FontListParser.parse(fontsIn);
@@ -284,11 +284,11 @@
 
     static {
         final ArrayMap<String, FontFamily[]> systemFallbackMap = new ArrayMap<>();
-        final HashSet<Font> availableFonts = new HashSet<>();
+        final ArrayList<Font> availableFonts = new ArrayList<>();
         sAliases = buildSystemFallback("/system/etc/fonts.xml", "/system/fonts/",
                 systemFallbackMap, availableFonts);
         sSystemFallbackMap = Collections.unmodifiableMap(systemFallbackMap);
-        sAvailableFonts = Collections.unmodifiableSet(availableFonts);
+        sAvailableFonts = Collections.unmodifiableList(availableFonts);
     }
 
 }
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index 04bbe24..b011363 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -247,7 +247,7 @@
         // Enables fine-grained GLES error checking
         // If enabled, every GLES call is wrapped & error checked
         // Has moderate overhead
-        "hwui_enable_opengl_validation",
+        //"hwui_enable_opengl_validation",
     ],
 }
 
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/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/pipeline/skia/SkiaOpenGLPipeline.cpp b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
index d58b59e..3b1ebd6 100644
--- a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
@@ -27,6 +27,8 @@
 #include "utils/GLUtils.h"
 #include "utils/TraceUtils.h"
 
+#include <GLES3/gl3.h>
+
 #include <GrBackendSurface.h>
 #include <SkBlendMode.h>
 #include <SkImageInfo.h>
@@ -62,21 +64,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);
@@ -89,8 +93,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
@@ -147,8 +150,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) {
@@ -168,6 +170,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 808685a..fbdf313 100644
--- a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h
@@ -34,8 +34,7 @@
     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,
@@ -46,6 +45,8 @@
     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/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 611a34c..5cbe33d 100644
--- a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
@@ -63,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();
@@ -72,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
@@ -139,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 900b054..6e723a8 100644
--- a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h
+++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h
@@ -32,8 +32,7 @@
     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,
@@ -44,6 +43,8 @@
     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/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 727cef3..ea6a851 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -151,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;
@@ -416,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;
@@ -555,8 +556,7 @@
     // 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);
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 02ee72f..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);
     }
 
     /**
diff --git a/libs/hwui/renderthread/EglManager.cpp b/libs/hwui/renderthread/EglManager.cpp
index 5f8d7ad..675df41 100644
--- a/libs/hwui/renderthread/EglManager.cpp
+++ b/libs/hwui/renderthread/EglManager.cpp
@@ -20,6 +20,7 @@
 #include <log/log.h>
 #include <private/gui/SyncFeatures.h>
 #include <utils/Trace.h>
+#include "utils/Color.h"
 #include "utils/StringUtils.h"
 
 #include "DeviceInfo.h"
@@ -27,6 +28,7 @@
 #include "Properties.h"
 
 #include <EGL/eglext.h>
+#include <GLES/gl.h>
 
 #include <string>
 #include <vector>
@@ -75,6 +77,7 @@
     bool pixelFormatFloat = false;
     bool glColorSpace = false;
     bool scRGB = false;
+    bool displayP3 = false;
     bool contextPriority = false;
     bool surfacelessContext = false;
 } EglExtensions;
@@ -125,6 +128,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() {
@@ -148,6 +162,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");
 }
@@ -160,6 +175,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,
@@ -255,11 +274,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
@@ -269,9 +289,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
@@ -279,7 +299,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
@@ -291,13 +311,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
     }
diff --git a/libs/hwui/renderthread/EglManager.h b/libs/hwui/renderthread/EglManager.h
index 507673a..e97228c 100644
--- a/libs/hwui/renderthread/EglManager.h
+++ b/libs/hwui/renderthread/EglManager.h
@@ -18,11 +18,13 @@
 
 #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 {
@@ -45,7 +47,7 @@
 
     bool hasEglContext();
 
-    EGLSurface createSurface(EGLNativeWindowType window, bool wideColorGamut);
+    EGLSurface createSurface(EGLNativeWindowType window, ColorMode colorMode);
     void destroySurface(EGLSurface surface);
 
     void destroy();
@@ -76,6 +78,9 @@
     // 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();
@@ -89,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 b7b7853..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,7 +68,7 @@
     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,
@@ -67,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/VulkanManager.h b/libs/hwui/renderthread/VulkanManager.h
index ebc11a5..7a539ae 100644
--- a/libs/hwui/renderthread/VulkanManager.h
+++ b/libs/hwui/renderthread/VulkanManager.h
@@ -118,6 +118,10 @@
     // 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/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/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/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/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/media/java/android/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java
index 5ad7365..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
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/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/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/native/android/Android.bp b/native/android/Android.bp
index 43847cc..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",
     ],
 
@@ -65,6 +66,7 @@
         "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/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 fee2a25..7f71f63 100644
--- a/native/webview/loader/loader.cpp
+++ b/native/webview/loader/loader.cpp
@@ -26,6 +26,7 @@
 #include <string.h>
 #include <unistd.h>
 #include <sys/mman.h>
+#include <sys/prctl.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 
@@ -58,6 +59,7 @@
           vsize, strerror(errno));
     return JNI_FALSE;
   }
+  prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, addr, vsize, "libwebview reservation");
   gReservedAddress = addr;
   gReservedSize = vsize;
   ALOGV("Reserved %zd bytes at %p", vsize, addr);
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/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/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/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 290a4f8..63978ba 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -2948,7 +2948,7 @@
         }
 
         private final class UpgradeController {
-            private static final int SETTINGS_VERSION = 171;
+            private static final int SETTINGS_VERSION = 172;
 
             private final int mUserId;
 
@@ -3900,6 +3900,37 @@
                     currentVersion = 171;
                 }
 
+                if (currentVersion == 171) {
+                    // Version 171: by default, add STREAM_VOICE_CALL to list of streams that can
+                    // be muted.
+                    final SettingsState systemSettings = getSystemSettingsLocked(userId);
+                    final Setting currentSetting = systemSettings.getSettingLocked(
+                              Settings.System.MUTE_STREAMS_AFFECTED);
+                    if (!currentSetting.isNull()) {
+                        try {
+                            int currentSettingIntegerValue = Integer.parseInt(
+                                    currentSetting.getValue());
+                            if ((currentSettingIntegerValue
+                                 & (1 << AudioManager.STREAM_VOICE_CALL)) == 0) {
+                                systemSettings.insertSettingLocked(
+                                    Settings.System.MUTE_STREAMS_AFFECTED,
+                                    Integer.toString(
+                                        currentSettingIntegerValue
+                                        | (1 << AudioManager.STREAM_VOICE_CALL)),
+                                    null, true, SettingsState.SYSTEM_PACKAGE_NAME);
+                            }
+                        } catch (NumberFormatException e) {
+                            // remove the setting in case it is not a valid integer
+                            Slog.w("Failed to parse integer value of MUTE_STREAMS_AFFECTED"
+                                   + "setting, removing setting", e);
+                            systemSettings.deleteSettingLocked(
+                                Settings.System.MUTE_STREAMS_AFFECTED);
+                        }
+
+                    }
+                    currentVersion = 172;
+                }
+
                 // vXXX: Add new settings above this point.
 
                 if (currentVersion != newVersion) {
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/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index e31dd1e..3725940 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -216,6 +216,7 @@
 
     <protected-broadcast android:name="com.android.settingslib.action.REGISTER_SLICE_RECEIVER" />
     <protected-broadcast android:name="com.android.settingslib.action.UNREGISTER_SLICE_RECEIVER" />
+    <protected-broadcast android:name="com.android.settings.flashlight.action.FLASHLIGHT_CHANGED" />
 
     <application
         android:name=".SystemUIApplication"
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/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 7ec4db2..7316c02dd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -732,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(
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/tests/AndroidManifest.xml b/packages/SystemUI/tests/AndroidManifest.xml
index 8b1324a..e73c70b 100644
--- a/packages/SystemUI/tests/AndroidManifest.xml
+++ b/packages/SystemUI/tests/AndroidManifest.xml
@@ -17,6 +17,7 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
     xmlns:tools="http://schemas.android.com/tools"
+    android:sharedUserId="android.uid.system"
     package="com.android.systemui.tests">
 
     <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
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/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java b/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
index 371f932..cf9f233 100644
--- a/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
+++ b/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
@@ -170,6 +170,20 @@
      *                action.
      */
     public TouchExplorer(Context context, AccessibilityManagerService service) {
+        this(context, service, null);
+    }
+
+    /**
+     * Creates a new instance.
+     *
+     * @param context A context handle for accessing resources.
+     * @param service The service to notify touch interaction and gesture completed and to perform
+     *                action.
+     * @param detector The gesture detector to handle accessibility touch event. If null the default
+     *                one created in place, or for testing purpose.
+     */
+    public TouchExplorer(Context context, AccessibilityManagerService service,
+            AccessibilityGestureDetector detector) {
         mContext = context;
         mAms = service;
         mReceivedPointerTracker = new ReceivedPointerTracker();
@@ -186,7 +200,11 @@
         mSendTouchInteractionEndDelayed = new SendAccessibilityEventDelayed(
                 AccessibilityEvent.TYPE_TOUCH_INTERACTION_END,
                 mDetermineUserIntentTimeout);
-        mGestureDetector = new AccessibilityGestureDetector(context, this);
+        if (detector == null) {
+            mGestureDetector = new AccessibilityGestureDetector(context, this);
+        } else {
+            mGestureDetector = detector;
+        }
         final float density = context.getResources().getDisplayMetrics().density;
         mScaledMinPointerDistanceToUseMiddleLocation =
             (int) (MIN_POINTER_DISTANCE_TO_USE_MIDDLE_LOCATION_DIP * density);
diff --git a/services/core/java/com/android/server/BinderCallsStatsService.java b/services/core/java/com/android/server/BinderCallsStatsService.java
index 15673a7..51d95a2 100644
--- a/services/core/java/com/android/server/BinderCallsStatsService.java
+++ b/services/core/java/com/android/server/BinderCallsStatsService.java
@@ -118,10 +118,22 @@
             this.mBinderCallsStats = binderCallsStats;
         }
 
+        /** @see BinderCallsStats#reset */
+        public void reset() {
+            mBinderCallsStats.reset();
+        }
+
+        /**
+         * @see BinderCallsStats#getExportedCallStats.
+         *
+         * Note that binder calls stats will be reset by statsd every time
+         * the data is exported.
+         */
         public ArrayList<BinderCallsStats.ExportedCallStat> getExportedCallStats() {
             return mBinderCallsStats.getExportedCallStats();
         }
 
+        /** @see BinderCallsStats#getExportedExceptionStats */
         public ArrayMap<String, Integer> getExportedExceptionStats() {
             return mBinderCallsStats.getExportedExceptionStats();
         }
diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java
index 2c8f2fc..3a0289c 100644
--- a/services/core/java/com/android/server/am/ActivityManagerConstants.java
+++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java
@@ -68,6 +68,7 @@
     static final String KEY_BOUND_SERVICE_CRASH_MAX_RETRY = "service_crash_max_retry";
     static final String KEY_PROCESS_START_ASYNC = "process_start_async";
     static final String KEY_MEMORY_INFO_THROTTLE_TIME = "memory_info_throttle_time";
+    static final String KEY_TOP_TO_FGS_GRACE_DURATION = "top_to_fgs_grace_duration";
 
     private static final int DEFAULT_MAX_CACHED_PROCESSES = 32;
     private static final long DEFAULT_BACKGROUND_SETTLE_TIME = 60*1000;
@@ -97,6 +98,7 @@
     private static final int DEFAULT_BOUND_SERVICE_CRASH_MAX_RETRY = 16;
     private static final boolean DEFAULT_PROCESS_START_ASYNC = true;
     private static final long DEFAULT_MEMORY_INFO_THROTTLE_TIME = 5*60*1000;
+    private static final long DEFAULT_TOP_TO_FGS_GRACE_DURATION = 15 * 1000;
 
     // Maximum number of cached processes we will allow.
     public int MAX_CACHED_PROCESSES = DEFAULT_MAX_CACHED_PROCESSES;
@@ -212,6 +214,10 @@
     // throttle requests from apps.
     public long MEMORY_INFO_THROTTLE_TIME = DEFAULT_MEMORY_INFO_THROTTLE_TIME;
 
+    // Allow app just moving from TOP to FOREGROUND_SERVICE to stay in a higher adj value for
+    // this long.
+    public long TOP_TO_FGS_GRACE_DURATION = DEFAULT_TOP_TO_FGS_GRACE_DURATION;
+
     // Indicates whether the activity starts logging is enabled.
     // Controlled by Settings.Global.ACTIVITY_STARTS_LOGGING_ENABLED
     boolean mFlagActivityStartsLoggingEnabled;
@@ -355,6 +361,8 @@
                     DEFAULT_PROCESS_START_ASYNC);
             MEMORY_INFO_THROTTLE_TIME = mParser.getLong(KEY_MEMORY_INFO_THROTTLE_TIME,
                     DEFAULT_MEMORY_INFO_THROTTLE_TIME);
+            TOP_TO_FGS_GRACE_DURATION = mParser.getDurationMillis(KEY_TOP_TO_FGS_GRACE_DURATION,
+                    DEFAULT_TOP_TO_FGS_GRACE_DURATION);
 
             updateMaxCachedProcesses();
         }
@@ -438,6 +446,8 @@
         pw.println(FLAG_PROCESS_START_ASYNC);
         pw.print("  "); pw.print(KEY_MEMORY_INFO_THROTTLE_TIME); pw.print("=");
         pw.println(MEMORY_INFO_THROTTLE_TIME);
+        pw.print("  "); pw.print(KEY_TOP_TO_FGS_GRACE_DURATION); pw.print("=");
+        pw.println(TOP_TO_FGS_GRACE_DURATION);
 
         pw.println();
         if (mOverrideMaxCachedProcesses >= 0) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index b64e8b8..7533db1 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -17778,6 +17778,19 @@
             }
         }
 
+        // If the app was recently in the foreground and moved to a foreground service status,
+        // allow it to get a higher rank in memory for some time, compared to other foreground
+        // services so that it can finish performing any persistence/processing of in-memory state.
+        if (app.hasForegroundServices() && adj > ProcessList.PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ
+                && (app.lastTopTime + mConstants.TOP_TO_FGS_GRACE_DURATION > now
+                    || app.setProcState <= ActivityManager.PROCESS_STATE_TOP)) {
+            adj = ProcessList.PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ;
+            app.adjType = "fg-service-act";
+            if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
+                reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to recent fg: " + app);
+            }
+        }
+
         if (adj > ProcessList.PERCEPTIBLE_APP_ADJ
                 || procState > ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND) {
             if (app.forcingToImportant != null) {
@@ -18045,6 +18058,10 @@
                                         cr.trackProcState(procState, mAdjSeq, now);
                                         trackedProcState = true;
                                     }
+                                } else if ((cr.flags & Context.BIND_ADJUST_BELOW_PERCEPTIBLE) != 0
+                                        && clientAdj < ProcessList.PERCEPTIBLE_APP_ADJ
+                                        && adj > ProcessList.PERCEPTIBLE_APP_ADJ + 1) {
+                                    newAdj = ProcessList.PERCEPTIBLE_APP_ADJ + 1;
                                 } else if ((cr.flags&Context.BIND_NOT_VISIBLE) != 0
                                         && clientAdj < ProcessList.PERCEPTIBLE_APP_ADJ
                                         && adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
@@ -19044,6 +19061,8 @@
             // Must be called before updating setProcState
             maybeUpdateUsageStatsLocked(app, nowElapsed);
 
+            maybeUpdateLastTopTime(app, now);
+
             app.setProcState = app.curProcState;
             if (app.setProcState >= ActivityManager.PROCESS_STATE_HOME) {
                 app.notCachedSinceIdle = false;
@@ -19268,6 +19287,13 @@
         }
     }
 
+    private void maybeUpdateLastTopTime(ProcessRecord app, long nowUptime) {
+        if (app.setProcState <= ActivityManager.PROCESS_STATE_TOP
+                && app.curProcState > ActivityManager.PROCESS_STATE_TOP) {
+            app.lastTopTime = nowUptime;
+        }
+    }
+
     private final void setProcessTrackerStateLocked(ProcessRecord proc, int memFactor, long now) {
         if (proc.thread != null && proc.baseProcessTracker != null) {
             proc.baseProcessTracker.setState(
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 784d62e..3ac7885 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -104,6 +104,11 @@
     static final int VISIBLE_APP_ADJ = 100;
     static final int VISIBLE_APP_LAYER_MAX = PERCEPTIBLE_APP_ADJ - VISIBLE_APP_ADJ - 1;
 
+    // This is a process that was recently TOP and moved to FGS. Continue to treat it almost
+    // like a foreground app for a while.
+    // @see TOP_TO_FGS_GRACE_PERIOD
+    static final int PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ = 50;
+
     // This is the process running the current foreground app.  We'd really
     // rather not kill it!
     static final int FOREGROUND_APP_ADJ = 0;
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index 144f18b..d3dc0f3 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -198,6 +198,7 @@
     long lastRequestedGc;       // When we last asked the app to do a gc
     long lastLowMemory;         // When we last told the app that memory is low
     long lastProviderTime;      // The last time someone else was using a provider in this process.
+    long lastTopTime;           // The last time the process was in the TOP state or greater.
     boolean reportLowMemory;    // Set to true when waiting to report low mem
     boolean empty;              // Is this an empty background process?
     boolean cached;             // Is this a cached process?
@@ -415,6 +416,11 @@
             TimeUtils.formatDuration(lastProviderTime, nowUptime, pw);
             pw.println();
         }
+        if (lastTopTime > 0) {
+            pw.print(prefix); pw.print("lastTopTime=");
+            TimeUtils.formatDuration(lastTopTime, nowUptime, pw);
+            pw.println();
+        }
         if (hasStartedServices) {
             pw.print(prefix); pw.print("hasStartedServices="); pw.println(hasStartedServices);
         }
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/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 44fb9ea..b2287ac 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -130,10 +130,6 @@
 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;
-import com.android.internal.inputmethod.InputMethodUtils.InputMethodSettings;
 import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
 import com.android.internal.notification.SystemNotificationChannels;
 import com.android.internal.os.HandlerCaller;
@@ -153,6 +149,8 @@
 import com.android.server.EventLogTags;
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
+import com.android.server.inputmethod.InputMethodSubtypeSwitchingController.ImeSubtypeListItem;
+import com.android.server.inputmethod.InputMethodUtils.InputMethodSettings;
 import com.android.server.statusbar.StatusBarManagerService;
 import com.android.server.wm.WindowManagerInternal;
 
diff --git a/core/java/com/android/internal/inputmethod/InputMethodSubtypeSwitchingController.java b/services/core/java/com/android/server/inputmethod/InputMethodSubtypeSwitchingController.java
similarity index 98%
rename from core/java/com/android/internal/inputmethod/InputMethodSubtypeSwitchingController.java
rename to services/core/java/com/android/server/inputmethod/InputMethodSubtypeSwitchingController.java
index 14ac2f6..77b2fee 100644
--- a/core/java/com/android/internal/inputmethod/InputMethodSubtypeSwitchingController.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodSubtypeSwitchingController.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.internal.inputmethod;
+package com.android.server.inputmethod;
 
 import android.annotation.Nullable;
 import android.content.Context;
@@ -27,7 +27,7 @@
 import android.view.inputmethod.InputMethodSubtype;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.inputmethod.InputMethodUtils.InputMethodSettings;
+import com.android.server.inputmethod.InputMethodUtils.InputMethodSettings;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -41,13 +41,11 @@
 
 /**
  * InputMethodSubtypeSwitchingController controls the switching behavior of the subtypes.
- * <p>
- * This class is designed to be used from and only from
- * {@link com.android.server.InputMethodManagerService} by using
- * {@link com.android.server.InputMethodManagerService#mMethodMap} as a global lock.
- * </p>
+ *
+ * <p>This class is designed to be used from and only from {@link InputMethodManagerService} by
+ * using {@link InputMethodManagerService#mMethodMap} as a global lock.</p>
  */
-public class InputMethodSubtypeSwitchingController {
+final class InputMethodSubtypeSwitchingController {
     private static final String TAG = InputMethodSubtypeSwitchingController.class.getSimpleName();
     private static final boolean DEBUG = false;
     private static final int NOT_A_SUBTYPE_ID = InputMethodUtils.NOT_A_SUBTYPE_ID;
diff --git a/core/java/com/android/internal/inputmethod/InputMethodUtils.java b/services/core/java/com/android/server/inputmethod/InputMethodUtils.java
similarity index 88%
rename from core/java/com/android/internal/inputmethod/InputMethodUtils.java
rename to services/core/java/com/android/server/inputmethod/InputMethodUtils.java
index 1e5b5c8..e951b27 100644
--- a/core/java/com/android/internal/inputmethod/InputMethodUtils.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodUtils.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.internal.inputmethod;
+package com.android.server.inputmethod;
 
 import static android.view.inputmethod.InputMethodManager.CONTROL_WINDOW_IS_TEXT_EDITOR;
 import static android.view.inputmethod.InputMethodManager.CONTROL_WINDOW_VIEW_HAS_FOCUS;
@@ -53,10 +53,14 @@
 import java.util.Locale;
 
 /**
- * InputMethodManagerUtils contains some static methods that provides IME informations.
- * This methods are supposed to be used in both the framework and the Settings application.
+ * This class provides random static utility methods for {@link InputMethodManagerService} and its
+ * utility classes.
+ *
+ * <p>This class is intentionally package-private.  Utility methods here are tightly coupled with
+ * implementation details in {@link InputMethodManagerService}.  Hence this class is not suitable
+ * for other components to directly use.</p>
  */
-public class InputMethodUtils {
+final class InputMethodUtils {
     public static final boolean DEBUG = false;
     public static final int NOT_A_SUBTYPE_ID = -1;
     public static final String SUBTYPE_MODE_ANY = null;
@@ -334,32 +338,6 @@
         return getDefaultEnabledImes(context, imis, false /* onlyMinimum */);
     }
 
-    public static Locale constructLocaleFromString(String localeStr) {
-        if (TextUtils.isEmpty(localeStr)) {
-            return null;
-        }
-        // TODO: Use {@link Locale#toLanguageTag()} and {@link Locale#forLanguageTag(languageTag)}.
-        String[] localeParams = localeStr.split("_", 3);
-        if (localeParams.length >= 1 && "tl".equals(localeParams[0])) {
-             // Convert a locale whose language is "tl" to one whose language is "fil".
-             // For example, "tl_PH" will get converted to "fil_PH".
-             // Versions of Android earlier than Lollipop did not support three letter language
-             // codes, and used "tl" (Tagalog) as the language string for "fil" (Filipino).
-             // On Lollipop and above, the current three letter version must be used.
-             localeParams[0] = "fil";
-        }
-        // The length of localeStr is guaranteed to always return a 1 <= value <= 3
-        // because localeStr is not empty.
-        if (localeParams.length == 1) {
-            return new Locale(localeParams[0]);
-        } else if (localeParams.length == 2) {
-            return new Locale(localeParams[0], localeParams[1]);
-        } else if (localeParams.length == 3) {
-            return new Locale(localeParams[0], localeParams[1], localeParams[2]);
-        }
-        return null;
-    }
-
     public static boolean containsSubtypeOf(final InputMethodInfo imi,
             @Nullable final Locale locale, final boolean checkCountry, final String mode) {
         if (locale == null) {
@@ -1320,133 +1298,6 @@
         }
     }
 
-    // For spell checker service manager.
-    // TODO: Should we have TextServicesUtils.java?
-    private static final Locale LOCALE_EN_US = new Locale("en", "US");
-    private static final Locale LOCALE_EN_GB = new Locale("en", "GB");
-
-    /**
-     * Returns a list of {@link Locale} in the order of appropriateness for the default spell
-     * checker service.
-     *
-     * <p>If the system language is English, and the region is also explicitly specified in the
-     * system locale, the following fallback order will be applied.</p>
-     * <ul>
-     * <li>(system-locale-language, system-locale-region, system-locale-variant) (if exists)</li>
-     * <li>(system-locale-language, system-locale-region)</li>
-     * <li>("en", "US")</li>
-     * <li>("en", "GB")</li>
-     * <li>("en")</li>
-     * </ul>
-     *
-     * <p>If the system language is English, but no region is specified in the system locale,
-     * the following fallback order will be applied.</p>
-     * <ul>
-     * <li>("en")</li>
-     * <li>("en", "US")</li>
-     * <li>("en", "GB")</li>
-     * </ul>
-     *
-     * <p>If the system language is not English, the following fallback order will be applied.</p>
-     * <ul>
-     * <li>(system-locale-language, system-locale-region, system-locale-variant) (if exists)</li>
-     * <li>(system-locale-language, system-locale-region) (if exists)</li>
-     * <li>(system-locale-language) (if exists)</li>
-     * <li>("en", "US")</li>
-     * <li>("en", "GB")</li>
-     * <li>("en")</li>
-     * </ul>
-     *
-     * @param systemLocale the current system locale to be taken into consideration.
-     * @return a list of {@link Locale}. The first one is considered to be most appropriate.
-     */
-    @VisibleForTesting
-    public static ArrayList<Locale> getSuitableLocalesForSpellChecker(
-            @Nullable final Locale systemLocale) {
-        final Locale systemLocaleLanguageCountryVariant;
-        final Locale systemLocaleLanguageCountry;
-        final Locale systemLocaleLanguage;
-        if (systemLocale != null) {
-            final String language = systemLocale.getLanguage();
-            final boolean hasLanguage = !TextUtils.isEmpty(language);
-            final String country = systemLocale.getCountry();
-            final boolean hasCountry = !TextUtils.isEmpty(country);
-            final String variant = systemLocale.getVariant();
-            final boolean hasVariant = !TextUtils.isEmpty(variant);
-            if (hasLanguage && hasCountry && hasVariant) {
-                systemLocaleLanguageCountryVariant = new Locale(language, country, variant);
-            } else {
-                systemLocaleLanguageCountryVariant = null;
-            }
-            if (hasLanguage && hasCountry) {
-                systemLocaleLanguageCountry = new Locale(language, country);
-            } else {
-                systemLocaleLanguageCountry = null;
-            }
-            if (hasLanguage) {
-                systemLocaleLanguage = new Locale(language);
-            } else {
-                systemLocaleLanguage = null;
-            }
-        } else {
-            systemLocaleLanguageCountryVariant = null;
-            systemLocaleLanguageCountry = null;
-            systemLocaleLanguage = null;
-        }
-
-        final ArrayList<Locale> locales = new ArrayList<>();
-        if (systemLocaleLanguageCountryVariant != null) {
-            locales.add(systemLocaleLanguageCountryVariant);
-        }
-
-        if (Locale.ENGLISH.equals(systemLocaleLanguage)) {
-            if (systemLocaleLanguageCountry != null) {
-                // If the system language is English, and the region is also explicitly specified,
-                // following fallback order will be applied.
-                // - systemLocaleLanguageCountry [if systemLocaleLanguageCountry is non-null]
-                // - en_US [if systemLocaleLanguageCountry is non-null and not en_US]
-                // - en_GB [if systemLocaleLanguageCountry is non-null and not en_GB]
-                // - en
-                if (systemLocaleLanguageCountry != null) {
-                    locales.add(systemLocaleLanguageCountry);
-                }
-                if (!LOCALE_EN_US.equals(systemLocaleLanguageCountry)) {
-                    locales.add(LOCALE_EN_US);
-                }
-                if (!LOCALE_EN_GB.equals(systemLocaleLanguageCountry)) {
-                    locales.add(LOCALE_EN_GB);
-                }
-                locales.add(Locale.ENGLISH);
-            } else {
-                // If the system language is English, but no region is specified, following
-                // fallback order will be applied.
-                // - en
-                // - en_US
-                // - en_GB
-                locales.add(Locale.ENGLISH);
-                locales.add(LOCALE_EN_US);
-                locales.add(LOCALE_EN_GB);
-            }
-        } else {
-            // If the system language is not English, the fallback order will be
-            // - systemLocaleLanguageCountry  [if non-null]
-            // - systemLocaleLanguage  [if non-null]
-            // - en_US
-            // - en_GB
-            // - en
-            if (systemLocaleLanguageCountry != null) {
-                locales.add(systemLocaleLanguageCountry);
-            }
-            if (systemLocaleLanguage != null) {
-                locales.add(systemLocaleLanguage);
-            }
-            locales.add(LOCALE_EN_US);
-            locales.add(LOCALE_EN_GB);
-            locales.add(Locale.ENGLISH);
-        }
-        return locales;
-    }
-
     public static boolean isSoftInputModeStateVisibleAllowed(
             int targetSdkVersion, int controlFlags) {
         if (targetSdkVersion < Build.VERSION_CODES.P) {
diff --git a/core/java/com/android/internal/inputmethod/LocaleUtils.java b/services/core/java/com/android/server/inputmethod/LocaleUtils.java
similarity index 97%
rename from core/java/com/android/internal/inputmethod/LocaleUtils.java
rename to services/core/java/com/android/server/inputmethod/LocaleUtils.java
index eeb3854..4958ece 100644
--- a/core/java/com/android/internal/inputmethod/LocaleUtils.java
+++ b/services/core/java/com/android/server/inputmethod/LocaleUtils.java
@@ -14,9 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.internal.inputmethod;
-
-import com.android.internal.annotations.VisibleForTesting;
+package com.android.server.inputmethod;
 
 import android.annotation.IntRange;
 import android.annotation.NonNull;
@@ -31,9 +29,7 @@
 import java.util.List;
 import java.util.Locale;
 
-public final class LocaleUtils {
-
-    @VisibleForTesting
+final class LocaleUtils {
     public interface LocaleExtractor<T> {
         @Nullable
         Locale get(@Nullable T source);
@@ -149,7 +145,6 @@
      * @param dest Destination into which the filtered items will be added.
      * @param <T> Type of the data items.
      */
-    @VisibleForTesting
     public static <T> void filterByLanguage(
             @NonNull List<T> sources,
             @NonNull LocaleExtractor<T> extractor,
diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java
index 7751f5f..050a075 100644
--- a/services/core/java/com/android/server/notification/ManagedServices.java
+++ b/services/core/java/com/android/server/notification/ManagedServices.java
@@ -178,6 +178,10 @@
         }
     }
 
+    protected int getBindFlags() {
+        return BIND_AUTO_CREATE | BIND_FOREGROUND_SERVICE | BIND_ALLOW_WHITELIST_MANAGEMENT;
+    }
+
     protected void onServiceRemovedLocked(ManagedServiceInfo removed) { }
 
     private ManagedServiceInfo newServiceInfo(IInterface service,
@@ -1064,9 +1068,9 @@
                 }
             };
             if (!mContext.bindServiceAsUser(intent,
-                serviceConnection,
-                BIND_AUTO_CREATE | BIND_FOREGROUND_SERVICE | BIND_ALLOW_WHITELIST_MANAGEMENT,
-                new UserHandle(userid))) {
+                    serviceConnection,
+                    getBindFlags(),
+                    new UserHandle(userid))) {
                 mServicesBound.remove(servicesBindingTag);
                 Slog.w(TAG, "Unable to bind " + getCaption() + " service: " + intent);
                 return;
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 6e4d9e0..33f0172 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -33,6 +33,10 @@
 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_OFF;
 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_ON;
 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR;
+import static android.content.Context.BIND_ADJUST_BELOW_PERCEPTIBLE;
+import static android.content.Context.BIND_ALLOW_WHITELIST_MANAGEMENT;
+import static android.content.Context.BIND_AUTO_CREATE;
+import static android.content.Context.BIND_FOREGROUND_SERVICE;
 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;
@@ -4084,25 +4088,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;
             }
@@ -4113,8 +4122,6 @@
             // initially *and* force remove FLAG_FOREGROUND_SERVICE.
             sbn.getNotification().flags =
                     (r.mOriginalFlags & ~FLAG_FOREGROUND_SERVICE);
-            mRankingHelper.sort(mNotificationList);
-            mListeners.notifyPostedLocked(r, r);
         }
     };
 
@@ -4395,22 +4402,12 @@
     }
 
     protected boolean isBlocked(NotificationRecord r, NotificationUsageStats usageStats) {
-        final String pkg = r.sbn.getPackageName();
-        final int callingUid = r.sbn.getUid();
-
-        final boolean isPackageSuspended = isPackageSuspendedForUser(pkg, callingUid);
-        if (isPackageSuspended) {
-            Slog.e(TAG, "Suppressing notification from package due to package "
-                    + "suspended by administrator.");
-            usageStats.registerSuspendedByAdmin(r);
-            return isPackageSuspended;
-        }
-        final boolean isBlocked = isBlocked(r);
-        if (isBlocked) {
+        if (isBlocked(r)) {
             Slog.e(TAG, "Suppressing notification from package by user request.");
             usageStats.registerBlocked(r);
+            return true;
         }
-        return isBlocked;
+        return false;
     }
 
     private boolean isBlocked(NotificationRecord r) {
@@ -4684,7 +4681,11 @@
                         return;
                     }
 
-                    r.setHidden(isPackageSuspendedLocked(r));
+                    final boolean isPackageSuspended = isPackageSuspendedLocked(r);
+                    r.setHidden(isPackageSuspended);
+                    if (isPackageSuspended) {
+                        mUsageStats.registerSuspendedByAdmin(r);
+                    }
                     NotificationRecord old = mNotificationsByKey.get(key);
                     final StatusBarNotification n = r.sbn;
                     final Notification notification = n.getNotification();
@@ -6267,6 +6268,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();
@@ -6800,6 +6816,16 @@
         }
 
         @Override
+        protected int getBindFlags() {
+            // Most of the same flags as the base, but also add BIND_ADJUST_BELOW_PERCEPTIBLE
+            // because too many 3P apps could be kept in memory as notification listeners and
+            // cause extreme memory pressure.
+            // TODO: Change the binding lifecycle of NotificationListeners to avoid this situation.
+            return BIND_AUTO_CREATE | BIND_FOREGROUND_SERVICE
+                    | BIND_ADJUST_BELOW_PERCEPTIBLE | BIND_ALLOW_WHITELIST_MANAGEMENT;
+        }
+
+        @Override
         protected Config getConfig() {
             Config c = new Config();
             c.caption = "notification listener";
@@ -6890,7 +6916,6 @@
                 if (!oldSbnVisible && !sbnVisible) {
                     continue;
                 }
-
                 // If the notification is hidden, don't notifyPosted listeners targeting < P.
                 // Instead, those listeners will receive notifyPosted when the notification is
                 // unhidden.
@@ -7324,7 +7349,7 @@
                 new String[]{pkg});
 
         final String action = suspend ? Intent.ACTION_PACKAGES_SUSPENDED
-            : Intent.ACTION_PACKAGES_UNSUSPENDED;
+                : Intent.ACTION_PACKAGES_UNSUSPENDED;
         final Intent intent = new Intent(action);
         intent.putExtras(extras);
 
diff --git a/services/core/java/com/android/server/pm/ComponentResolver.java b/services/core/java/com/android/server/pm/ComponentResolver.java
index 7d762d9..5bf323a 100644
--- a/services/core/java/com/android/server/pm/ComponentResolver.java
+++ b/services/core/java/com/android/server/pm/ComponentResolver.java
@@ -378,7 +378,7 @@
         for (int i = newIntents.size() - 1; i >= 0; --i) {
             final PackageParser.ActivityIntentInfo intentInfo = newIntents.get(i);
             final PackageParser.Package disabledPkg = sPackageManagerInternal
-                    .getDisabledPackage(intentInfo.activity.info.packageName);
+                    .getDisabledSystemPackage(intentInfo.activity.info.packageName);
             final List<PackageParser.Activity> systemActivities =
                     disabledPkg != null ? disabledPkg.activities : null;
             adjustPriority(systemActivities, intentInfo, setupWizardPackage);
@@ -1048,11 +1048,14 @@
                         final String otherPackageName =
                                 (other != null && other.getComponentName() != null)
                                         ? other.getComponentName().getPackageName() : "?";
-                        throw new PackageManagerException(
-                                INSTALL_FAILED_CONFLICTING_PROVIDER,
-                                "Can't install because provider name " + names[j]
-                                        + " (in package " + pkg.applicationInfo.packageName
-                                        + ") is already used by " + otherPackageName);
+                        // if we're installing over the same already-installed package, this is ok
+                        if (otherPackageName != pkg.packageName) {
+                            throw new PackageManagerException(
+                                    INSTALL_FAILED_CONFLICTING_PROVIDER,
+                                    "Can't install because provider name " + names[j]
+                                            + " (in package " + pkg.applicationInfo.packageName
+                                            + ") is already used by " + otherPackageName);
+                        }
                     }
                 }
             }
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index adf95dc..91af0ec 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -111,7 +111,8 @@
 import static com.android.server.pm.PackageManagerServiceUtils.verifySignatures;
 import static com.android.server.pm.permission.PermissionsState.PERMISSION_OPERATION_FAILURE;
 import static com.android.server.pm.permission.PermissionsState.PERMISSION_OPERATION_SUCCESS;
-import static com.android.server.pm.permission.PermissionsState.PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED;
+import static com.android.server.pm.permission.PermissionsState
+        .PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED;
 
 import android.Manifest;
 import android.annotation.IntDef;
@@ -303,7 +304,8 @@
 import com.android.server.pm.dex.PackageDexUsage;
 import com.android.server.pm.permission.BasePermission;
 import com.android.server.pm.permission.DefaultPermissionGrantPolicy;
-import com.android.server.pm.permission.DefaultPermissionGrantPolicy.DefaultPermissionGrantedCallback;
+import com.android.server.pm.permission.DefaultPermissionGrantPolicy
+        .DefaultPermissionGrantedCallback;
 import com.android.server.pm.permission.PermissionManagerInternal;
 import com.android.server.pm.permission.PermissionManagerInternal.PermissionCallback;
 import com.android.server.pm.permission.PermissionManagerService;
@@ -716,6 +718,8 @@
     @GuardedBy("mPackages")
     final private ArraySet<PackageListObserver> mPackageListObservers = new ArraySet<>();
 
+    private PackageManager mPackageManager;
+
     class PackageParserCallback implements PackageParser.Callback {
         @Override public final boolean hasFeature(String feature) {
             return PackageManagerService.this.hasSystemFeature(feature, 0);
@@ -8582,7 +8586,10 @@
                             null /* originalPkgSetting */, null, parseFlags, scanFlags,
                             (pkg == mPlatformPackage), user);
                     applyPolicy(pkg, parseFlags, scanFlags, mPlatformPackage);
-                    scanPackageOnlyLI(request, mFactoryTest, -1L);
+                    final ScanResult scanResult = scanPackageOnlyLI(request, mFactoryTest, -1L);
+                    if (scanResult.existingSettingCopied && scanResult.request.pkgSetting != null) {
+                        scanResult.request.pkgSetting.updateFrom(scanResult.pkgSetting);
+                    }
                 }
             }
         }
@@ -9805,6 +9812,11 @@
         /** Whether or not the package scan was successful */
         public final boolean success;
         /**
+         * Whether or not the original PackageSetting needs to be updated with this result on
+         * commit.
+         */
+        public final boolean existingSettingCopied;
+        /**
          * The final package settings. This may be the same object passed in
          * the {@link ScanRequest}, but, with modified values.
          */
@@ -9814,11 +9826,12 @@
         public ScanResult(
                 ScanRequest request, boolean success,
                 @Nullable PackageSetting pkgSetting,
-                @Nullable List<String> changedAbiCodePath) {
+                @Nullable List<String> changedAbiCodePath, boolean existingSettingCopied) {
             this.request = request;
             this.success = success;
             this.pkgSetting = pkgSetting;
             this.changedAbiCodePath = changedAbiCodePath;
+            this.existingSettingCopied = existingSettingCopied;
         }
     }
 
@@ -9895,26 +9908,34 @@
     private @ScanFlags int adjustScanFlags(@ScanFlags int scanFlags,
             PackageSetting pkgSetting, PackageSetting disabledPkgSetting, UserHandle user,
             PackageParser.Package pkg) {
-        if (disabledPkgSetting != null) {
+
+        // TODO(patb): Do away entirely with disabledPkgSetting here. PkgSetting will always contain
+        // the correct isSystem value now that we don't disable system packages before scan.
+        final PackageSetting systemPkgSetting =
+                (scanFlags & SCAN_NEW_INSTALL) != 0 && disabledPkgSetting == null
+                        && pkgSetting != null && pkgSetting.isSystem()
+                        ? pkgSetting
+                        : disabledPkgSetting;
+        if (systemPkgSetting != null)  {
             // updated system application, must at least have SCAN_AS_SYSTEM
             scanFlags |= SCAN_AS_SYSTEM;
-            if ((disabledPkgSetting.pkgPrivateFlags
+            if ((systemPkgSetting.pkgPrivateFlags
                     & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0) {
                 scanFlags |= SCAN_AS_PRIVILEGED;
             }
-            if ((disabledPkgSetting.pkgPrivateFlags
+            if ((systemPkgSetting.pkgPrivateFlags
                     & ApplicationInfo.PRIVATE_FLAG_OEM) != 0) {
                 scanFlags |= SCAN_AS_OEM;
             }
-            if ((disabledPkgSetting.pkgPrivateFlags
+            if ((systemPkgSetting.pkgPrivateFlags
                     & ApplicationInfo.PRIVATE_FLAG_VENDOR) != 0) {
                 scanFlags |= SCAN_AS_VENDOR;
             }
-            if ((disabledPkgSetting.pkgPrivateFlags
+            if ((systemPkgSetting.pkgPrivateFlags
                     & ApplicationInfo.PRIVATE_FLAG_PRODUCT) != 0) {
                 scanFlags |= SCAN_AS_PRODUCT;
             }
-            if ((disabledPkgSetting.pkgPrivateFlags
+            if ((systemPkgSetting.pkgPrivateFlags
                     & ApplicationInfo.PRIVATE_FLAG_PRODUCT_SERVICES) != 0) {
                 scanFlags |= SCAN_AS_PRODUCT_SERVICES;
             }
@@ -10044,11 +10065,18 @@
         final PackageSetting disabledPkgSetting = request.disabledPkgSetting;
         final UserHandle user = request.user;
         final String realPkgName = request.realPkgName;
-        final PackageSetting pkgSetting = result.pkgSetting;
         final List<String> changedAbiCodePath = result.changedAbiCodePath;
-        final boolean newPkgSettingCreated = (result.pkgSetting != request.pkgSetting);
-
-        if (newPkgSettingCreated) {
+        final PackageSetting pkgSetting;
+        if (result.existingSettingCopied) {
+            pkgSetting = request.pkgSetting;
+            pkgSetting.updateFrom(result.pkgSetting);
+            pkg.mExtras = pkgSetting;
+            if (pkgSetting.sharedUser != null
+                    && pkgSetting.sharedUser.removePackage(result.pkgSetting)) {
+                pkgSetting.sharedUser.addPackage(pkgSetting);
+            }
+        } else {
+            pkgSetting = result.pkgSetting;
             if (originalPkgSetting != null) {
                 mSettings.addRenamedPackageLPw(pkg.packageName, originalPkgSetting.name);
             }
@@ -10355,7 +10383,6 @@
         String primaryCpuAbiFromSettings = null;
         String secondaryCpuAbiFromSettings = null;
         boolean needToDeriveAbi = (scanFlags & SCAN_FIRST_BOOT_OR_UPGRADE) != 0;
-
         if (!needToDeriveAbi) {
             if (pkgSetting != null) {
                 primaryCpuAbiFromSettings = pkgSetting.primaryCpuAbiString;
@@ -10399,6 +10426,11 @@
                     UserManagerService.getInstance(), usesStaticLibraries,
                     pkg.usesStaticLibrariesVersions);
         } else {
+            if (!createNewPackage) {
+                // make a deep copy to avoid modifying any existing system state.
+                pkgSetting = new PackageSetting(pkgSetting);
+                pkgSetting.pkg = pkg;
+            }
             // REMOVE SharedUserSetting from method; update in a separate call.
             //
             // TODO(narayan): This update is bogus. nativeLibraryDir & primaryCpuAbi,
@@ -10431,8 +10463,10 @@
             final boolean fullApp = (scanFlags & SCAN_AS_FULL_APP) != 0;
             setInstantAppForUser(pkgSetting, userId, instantApp, fullApp);
         }
-
-        if (disabledPkgSetting != null) {
+        // TODO(patb): see if we can do away with disabled check here.
+        if (disabledPkgSetting != null
+                || (0 != (scanFlags & SCAN_NEW_INSTALL)
+                && pkgSetting != null && pkgSetting.isSystem())) {
             pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
         }
 
@@ -10615,7 +10649,8 @@
             pkgSetting.volumeUuid = volumeUuid;
         }
 
-        return new ScanResult(request, true, pkgSetting, changedAbiCodePath);
+        return new ScanResult(request, true, pkgSetting, changedAbiCodePath,
+                !createNewPackage /* existingSettingCopied */);
     }
 
     /**
@@ -10830,7 +10865,7 @@
             }
 
             // A package name must be unique; don't allow duplicates
-            if (mPackages.containsKey(pkg.packageName)) {
+            if ((scanFlags & SCAN_NEW_INSTALL) == 0 && mPackages.containsKey(pkg.packageName)) {
                 throw new PackageManagerException(INSTALL_FAILED_DUPLICATE_PACKAGE,
                         "Application package " + pkg.packageName
                         + " already installed.  Skipping duplicate.");
@@ -10839,7 +10874,8 @@
             if (pkg.applicationInfo.isStaticSharedLibrary()) {
                 // Static libs have a synthetic package name containing the version
                 // but we still want the base name to be unique.
-                if (mPackages.containsKey(pkg.manifestPackageName)) {
+                if ((scanFlags & SCAN_NEW_INSTALL) == 0
+                        && mPackages.containsKey(pkg.manifestPackageName)) {
                     throw new PackageManagerException(
                             "Duplicate static shared lib provider package");
                 }
@@ -11928,7 +11964,9 @@
         // Remove the parent package setting
         PackageSetting ps = (PackageSetting) pkg.mExtras;
         if (ps != null) {
-            removePackageLI(ps, chatty);
+            removePackageLI(ps.name, chatty);
+        } else if (DEBUG_REMOVE && chatty) {
+            Log.d(TAG, "Not removing package " + pkg.packageName + "; mExtras == null");
         }
         // Remove the child package setting
         final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
@@ -11936,23 +11974,22 @@
             PackageParser.Package childPkg = pkg.childPackages.get(i);
             ps = (PackageSetting) childPkg.mExtras;
             if (ps != null) {
-                removePackageLI(ps, chatty);
+                removePackageLI(ps.name, chatty);
             }
         }
     }
 
-    void removePackageLI(PackageSetting ps, boolean chatty) {
+    void removePackageLI(String packageName, boolean chatty) {
         if (DEBUG_INSTALL) {
             if (chatty)
-                Log.d(TAG, "Removing package " + ps.name);
+                Log.d(TAG, "Removing package " + packageName);
         }
 
         // writer
         synchronized (mPackages) {
-            mPackages.remove(ps.name);
-            final PackageParser.Package pkg = ps.pkg;
-            if (pkg != null) {
-                cleanPackageDataStructuresLILPw(pkg, chatty);
+            final PackageParser.Package removedPackage = mPackages.remove(packageName);
+            if (removedPackage != null) {
+                cleanPackageDataStructuresLILPw(removedPackage, chatty);
             }
         }
     }
@@ -14653,68 +14690,6 @@
         String origPermission;
     }
 
-    /*
-     * Install a non-existing package.
-     */
-    private void installNewPackageLIF(PackageParser.Package pkg, final @ParseFlags int parseFlags,
-            final @ScanFlags int scanFlags, UserHandle user, String installerPackageName,
-            String volumeUuid, PackageInstalledInfo res, int installReason) {
-        Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installNewPackage");
-
-        // Remember this for later, in case we need to rollback this install
-        String pkgName = pkg.packageName;
-
-        if (DEBUG_INSTALL) Slog.d(TAG, "installNewPackageLI: " + pkg);
-
-        synchronized(mPackages) {
-            final String renamedPackage = mSettings.getRenamedPackageLPr(pkgName);
-            if (renamedPackage != null) {
-                // A package with the same name is already installed, though
-                // it has been renamed to an older name.  The package we
-                // are trying to install should be installed as an update to
-                // the existing one, but that has not been requested, so bail.
-                res.setError(INSTALL_FAILED_ALREADY_EXISTS, "Attempt to re-install " + pkgName
-                        + " without first uninstalling package running as "
-                        + renamedPackage);
-                return;
-            }
-            if (mPackages.containsKey(pkgName)) {
-                // Don't allow installation over an existing package with the same name.
-                res.setError(INSTALL_FAILED_ALREADY_EXISTS, "Attempt to re-install " + pkgName
-                        + " without first uninstalling.");
-                return;
-            }
-        }
-
-        try {
-            final PackageParser.Package newPackage;
-            List<ScanResult> scanResults = scanPackageTracedLI(pkg, parseFlags, scanFlags,
-                    System.currentTimeMillis(), user);
-            commitSuccessfulScanResults(scanResults);
-            // TODO(b/109941548): Child packages may return >1 result with the first being the base;
-            // we need to treat child packages as an atomic install and remove this hack
-            final ScanResult basePackageScanResult = scanResults.get(0);
-            newPackage = basePackageScanResult.pkgSetting.pkg;
-            updateSettingsLI(newPackage, installerPackageName, null, res, user, installReason);
-
-            if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
-                prepareAppDataAfterInstallLIF(newPackage);
-            } else {
-                // Remove package from internal structures, but keep around any
-                // data that might have already existed
-                deletePackageLIF(pkgName, UserHandle.ALL, false, null,
-                        PackageManager.DELETE_KEEP_DATA, res.removedInfo, true, null);
-            }
-        } catch (PackageManagerException e) {
-            destroyAppDataLIF(pkg, UserHandle.USER_ALL,
-                    StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE);
-            destroyAppProfilesLIF(pkg, UserHandle.USER_ALL);
-            res.setError("Package couldn't be installed in " + pkg.codePath, e);
-        }
-
-        Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
-    }
-
     private static void updateDigest(MessageDigest digest, File file) throws IOException {
         try (DigestInputStream digestStream =
                 new DigestInputStream(new FileInputStream(file), digest)) {
@@ -14722,482 +14697,6 @@
         }
     }
 
-    private void replacePackageLIF(PackageParser.Package pkg, final @ParseFlags int parseFlags,
-            final @ScanFlags int scanFlags, UserHandle user, String installerPackageName,
-            PackageInstalledInfo res, int installReason) {
-        final boolean isInstantApp = (scanFlags & SCAN_AS_INSTANT_APP) != 0;
-
-        final PackageParser.Package oldPackage;
-        final PackageSetting ps;
-        final String pkgName = pkg.packageName;
-        final int[] allUsers;
-        final int[] installedUsers;
-
-        synchronized(mPackages) {
-            oldPackage = mPackages.get(pkgName);
-            if (DEBUG_INSTALL) Slog.d(TAG, "replacePackageLI: new=" + pkg + ", old=" + oldPackage);
-
-            // don't allow upgrade to target a release SDK from a pre-release SDK
-            final boolean oldTargetsPreRelease = oldPackage.applicationInfo.targetSdkVersion
-                    == android.os.Build.VERSION_CODES.CUR_DEVELOPMENT;
-            final boolean newTargetsPreRelease = pkg.applicationInfo.targetSdkVersion
-                    == android.os.Build.VERSION_CODES.CUR_DEVELOPMENT;
-            if (oldTargetsPreRelease
-                    && !newTargetsPreRelease
-                    && ((parseFlags & PackageParser.PARSE_FORCE_SDK) == 0)) {
-                Slog.w(TAG, "Can't install package targeting released sdk");
-                res.setReturnCode(PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE);
-                return;
-            }
-
-            ps = mSettings.mPackages.get(pkgName);
-
-            // verify signatures are valid
-            final KeySetManagerService ksms = mSettings.mKeySetManagerService;
-            if (ksms.shouldCheckUpgradeKeySetLocked(ps, scanFlags)) {
-                if (!ksms.checkUpgradeKeySetLocked(ps, pkg)) {
-                    res.setError(INSTALL_FAILED_UPDATE_INCOMPATIBLE,
-                            "New package not signed by keys specified by upgrade-keysets: "
-                                    + pkgName);
-                    return;
-                }
-            } else {
-
-                // default to original signature matching
-                if (!pkg.mSigningDetails.checkCapability(oldPackage.mSigningDetails,
-                        PackageParser.SigningDetails.CertCapabilities.INSTALLED_DATA)
-                                && !oldPackage.mSigningDetails.checkCapability(
-                                        pkg.mSigningDetails,
-                                        PackageParser.SigningDetails.CertCapabilities.ROLLBACK)) {
-                    res.setError(INSTALL_FAILED_UPDATE_INCOMPATIBLE,
-                            "New package has a different signature: " + pkgName);
-                    return;
-                }
-            }
-
-            // don't allow a system upgrade unless the upgrade hash matches
-            if (oldPackage.restrictUpdateHash != null && oldPackage.isSystem()) {
-                final byte[] digestBytes;
-                try {
-                    final MessageDigest digest = MessageDigest.getInstance("SHA-512");
-                    updateDigest(digest, new File(pkg.baseCodePath));
-                    if (!ArrayUtils.isEmpty(pkg.splitCodePaths)) {
-                        for (String path : pkg.splitCodePaths) {
-                            updateDigest(digest, new File(path));
-                        }
-                    }
-                    digestBytes = digest.digest();
-                } catch (NoSuchAlgorithmException | IOException e) {
-                    res.setError(INSTALL_FAILED_INVALID_APK,
-                            "Could not compute hash: " + pkgName);
-                    return;
-                }
-                if (!Arrays.equals(oldPackage.restrictUpdateHash, digestBytes)) {
-                    res.setError(INSTALL_FAILED_INVALID_APK,
-                            "New package fails restrict-update check: " + pkgName);
-                    return;
-                }
-                // retain upgrade restriction
-                pkg.restrictUpdateHash = oldPackage.restrictUpdateHash;
-            }
-
-            // Check for shared user id changes
-            String invalidPackageName =
-                    getParentOrChildPackageChangedSharedUser(oldPackage, pkg);
-            if (invalidPackageName != null) {
-                res.setError(INSTALL_FAILED_SHARED_USER_INCOMPATIBLE,
-                        "Package " + invalidPackageName + " tried to change user "
-                                + oldPackage.mSharedUserId);
-                return;
-            }
-
-            // check if the new package supports all of the abis which the old package supports
-            boolean oldPkgSupportMultiArch = oldPackage.applicationInfo.secondaryCpuAbi != null;
-            boolean newPkgSupportMultiArch = pkg.applicationInfo.secondaryCpuAbi != null;
-            if (isSystemApp(oldPackage) && oldPkgSupportMultiArch && !newPkgSupportMultiArch) {
-                res.setError(INSTALL_FAILED_UPDATE_INCOMPATIBLE,
-                        "Update to package " + pkgName + " doesn't support multi arch");
-                return;
-            }
-
-            // In case of rollback, remember per-user/profile install state
-            allUsers = sUserManager.getUserIds();
-            installedUsers = ps.queryInstalledUsers(allUsers, true);
-
-            // don't allow an upgrade from full to ephemeral
-            if (isInstantApp) {
-                if (user == null || user.getIdentifier() == UserHandle.USER_ALL) {
-                    for (int currentUser : allUsers) {
-                        if (!ps.getInstantApp(currentUser)) {
-                            // can't downgrade from full to instant
-                            Slog.w(TAG, "Can't replace full app with instant app: " + pkgName
-                                    + " for user: " + currentUser);
-                            res.setReturnCode(PackageManager.INSTALL_FAILED_INSTANT_APP_INVALID);
-                            return;
-                        }
-                    }
-                } else if (!ps.getInstantApp(user.getIdentifier())) {
-                    // can't downgrade from full to instant
-                    Slog.w(TAG, "Can't replace full app with instant app: " + pkgName
-                            + " for user: " + user.getIdentifier());
-                    res.setReturnCode(PackageManager.INSTALL_FAILED_INSTANT_APP_INVALID);
-                    return;
-                }
-            }
-        }
-
-        // Update what is removed
-        res.removedInfo = new PackageRemovedInfo(this);
-        res.removedInfo.uid = oldPackage.applicationInfo.uid;
-        res.removedInfo.removedPackage = oldPackage.packageName;
-        res.removedInfo.installerPackageName = ps.installerPackageName;
-        res.removedInfo.isStaticSharedLib = pkg.staticSharedLibName != null;
-        res.removedInfo.isUpdate = true;
-        res.removedInfo.origUsers = installedUsers;
-        res.removedInfo.installReasons = new SparseArray<>(installedUsers.length);
-        for (int i = 0; i < installedUsers.length; i++) {
-            final int userId = installedUsers[i];
-            res.removedInfo.installReasons.put(userId, ps.getInstallReason(userId));
-        }
-
-        final int childCount = (oldPackage.childPackages != null)
-                ? oldPackage.childPackages.size() : 0;
-        for (int i = 0; i < childCount; i++) {
-            boolean childPackageUpdated = false;
-            PackageParser.Package childPkg = oldPackage.childPackages.get(i);
-            final PackageSetting childPs = mSettings.getPackageLPr(childPkg.packageName);
-            if (res.addedChildPackages != null) {
-                PackageInstalledInfo childRes = res.addedChildPackages.get(childPkg.packageName);
-                if (childRes != null) {
-                    childRes.removedInfo.uid = childPkg.applicationInfo.uid;
-                    childRes.removedInfo.removedPackage = childPkg.packageName;
-                    if (childPs != null) {
-                        childRes.removedInfo.installerPackageName = childPs.installerPackageName;
-                    }
-                    childRes.removedInfo.isUpdate = true;
-                    childRes.removedInfo.installReasons = res.removedInfo.installReasons;
-                    childPackageUpdated = true;
-                }
-            }
-            if (!childPackageUpdated) {
-                PackageRemovedInfo childRemovedRes = new PackageRemovedInfo(this);
-                childRemovedRes.removedPackage = childPkg.packageName;
-                if (childPs != null) {
-                    childRemovedRes.installerPackageName = childPs.installerPackageName;
-                }
-                childRemovedRes.isUpdate = false;
-                childRemovedRes.dataRemoved = true;
-                synchronized (mPackages) {
-                    if (childPs != null) {
-                        childRemovedRes.origUsers = childPs.queryInstalledUsers(allUsers, true);
-                    }
-                }
-                if (res.removedInfo.removedChildPackages == null) {
-                    res.removedInfo.removedChildPackages = new ArrayMap<>();
-                }
-                res.removedInfo.removedChildPackages.put(childPkg.packageName, childRemovedRes);
-            }
-        }
-
-        boolean sysPkg = (isSystemApp(oldPackage));
-        if (sysPkg) {
-            // Set the system/privileged/oem/vendor/product flags as needed
-            final boolean privileged = isPrivilegedApp(oldPackage);
-            final boolean oem = isOemApp(oldPackage);
-            final boolean vendor = isVendorApp(oldPackage);
-            final boolean product = isProductApp(oldPackage);
-            final boolean productServices = isProductServicesApp(oldPackage);
-
-            final @ParseFlags int systemParseFlags = parseFlags;
-            final @ScanFlags int systemScanFlags = scanFlags
-                    | SCAN_AS_SYSTEM
-                    | (privileged ? SCAN_AS_PRIVILEGED : 0)
-                    | (oem ? SCAN_AS_OEM : 0)
-                    | (vendor ? SCAN_AS_VENDOR : 0)
-                    | (product ? SCAN_AS_PRODUCT : 0)
-                    | (productServices ? SCAN_AS_PRODUCT_SERVICES : 0);
-
-            replaceSystemPackageLIF(oldPackage, pkg, systemParseFlags, systemScanFlags,
-                    user, allUsers, installerPackageName, res, installReason);
-        } else {
-            replaceNonSystemPackageLIF(oldPackage, pkg, parseFlags, scanFlags,
-                    user, allUsers, installerPackageName, res, installReason);
-        }
-    }
-
-    private void replaceNonSystemPackageLIF(PackageParser.Package deletedPackage,
-            PackageParser.Package pkg, final @ParseFlags int parseFlags,
-            final @ScanFlags int scanFlags, UserHandle user, int[] allUsers,
-            String installerPackageName, PackageInstalledInfo res, int installReason) {
-        if (DEBUG_INSTALL) Slog.d(TAG, "replaceNonSystemPackageLI: new=" + pkg + ", old="
-                + deletedPackage);
-
-        String pkgName = deletedPackage.packageName;
-        boolean deletedPkg = true;
-        boolean addedPkg = false;
-        boolean updatedSettings = false;
-        final boolean killApp = (scanFlags & SCAN_DONT_KILL_APP) == 0;
-        final int deleteFlags = PackageManager.DELETE_KEEP_DATA
-                | (killApp ? 0 : PackageManager.DELETE_DONT_KILL_APP);
-
-        final long origUpdateTime = (pkg.mExtras != null)
-                ? ((PackageSetting)pkg.mExtras).lastUpdateTime : 0;
-
-        // First delete the existing package while retaining the data directory
-        if (!deletePackageLIF(pkgName, null, true, allUsers, deleteFlags,
-                res.removedInfo, true, pkg)) {
-            // If the existing package wasn't successfully deleted
-            res.setError(INSTALL_FAILED_REPLACE_COULDNT_DELETE, "replaceNonSystemPackageLI");
-            deletedPkg = false;
-        } else {
-            // Successfully deleted the old package; proceed with replace.
-
-            // If deleted package lived in a container, give users a chance to
-            // relinquish resources before killing.
-            if (deletedPackage.isForwardLocked() || isExternal(deletedPackage)) {
-                if (DEBUG_INSTALL) {
-                    Slog.i(TAG, "upgrading pkg " + deletedPackage + " is ASEC-hosted -> UNAVAILABLE");
-                }
-                final int[] uidArray = new int[] { deletedPackage.applicationInfo.uid };
-                final ArrayList<String> pkgList = new ArrayList<>(1);
-                pkgList.add(deletedPackage.applicationInfo.packageName);
-                sendResourcesChangedBroadcast(false, true, pkgList, uidArray, null);
-            }
-
-            clearAppDataLIF(pkg, UserHandle.USER_ALL, StorageManager.FLAG_STORAGE_DE
-                    | StorageManager.FLAG_STORAGE_CE | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
-
-            try {
-                final List<ScanResult> scanResults = scanPackageTracedLI(pkg, parseFlags,
-                        scanFlags | SCAN_UPDATE_TIME, System.currentTimeMillis(), user);
-                commitSuccessfulScanResults(scanResults);
-                final PackageParser.Package newPackage = scanResults.get(0).pkgSetting.pkg;
-                updateSettingsLI(newPackage, installerPackageName, allUsers, res, user,
-                        installReason);
-
-                // Update the in-memory copy of the previous code paths.
-                PackageSetting ps = mSettings.mPackages.get(pkgName);
-                if (!killApp) {
-                    if (ps.oldCodePaths == null) {
-                        ps.oldCodePaths = new ArraySet<>();
-                    }
-                    Collections.addAll(ps.oldCodePaths, deletedPackage.baseCodePath);
-                    if (deletedPackage.splitCodePaths != null) {
-                        Collections.addAll(ps.oldCodePaths, deletedPackage.splitCodePaths);
-                    }
-                } else {
-                    ps.oldCodePaths = null;
-                }
-                if (ps.childPackageNames != null) {
-                    for (int i = ps.childPackageNames.size() - 1; i >= 0; --i) {
-                        final String childPkgName = ps.childPackageNames.get(i);
-                        final PackageSetting childPs = mSettings.mPackages.get(childPkgName);
-                        childPs.oldCodePaths = ps.oldCodePaths;
-                    }
-                }
-                prepareAppDataAfterInstallLIF(newPackage);
-                addedPkg = true;
-                mDexManager.notifyPackageUpdated(newPackage.packageName,
-                        newPackage.baseCodePath, newPackage.splitCodePaths);
-            } catch (PackageManagerException e) {
-                res.setError("Package couldn't be installed in " + pkg.codePath, e);
-            }
-        }
-
-        if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
-            if (DEBUG_INSTALL) Slog.d(TAG, "Install failed, rolling pack: " + pkgName);
-
-            // Revert all internal state mutations and added folders for the failed install
-            if (addedPkg) {
-                deletePackageLIF(pkgName, null, true, allUsers, deleteFlags,
-                        res.removedInfo, true, null);
-            }
-
-            // Restore the old package
-            if (deletedPkg) {
-                if (DEBUG_INSTALL) Slog.d(TAG, "Install failed, reinstalling: " + deletedPackage);
-                File restoreFile = new File(deletedPackage.codePath);
-                // Parse old package
-                boolean oldExternal = isExternal(deletedPackage);
-                int oldParseFlags  = mDefParseFlags | PackageParser.PARSE_CHATTY |
-                        (deletedPackage.isForwardLocked() ? PackageParser.PARSE_FORWARD_LOCK : 0) |
-                        (oldExternal ? PackageParser.PARSE_EXTERNAL_STORAGE : 0);
-                int oldScanFlags = SCAN_UPDATE_SIGNATURE | SCAN_UPDATE_TIME;
-                try {
-                    scanPackageTracedLI(restoreFile, oldParseFlags, oldScanFlags, origUpdateTime,
-                            null);
-                } catch (PackageManagerException e) {
-                    Slog.e(TAG, "Failed to restore package : " + pkgName + " after failed upgrade: "
-                            + e.getMessage());
-                    return;
-                }
-
-                synchronized (mPackages) {
-                    // Ensure the installer package name up to date
-                    setInstallerPackageNameLPw(deletedPackage, installerPackageName);
-
-                    // Update permissions for restored package
-                    mPermissionManager.updatePermissions(
-                            deletedPackage.packageName, deletedPackage, false, mPackages.values(),
-                            mPermissionCallback);
-
-                    mSettings.writeLPr();
-                }
-
-                Slog.i(TAG, "Successfully restored package : " + pkgName + " after failed upgrade");
-            }
-        } else {
-            synchronized (mPackages) {
-                PackageSetting ps = mSettings.getPackageLPr(pkg.packageName);
-                if (ps != null) {
-                    res.removedInfo.removedForAllUsers = mPackages.get(ps.name) == null;
-                    if (res.removedInfo.removedChildPackages != null) {
-                        final int childCount = res.removedInfo.removedChildPackages.size();
-                        // Iterate in reverse as we may modify the collection
-                        for (int i = childCount - 1; i >= 0; i--) {
-                            String childPackageName = res.removedInfo.removedChildPackages.keyAt(i);
-                            if (res.addedChildPackages.containsKey(childPackageName)) {
-                                res.removedInfo.removedChildPackages.removeAt(i);
-                            } else {
-                                PackageRemovedInfo childInfo = res.removedInfo
-                                        .removedChildPackages.valueAt(i);
-                                childInfo.removedForAllUsers = mPackages.get(
-                                        childInfo.removedPackage) == null;
-                            }
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    private void replaceSystemPackageLIF(PackageParser.Package deletedPackage,
-            PackageParser.Package pkg, final @ParseFlags int parseFlags,
-            final @ScanFlags int scanFlags, UserHandle user,
-            int[] allUsers, String installerPackageName, PackageInstalledInfo res,
-            int installReason) {
-        if (DEBUG_INSTALL) Slog.d(TAG, "replaceSystemPackageLI: new=" + pkg
-                + ", old=" + deletedPackage);
-
-        final boolean disabledSystem;
-
-        // Remove existing system package
-        removePackageLI(deletedPackage, true);
-
-        synchronized (mPackages) {
-            disabledSystem = disableSystemPackageLPw(deletedPackage, pkg);
-        }
-        if (!disabledSystem) {
-            // We didn't need to disable the .apk as a current system package,
-            // which means we are replacing another update that is already
-            // installed.  We need to make sure to delete the older one's .apk.
-            res.removedInfo.args = createInstallArgsForExisting(0,
-                    deletedPackage.applicationInfo.getCodePath(),
-                    deletedPackage.applicationInfo.getResourcePath(),
-                    getAppDexInstructionSets(deletedPackage.applicationInfo));
-        } else {
-            res.removedInfo.args = null;
-        }
-
-        // Successfully disabled the old package. Now proceed with re-installation
-        clearAppDataLIF(pkg, UserHandle.USER_ALL, StorageManager.FLAG_STORAGE_DE
-                | StorageManager.FLAG_STORAGE_CE | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
-
-        res.setReturnCode(PackageManager.INSTALL_SUCCEEDED);
-        pkg.setApplicationInfoFlags(ApplicationInfo.FLAG_UPDATED_SYSTEM_APP,
-                ApplicationInfo.FLAG_UPDATED_SYSTEM_APP);
-
-        PackageParser.Package newPackage = null;
-        try {
-            final List<ScanResult> scanResults =
-                    scanPackageTracedLI(pkg, parseFlags, scanFlags, 0, user);
-            // Add the package to the internal data structures
-            commitSuccessfulScanResults(scanResults);
-            newPackage = scanResults.get(0).pkgSetting.pkg;
-
-            // Set the update and install times
-            PackageSetting deletedPkgSetting = (PackageSetting) deletedPackage.mExtras;
-            setInstallAndUpdateTime(newPackage, deletedPkgSetting.firstInstallTime,
-                    System.currentTimeMillis());
-
-            // Update the package dynamic state if succeeded
-            if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
-                // Now that the install succeeded make sure we remove data
-                // directories for any child package the update removed.
-                final int deletedChildCount = (deletedPackage.childPackages != null)
-                        ? deletedPackage.childPackages.size() : 0;
-                final int newChildCount = (newPackage.childPackages != null)
-                        ? newPackage.childPackages.size() : 0;
-                for (int i = 0; i < deletedChildCount; i++) {
-                    PackageParser.Package deletedChildPkg = deletedPackage.childPackages.get(i);
-                    boolean childPackageDeleted = true;
-                    for (int j = 0; j < newChildCount; j++) {
-                        PackageParser.Package newChildPkg = newPackage.childPackages.get(j);
-                        if (deletedChildPkg.packageName.equals(newChildPkg.packageName)) {
-                            childPackageDeleted = false;
-                            break;
-                        }
-                    }
-                    if (childPackageDeleted) {
-                        PackageSetting ps = mSettings.getDisabledSystemPkgLPr(
-                                deletedChildPkg.packageName);
-                        if (ps != null && res.removedInfo.removedChildPackages != null) {
-                            PackageRemovedInfo removedChildRes = res.removedInfo
-                                    .removedChildPackages.get(deletedChildPkg.packageName);
-                            removePackageDataLIF(ps, allUsers, removedChildRes, 0, false);
-                            removedChildRes.removedForAllUsers = mPackages.get(ps.name) == null;
-                        }
-                    }
-                }
-
-                updateSettingsLI(newPackage, installerPackageName, allUsers, res, user,
-                        installReason);
-                prepareAppDataAfterInstallLIF(newPackage);
-
-                mDexManager.notifyPackageUpdated(newPackage.packageName,
-                            newPackage.baseCodePath, newPackage.splitCodePaths);
-            }
-        } catch (PackageManagerException e) {
-            res.setReturnCode(INSTALL_FAILED_INTERNAL_ERROR);
-            res.setError("Package couldn't be installed in " + pkg.codePath, e);
-        }
-
-        if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
-            // Re installation failed. Restore old information
-            // Remove new pkg information
-            if (newPackage != null) {
-                removeInstalledPackageLI(newPackage, true);
-            }
-            // Add back the old system package
-            try {
-                final List<ScanResult> scanResults = scanPackageTracedLI(
-                        deletedPackage, parseFlags, SCAN_UPDATE_SIGNATURE, 0, user);
-                commitSuccessfulScanResults(scanResults);
-            } catch (PackageManagerException e) {
-                Slog.e(TAG, "Failed to restore original package: " + e.getMessage());
-            }
-
-            synchronized (mPackages) {
-                if (disabledSystem) {
-                    enableSystemPackageLPw(deletedPackage);
-                }
-
-                // Ensure the installer package name up to date
-                setInstallerPackageNameLPw(deletedPackage, installerPackageName);
-
-                // Update permissions for restored package
-                mPermissionManager.updatePermissions(
-                        deletedPackage.packageName, deletedPackage, false, mPackages.values(),
-                        mPermissionCallback);
-
-                mSettings.writeLPr();
-            }
-
-            Slog.i(TAG, "Successfully restored package : " + deletedPackage.packageName
-                    + " after failed upgrade");
-        }
-    }
-
     /**
      * Checks whether the parent or any of the child packages have a change shared
      * user. For a package to be a valid update the shred users of the parent and
@@ -15394,92 +14893,683 @@
 
         Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
     }
+
     private static class InstallRequest {
-        final InstallArgs args;
-        final PackageInstalledInfo res;
+        public final InstallArgs args;
+        public final PackageInstalledInfo installResult;
 
         private InstallRequest(InstallArgs args, PackageInstalledInfo res) {
             this.args = args;
-            this.res = res;
+            this.installResult = res;
         }
     }
 
     @GuardedBy({"mInstallLock", "mPackages"})
-    private void installPackageTracedLI(InstallArgs args, PackageInstalledInfo res) {
+    private void installPackageTracedLI(InstallArgs args, PackageInstalledInfo installResult) {
         try {
             Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installPackage");
-            installPackagesLI(Collections.singletonList(new InstallRequest(args, res)));
+            installPackagesLI(Collections.singletonList(new InstallRequest(args, installResult)));
         } finally {
             Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
         }
     }
 
+    /**
+     * Package state to commit to memory and disk after reconciliation has completed.
+     */
     private static class CommitRequest {
         final Map<String, ReconciledPackage> reconciledPackages;
+        final int[] mAllUsers;
 
-        private CommitRequest(Map<String, ReconciledPackage> reconciledPackages) {
+        private CommitRequest(Map<String, ReconciledPackage> reconciledPackages, int[] allUsers) {
             this.reconciledPackages = reconciledPackages;
+            this.mAllUsers = allUsers;
         }
     }
-    private static class ReconcileRequest {
-        final Map<String, ScanResult> scannedPackages;
 
-        private ReconcileRequest(Map<String, ScanResult> scannedPackages) {
+    /**
+     * Package scan results and related request details used to reconcile the potential addition of
+     * one or more packages to the system.
+     *
+     * Reconcile will take a set of package details that need to be committed to the system and make
+     * sure that they are valid in the context of the system and the other installing apps. Any
+     * invalid state or app will result in a failed reconciliation and thus whatever operation (such
+     * as install) led to the request.
+     */
+    private static class ReconcileRequest {
+        public final Map<String, ScanResult> scannedPackages;
+
+        // TODO: Remove install-specific details from reconcile request; make them generic types
+        //       that can be used for scanDir for example.
+        public final Map<String, InstallArgs> installArgs;
+        public final Map<String, PackageInstalledInfo> installResults;
+        public final Map<String, PrepareResult> preparedPackages;
+
+        private ReconcileRequest(Map<String, ScanResult> scannedPackages,
+                Map<String, InstallArgs> installArgs,
+                Map<String, PackageInstalledInfo> installResults,
+                Map<String, PrepareResult> preparedPackages) {
             this.scannedPackages = scannedPackages;
+            this.installArgs = installArgs;
+            this.installResults = installResults;
+            this.preparedPackages = preparedPackages;
         }
     }
     private static class ReconcileFailure extends PackageManagerException {
         public ReconcileFailure(String message) {
             super("Invalid reconcile request: " + message);
         }
-    };
+    }
 
     /**
      * A container of all data needed to commit a package to in-memory data structures and to disk.
-     * Ideally most of the data contained in this class will move into a PackageSetting it contains.
+     * TODO: move most of the data contained her into a PackageSetting for commit.
      */
-    private static class ReconciledPackage {}
+    private static class ReconciledPackage {
+        public final PackageSetting pkgSetting;
+        public final ScanResult scanResult;
+        public final UserHandle installForUser;
+        public final String volumeUuid;
+        // TODO: Remove install-specific details from the reconcile result
+        public final PackageInstalledInfo installResult;
+        public final PrepareResult prepareResult;
+        @PackageManager.InstallFlags
+        public final int installFlags;
+        public final InstallArgs installArgs;
+
+        private ReconciledPackage(InstallArgs installArgs, PackageSetting pkgSetting,
+                UserHandle installForUser, PackageInstalledInfo installResult, int installFlags,
+                String volumeUuid, PrepareResult prepareResult, ScanResult scanResult) {
+            this.installArgs = installArgs;
+            this.pkgSetting = pkgSetting;
+            this.installForUser = installForUser;
+            this.installResult = installResult;
+            this.installFlags = installFlags;
+            this.volumeUuid = volumeUuid;
+            this.prepareResult = prepareResult;
+            this.scanResult = scanResult;
+        }
+    }
 
     @GuardedBy("mPackages")
     private static Map<String, ReconciledPackage> reconcilePackagesLocked(
-            final ReconcileRequest request) throws ReconcileFailure {
-        return Collections.emptyMap();
+            final ReconcileRequest request)
+            throws ReconcileFailure {
+        Map<String, ReconciledPackage> result = new ArrayMap<>(request.scannedPackages.size());
+        for (String installPackageName : request.installArgs.keySet()) {
+            final ScanResult scanResult = request.scannedPackages.get(installPackageName);
+            final InstallArgs installArgs = request.installArgs.get(installPackageName);
+            final PackageInstalledInfo res = request.installResults.get(installPackageName);
+            if (scanResult == null || installArgs == null || res == null) {
+                throw new ReconcileFailure(
+                        "inputs not balanced; missing argument for " + installPackageName);
+            }
+            result.put(installPackageName,
+                    new ReconciledPackage(installArgs, scanResult.pkgSetting, installArgs.getUser(),
+                            res, installArgs.installFlags, installArgs.volumeUuid,
+                            request.preparedPackages.get(installPackageName), scanResult));
+        }
+        return result;
     }
 
     @GuardedBy("mPackages")
     private boolean commitPackagesLocked(final CommitRequest request) {
+        // TODO: remove any expected failures from this method; this should only be able to fail due
+        //       to unavoidable errors (I/O, etc.)
+        for (ReconciledPackage reconciledPkg : request.reconciledPackages.values()) {
+            final ScanResult scanResult = reconciledPkg.scanResult;
+            final ScanRequest scanRequest = scanResult.request;
+            final PackageParser.Package pkg = scanRequest.pkg;
+            final String packageName = pkg.packageName;
+            final PackageInstalledInfo res = reconciledPkg.installResult;
+
+            if (reconciledPkg.prepareResult.replace) {
+                PackageParser.Package oldPackage = mPackages.get(packageName);
+                if (reconciledPkg.prepareResult.system) {
+                    // Remove existing system package
+                    removePackageLI(oldPackage, true);
+                    if (!disableSystemPackageLPw(oldPackage, pkg)) {
+                        // We didn't need to disable the .apk as a current system package,
+                        // which means we are replacing another update that is already
+                        // installed.  We need to make sure to delete the older one's .apk.
+                        res.removedInfo.args = createInstallArgsForExisting(0,
+                                oldPackage.applicationInfo.getCodePath(),
+                                oldPackage.applicationInfo.getResourcePath(),
+                                getAppDexInstructionSets(oldPackage.applicationInfo));
+                    } else {
+                        res.removedInfo.args = null;
+                    }
+
+                    // Set the update and install times
+                    PackageSetting deletedPkgSetting = (PackageSetting) oldPackage.mExtras;
+                    setInstallAndUpdateTime(pkg, deletedPkgSetting.firstInstallTime,
+                            System.currentTimeMillis());
+
+                    // Update the package dynamic state if succeeded
+                    // Now that the install succeeded make sure we remove data
+                    // directories for any child package the update removed.
+                    final int deletedChildCount = (oldPackage.childPackages != null)
+                            ? oldPackage.childPackages.size() : 0;
+                    final int newChildCount = (pkg.childPackages != null)
+                            ? pkg.childPackages.size() : 0;
+                    for (int i = 0; i < deletedChildCount; i++) {
+                        PackageParser.Package deletedChildPkg = oldPackage.childPackages.get(i);
+                        boolean childPackageDeleted = true;
+                        for (int j = 0; j < newChildCount; j++) {
+                            PackageParser.Package newChildPkg = pkg.childPackages.get(j);
+                            if (deletedChildPkg.packageName.equals(newChildPkg.packageName)) {
+                                childPackageDeleted = false;
+                                break;
+                            }
+                        }
+                        if (childPackageDeleted) {
+                            PackageSetting ps1 = mSettings.getDisabledSystemPkgLPr(
+                                    deletedChildPkg.packageName);
+                            if (ps1 != null && res.removedInfo.removedChildPackages != null) {
+                                PackageRemovedInfo removedChildRes = res.removedInfo
+                                        .removedChildPackages.get(deletedChildPkg.packageName);
+                                removePackageDataLIF(ps1, request.mAllUsers, removedChildRes, 0,
+                                        false);
+                                removedChildRes.removedForAllUsers = mPackages.get(ps1.name)
+                                        == null;
+                            }
+                        }
+                    }
+                } else {
+                    final boolean killApp = (scanRequest.scanFlags & SCAN_DONT_KILL_APP) == 0;
+                    final int deleteFlags = PackageManager.DELETE_KEEP_DATA
+                            | (killApp ? 0 : PackageManager.DELETE_DONT_KILL_APP);
+                    // First delete the existing package while retaining the data directory
+                    if (!deletePackageLIF(packageName, null, true, request.mAllUsers, deleteFlags,
+                            res.removedInfo, true, pkg)) {
+                        // If the existing package wasn't successfully deleted
+                        res.setError(INSTALL_FAILED_REPLACE_COULDNT_DELETE,
+                                "replaceNonSystemPackageLI");
+                        return false;
+                    } else {
+                        // Successfully deleted the old package; proceed with replace.
+
+                        // If deleted package lived in a container, give users a chance to
+                        // relinquish resources before killing.
+                        if (oldPackage.isForwardLocked() || isExternal(oldPackage)) {
+                            if (DEBUG_INSTALL) {
+                                Slog.i(TAG, "upgrading pkg " + oldPackage
+                                        + " is ASEC-hosted -> UNAVAILABLE");
+                            }
+                            final int[] uidArray = new int[]{oldPackage.applicationInfo.uid};
+                            final ArrayList<String> pkgList = new ArrayList<>(1);
+                            pkgList.add(oldPackage.applicationInfo.packageName);
+                            sendResourcesChangedBroadcast(false, true, pkgList, uidArray, null);
+                        }
+
+                        clearAppDataLIF(pkg, UserHandle.USER_ALL, StorageManager.FLAG_STORAGE_DE
+                                | StorageManager.FLAG_STORAGE_CE
+                                | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
+                    }
+
+
+
+                    // Update the in-memory copy of the previous code paths.
+                    PackageSetting ps1 = mSettings.mPackages.get(
+                            reconciledPkg.prepareResult.existingPackage.packageName);
+                    if ((reconciledPkg.installArgs.installFlags & PackageManager.DONT_KILL_APP)
+                            == 0) {
+                        if (ps1.mOldCodePaths == null) {
+                            ps1.mOldCodePaths = new ArraySet<>();
+                        }
+                        Collections.addAll(ps1.mOldCodePaths, oldPackage.baseCodePath);
+                        if (oldPackage.splitCodePaths != null) {
+                            Collections.addAll(ps1.mOldCodePaths, oldPackage.splitCodePaths);
+                        }
+                    } else {
+                        ps1.mOldCodePaths = null;
+                    }
+                    if (ps1.childPackageNames != null) {
+                        for (int i = ps1.childPackageNames.size() - 1; i >= 0; --i) {
+                            final String childPkgName = ps1.childPackageNames.get(i);
+                            final PackageSetting childPs = mSettings.mPackages.get(childPkgName);
+                            childPs.mOldCodePaths = ps1.mOldCodePaths;
+                        }
+                    }
+
+                    if (reconciledPkg.installResult.returnCode
+                            == PackageManager.INSTALL_SUCCEEDED) {
+                        PackageSetting ps2 = mSettings.getPackageLPr(pkg.packageName);
+                        if (ps2 != null) {
+                            res.removedInfo.removedForAllUsers = mPackages.get(ps2.name) == null;
+                            if (res.removedInfo.removedChildPackages != null) {
+                                final int childCount1 = res.removedInfo.removedChildPackages.size();
+                                // Iterate in reverse as we may modify the collection
+                                for (int i = childCount1 - 1; i >= 0; i--) {
+                                    String childPackageName =
+                                            res.removedInfo.removedChildPackages.keyAt(i);
+                                    if (res.addedChildPackages.containsKey(childPackageName)) {
+                                        res.removedInfo.removedChildPackages.removeAt(i);
+                                    } else {
+                                        PackageRemovedInfo childInfo = res.removedInfo
+                                                .removedChildPackages.valueAt(i);
+                                        childInfo.removedForAllUsers = mPackages.get(
+                                                childInfo.removedPackage) == null;
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+
+
+
+            try {
+                commitScanResultLocked(scanResult);
+            } catch (PackageManagerException e) {
+                res.setReturnCode(INSTALL_FAILED_INTERNAL_ERROR);
+                res.setError("Package couldn't be installed in " + pkg.codePath, e);
+                return false;
+            }
+            updateSettingsLI(pkg, reconciledPkg.installArgs.installerPackageName, request.mAllUsers,
+                    res, reconciledPkg.installForUser, reconciledPkg.installArgs.installReason);
+
+            final PackageSetting ps = mSettings.mPackages.get(packageName);
+            if (ps != null) {
+                res.newUsers = ps.queryInstalledUsers(sUserManager.getUserIds(), true);
+                ps.setUpdateAvailable(false /*updateAvailable*/);
+            }
+            final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
+            for (int i = 0; i < childCount; i++) {
+                PackageParser.Package childPkg = pkg.childPackages.get(i);
+                PackageInstalledInfo childRes = res.addedChildPackages.get(
+                        childPkg.packageName);
+                PackageSetting childPs = mSettings.getPackageLPr(childPkg.packageName);
+                if (childPs != null) {
+                    childRes.newUsers = childPs.queryInstalledUsers(
+                            sUserManager.getUserIds(), true);
+                }
+            }
+            if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
+                updateSequenceNumberLP(ps, res.newUsers);
+                updateInstantAppInstallerLocked(packageName);
+            }
+        }
         return true;
     }
 
-    @GuardedBy({"mInstallLock", "mPackages", "PackageManagerService.mPackages"})
+    /**
+     * Installs one or more packages atomically. This operation is broken up into four phases:
+     * <ul>
+     *     <li><b>Prepare</b>
+     *         <br/>Analyzes any current install state, parses the package and does initial
+     *         validation on it.</li>
+     *     <li><b>Scan</b>
+     *         <br/>Interrogates the parsed packages given the context collected in prepare.</li>
+     *     <li><b>Reconcile</b>
+     *         <br/>Validates scanned packages in the context of each other and the current system
+     *         state to ensure that the install will be successful.
+     *     <li><b>Commit</b>
+     *         <br/>Commits all scanned packages and updates system state. This is the only place
+     *         that system state may be modified in the install flow and all predictable errors
+     *         must be determined before this phase.</li>
+     * </ul>
+     *
+     * Failure at any phase will result in a full failure to install all packages.
+     */
+    @GuardedBy({"mInstallLock", "mPackages"})
     private void installPackagesLI(List<InstallRequest> requests) {
-        Map<String, ScanResult> scans = new ArrayMap<>(requests.size());
-        for (InstallRequest request : requests) {
-            // TODO(b/109941548): remove this once we've pulled everything from it and into scan,
-            // reconcile or commit.
-            preparePackageLI(request.args, request.res);
-
-            // TODO(b/109941548): scan package and get result
-        }
-        ReconcileRequest reconcileRequest = new ReconcileRequest(scans);
-        Map<String, ReconciledPackage> reconciledPackages;
+        final Map<String, ScanResult> scans = new ArrayMap<>(requests.size());
+        final Map<String, InstallArgs> installArgs = new ArrayMap<>(requests.size());
+        final Map<String, PackageInstalledInfo> installResults = new ArrayMap<>(requests.size());
+        final Map<String, PrepareResult> prepareResults = new ArrayMap<>(requests.size());
         try {
-            reconciledPackages = reconcilePackagesLocked(reconcileRequest);
-        } catch (ReconcileFailure e) {
-            // TODO(b/109941548): set install args error
-            return;
+            Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installPackagesLI");
+            for (InstallRequest request : requests) {
+                // TODO(b/109941548): remove this once we've pulled everything from it and into
+                //                    scan, reconcile or commit.
+                final PrepareResult prepareResult;
+                try {
+                    Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "preparePackage");
+                    prepareResult = preparePackageLI(request.args, request.installResult);
+                } catch (PrepareFailure prepareFailure) {
+                    request.installResult.setError(prepareFailure.error,
+                            prepareFailure.getMessage());
+                    request.installResult.origPackage = prepareFailure.conflictingPackage;
+                    request.installResult.origPermission = prepareFailure.conflictingPermission;
+                    return;
+                } finally {
+                    Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+                }
+                request.installResult.setReturnCode(PackageManager.INSTALL_SUCCEEDED);
+                request.installResult.installerPackageName = request.args.installerPackageName;
+
+                final String packageName = prepareResult.packageToScan.packageName;
+                prepareResults.put(packageName, prepareResult);
+                installResults.put(packageName, request.installResult);
+                installArgs.put(packageName, request.args);
+                try {
+                    final List<ScanResult> scanResults = scanPackageTracedLI(
+                            prepareResult.packageToScan, prepareResult.parseFlags,
+                            prepareResult.scanFlags, System.currentTimeMillis(),
+                            request.args.user);
+                    for (ScanResult result : scanResults) {
+                        if (null != scans.put(result.pkgSetting.pkg.packageName, result)) {
+                            request.installResult.setError(
+                                    PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE,
+                                    "Duplicate package " + result.pkgSetting.pkg.packageName
+                                            + " in atomic install request.");
+                            return;
+                        }
+                    }
+                } catch (PackageManagerException e) {
+                    request.installResult.setError("Scanning Failed.", e);
+                    return;
+                }
+            }
+            ReconcileRequest reconcileRequest = new ReconcileRequest(scans, installArgs,
+                    installResults,
+                    prepareResults);
+            CommitRequest commitRequest = null;
+            synchronized (mPackages) {
+                Map<String, ReconciledPackage> reconciledPackages;
+                try {
+                    Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "reconcilePackages");
+                    reconciledPackages = reconcilePackagesLocked(reconcileRequest);
+                } catch (ReconcileFailure e) {
+                    for (InstallRequest request : requests) {
+                        // TODO(b/109941548): add more concrete failure reasons
+                        request.installResult.setError("Reconciliation failed...", e);
+                        // TODO: return any used system resources
+                    }
+                    return;
+                } finally {
+                    Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+                }
+                try {
+                    Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "commitPackages");
+                    commitRequest = new CommitRequest(reconciledPackages,
+                            sUserManager.getUserIds());
+                    if (!commitPackagesLocked(commitRequest)) {
+                        cleanUpCommitFailuresLocked(commitRequest);
+                        return;
+                    }
+                } finally {
+                    for (PrepareResult result : prepareResults.values()) {
+                        if (result.freezer != null) {
+                            result.freezer.close();
+                        }
+                    }
+                    Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+                }
+            }
+            executePostCommitSteps(commitRequest);
+        } finally {
+            for (PrepareResult result : prepareResults.values()) {
+                if (result.freezer != null) {
+                    result.freezer.close();
+                }
+            }
+            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
         }
-        CommitRequest request = new CommitRequest(reconciledPackages);
-        if (!commitPackagesLocked(request)) {
-            // TODO(b/109941548): set install args error
-            return;
-        }
-        // TODO(b/109941548) post-commit actions (dex-opt, etc.)
     }
 
-    @Deprecated
+    /**
+     * On successful install, executes remaining steps after commit completes and the package lock
+     * is released.
+     */
+    private void executePostCommitSteps(CommitRequest commitRequest) {
+        for (ReconciledPackage reconciledPkg : commitRequest.reconciledPackages.values()) {
+            final boolean forwardLocked =
+                    ((reconciledPkg.installFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0);
+            final boolean instantApp =
+                    ((reconciledPkg.installFlags & PackageManager.INSTALL_INSTANT_APP) != 0);
+            final PackageParser.Package pkg = reconciledPkg.pkgSetting.pkg;
+            final String packageName = pkg.packageName;
+            prepareAppDataAfterInstallLIF(pkg);
+            if (reconciledPkg.prepareResult.clearCodeCache) {
+                clearAppDataLIF(pkg, UserHandle.USER_ALL, StorageManager.FLAG_STORAGE_DE
+                        | StorageManager.FLAG_STORAGE_CE | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
+            }
+            if (reconciledPkg.prepareResult.replace) {
+                mDexManager.notifyPackageUpdated(pkg.packageName,
+                        pkg.baseCodePath, pkg.splitCodePaths);
+            }
+
+            // Prepare the application profiles for the new code paths.
+            // This needs to be done before invoking dexopt so that any install-time profile
+            // can be used for optimizations.
+            mArtManagerService.prepareAppProfiles(
+                    pkg, resolveUserIds(reconciledPkg.installForUser.getIdentifier()));
+
+            // Check whether we need to dexopt the app.
+            //
+            // NOTE: it is IMPORTANT to call dexopt:
+            //   - after doRename which will sync the package data from PackageParser.Package and
+            //     its corresponding ApplicationInfo.
+            //   - after installNewPackageLIF or replacePackageLIF which will update result with the
+            //     uid of the application (pkg.applicationInfo.uid).
+            //     This update happens in place!
+            //
+            // We only need to dexopt if the package meets ALL of the following conditions:
+            //   1) it is not forward locked.
+            //   2) it is not on on an external ASEC container.
+            //   3) it is not an instant app or if it is then dexopt is enabled via gservices.
+            //   4) it is not debuggable.
+            //
+            // Note that we do not dexopt instant apps by default. dexopt can take some time to
+            // complete, so we skip this step during installation. Instead, we'll take extra time
+            // the first time the instant app starts. It's preferred to do it this way to provide
+            // continuous progress to the useur instead of mysteriously blocking somewhere in the
+            // middle of running an instant app. The default behaviour can be overridden
+            // via gservices.
+            final boolean performDexopt = !forwardLocked
+                    && !pkg.applicationInfo.isExternalAsec()
+                    && (!instantApp || Global.getInt(mContext.getContentResolver(),
+                    Global.INSTANT_APP_DEXOPT_ENABLED, 0) != 0)
+                    && ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) == 0);
+
+            if (performDexopt) {
+                Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt");
+                // Do not run PackageDexOptimizer through the local performDexOpt
+                // method because `pkg` may not be in `mPackages` yet.
+                //
+                // Also, don't fail application installs if the dexopt step fails.
+                DexoptOptions dexoptOptions = new DexoptOptions(packageName,
+                        REASON_INSTALL,
+                        DexoptOptions.DEXOPT_BOOT_COMPLETE
+                                | DexoptOptions.DEXOPT_INSTALL_WITH_DEX_METADATA_FILE);
+                mPackageDexOptimizer.performDexOpt(pkg, pkg.usesLibraryFiles,
+                        null /* instructionSets */,
+                        getOrCreateCompilerPackageStats(pkg),
+                        mDexManager.getPackageUseInfoOrDefault(packageName),
+                        dexoptOptions);
+                Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+            }
+
+            // Notify BackgroundDexOptService that the package has been changed.
+            // If this is an update of a package which used to fail to compile,
+            // BackgroundDexOptService will remove it from its blacklist.
+            // TODO: Layering violation
+            BackgroundDexOptService.notifyPackageChanged(packageName);
+        }
+
+    }
+
+    private void cleanUpCommitFailuresLocked(CommitRequest request) {
+        final Map<String, ReconciledPackage> reconciledPackages = request.reconciledPackages;
+        final int[] allUsers = request.mAllUsers;
+        for (ReconciledPackage reconciledPackage : reconciledPackages.values()) {
+            final String pkgName1 = reconciledPackage.pkgSetting.pkg.packageName;
+            if (reconciledPackage.installResult.returnCode == PackageManager.INSTALL_SUCCEEDED) {
+                reconciledPackage.installResult.setError(
+                        PackageManager.INSTALL_FAILED_INTERNAL_ERROR, "Commit failed...");
+            }
+            final PackageParser.Package oldPackage =
+                    reconciledPackage.prepareResult.existingPackage;
+            final PackageParser.Package newPackage = reconciledPackage.pkgSetting.pkg;
+            if (reconciledPackage.prepareResult.system) {
+                // Re installation failed. Restore old information
+                // Remove new pkg information
+                if (newPackage != null) {
+                    removeInstalledPackageLI(newPackage, true);
+                }
+                // Add back the old system package
+                PackageParser.Package restoredPkg = null;
+                try {
+                    final List<ScanResult> restoreResults = scanPackageTracedLI(oldPackage,
+                            reconciledPackage.prepareResult.parseFlags, SCAN_UPDATE_SIGNATURE, 0,
+                            reconciledPackage.installForUser);
+                    commitSuccessfulScanResults(restoreResults);
+                    restoredPkg = restoreResults.get(0).pkgSetting.pkg;
+                } catch (PackageManagerException e) {
+                    Slog.e(TAG, "Failed to restore original package: " + e.getMessage());
+                }
+                synchronized (mPackages) {
+                    final boolean disabledSystem;
+                    // Remove existing system package
+                    removePackageLI(reconciledPackage.scanResult.pkgSetting.pkg, true);
+                    disabledSystem = disableSystemPackageLPw(
+                            reconciledPackage.scanResult.pkgSetting.pkg, restoredPkg);
+                    if (disabledSystem) {
+                        enableSystemPackageLPw(restoredPkg);
+                    }
+                    // Ensure the installer package name up to date
+                    setInstallerPackageNameLPw(reconciledPackage.scanResult.pkgSetting.pkg,
+                            reconciledPackage.installArgs.installerPackageName);
+                    // Update permissions for restored package
+                    mPermissionManager.updatePermissions(
+                            restoredPkg.packageName, restoredPkg, false, mPackages.values(),
+                            mPermissionCallback);
+                    mSettings.writeLPr();
+                }
+                Slog.i(TAG, "Successfully restored package : " + restoredPkg.packageName
+                        + " after failed upgrade");
+            } else if (reconciledPackage.prepareResult.replace) {
+                if (DEBUG_INSTALL) Slog.d(TAG, "Install failed, rolling pack: " + pkgName1);
+
+                // Revert all internal state mutations and added folders for the failed install
+                boolean deletedPkg = deletePackageLIF(pkgName1, null, true,
+                        allUsers, /*TODO: deleteFlags*/ 0,
+                        reconciledPackage.installResult.removedInfo, true, null);
+
+                // Restore the old package
+                if (deletedPkg) {
+                    if (DEBUG_INSTALL) Slog.d(TAG, "Install failed, reinstalling: " + oldPackage);
+                    File restoreFile = new File(oldPackage.codePath);
+                    // Parse old package
+                    boolean oldExternal = isExternal(oldPackage);
+                    int oldParseFlags = mDefParseFlags | PackageParser.PARSE_CHATTY
+                            | (oldPackage.isForwardLocked() ? PackageParser.PARSE_FORWARD_LOCK : 0)
+                            | (oldExternal ? PackageParser.PARSE_EXTERNAL_STORAGE : 0);
+                    int oldScanFlags = SCAN_UPDATE_SIGNATURE | SCAN_UPDATE_TIME;
+                    try {
+                        scanPackageTracedLI(restoreFile, oldParseFlags, oldScanFlags,
+                                /* origUpdateTime */ System.currentTimeMillis(), null);
+                    } catch (PackageManagerException e) {
+                        Slog.e(TAG, "Failed to restore package : " + pkgName1
+                                + " after failed upgrade: "
+                                + e.getMessage());
+                        return;
+                    }
+
+                    synchronized (mPackages) {
+                        // Ensure the installer package name up to date
+                        setInstallerPackageNameLPw(oldPackage,
+                                reconciledPackage.installArgs.installerPackageName);
+
+                        // Update permissions for restored package
+                        mPermissionManager.updatePermissions(
+                                oldPackage.packageName, oldPackage, false, mPackages.values(),
+                                mPermissionCallback);
+
+                        mSettings.writeLPr();
+                    }
+
+                    Slog.i(TAG, "Successfully restored package : " + pkgName1
+                            + " after failed upgrade");
+                }
+            } else {
+                // Remove package from internal structures, but keep around any
+                // data that might have already existed
+                deletePackageLIF(pkgName1, UserHandle.ALL, false, null,
+                        PackageManager.DELETE_KEEP_DATA,
+                        reconciledPackage.installResult.removedInfo, true, null);
+            }
+        }
+    }
+
+    /**
+     * The set of data needed to successfully install the prepared package. This includes data that
+     * will be used to scan and reconcile the package.
+     */
+    private static class PrepareResult {
+        public final int installReason;
+        public final String volumeUuid;
+        public final String installerPackageName;
+        public final UserHandle user;
+        public final boolean replace;
+        public final int scanFlags;
+        public final int parseFlags;
+        @Nullable /* The original Package if it is being replaced, otherwise {@code null} */
+        public final PackageParser.Package existingPackage;
+        public final PackageParser.Package packageToScan;
+        public final boolean clearCodeCache;
+        public final boolean system;
+        /* The original package name if it was changed during an update, otherwise {@code null}. */
+        @Nullable
+        public final String renamedPackage;
+        public final PackageFreezer freezer;
+
+        private PrepareResult(int installReason, String volumeUuid,
+                String installerPackageName, UserHandle user, boolean replace, int scanFlags,
+                int parseFlags, PackageParser.Package existingPackage,
+                PackageParser.Package packageToScan, boolean clearCodeCache, boolean system,
+                String renamedPackage,
+                PackageFreezer freezer) {
+            this.installReason = installReason;
+            this.volumeUuid = volumeUuid;
+            this.installerPackageName = installerPackageName;
+            this.user = user;
+            this.replace = replace;
+            this.scanFlags = scanFlags;
+            this.parseFlags = parseFlags;
+            this.existingPackage = existingPackage;
+            this.packageToScan = packageToScan;
+            this.clearCodeCache = clearCodeCache;
+            this.system = system;
+            this.renamedPackage = renamedPackage;
+            this.freezer = freezer;
+        }
+    }
+
+    private static class PrepareFailure extends PackageManagerException {
+
+        public String conflictingPackage;
+        public String conflictingPermission;
+
+        PrepareFailure(int error) {
+            super(error, "Failed to prepare for install.");
+        }
+
+        PrepareFailure(int error, String detailMessage) {
+            super(error, detailMessage);
+        }
+
+        PrepareFailure(String message, Exception e) {
+            super(e instanceof PackageParserException
+                    ? ((PackageParserException) e).error
+                    : ((PackageManagerException) e).error,
+                    ExceptionUtils.getCompleteMessage(message, e));
+        }
+
+        PrepareFailure conflictsWithExistingPermission(String conflictingPermission,
+                String conflictingPackage) {
+            this.conflictingPermission = conflictingPermission;
+            this.conflictingPackage = conflictingPackage;
+            return this;
+        }
+    }
+
     @GuardedBy("mInstallLock")
-    private void preparePackageLI(InstallArgs args, PackageInstalledInfo res) {
+    private PrepareResult preparePackageLI(InstallArgs args, PackageInstalledInfo res)
+            throws PrepareFailure {
         final int installFlags = args.installFlags;
         final String installerPackageName = args.installerPackageName;
         final String volumeUuid = args.volumeUuid;
@@ -15492,7 +15582,6 @@
         final boolean forceSdk = ((installFlags & PackageManager.INSTALL_FORCE_SDK) != 0);
         final boolean virtualPreload =
                 ((installFlags & PackageManager.INSTALL_VIRTUAL_PRELOAD) != 0);
-        boolean replace = false;
         @ScanFlags int scanFlags = SCAN_NEW_INSTALL | SCAN_UPDATE_SIGNATURE;
         if (args.move != null) {
             // moving a complete application; perform an initial scan on the new install location
@@ -15511,18 +15600,13 @@
             scanFlags |= SCAN_AS_VIRTUAL_PRELOAD;
         }
 
-        // Result object to be returned
-        res.setReturnCode(PackageManager.INSTALL_SUCCEEDED);
-        res.installerPackageName = installerPackageName;
-
         if (DEBUG_INSTALL) Slog.d(TAG, "installPackageLI: path=" + tmpPackageFile);
 
         // Sanity check
         if (instantApp && (forwardLocked || onExternal)) {
             Slog.i(TAG, "Incompatible ephemeral install; fwdLocked=" + forwardLocked
                     + " external=" + onExternal);
-            res.setReturnCode(PackageManager.INSTALL_FAILED_INSTANT_APP_INVALID);
-            return;
+            throw new PrepareFailure(PackageManager.INSTALL_FAILED_INSTANT_APP_INVALID);
         }
 
         // Retrieve PackageSettings and parse package
@@ -15531,6 +15615,7 @@
                 | (forwardLocked ? PackageParser.PARSE_FORWARD_LOCK : 0)
                 | (onExternal ? PackageParser.PARSE_EXTERNAL_STORAGE : 0)
                 | (forceSdk ? PackageParser.PARSE_FORCE_SDK : 0);
+
         PackageParser pp = new PackageParser();
         pp.setSeparateProcesses(mSeparateProcesses);
         pp.setDisplayMetrics(mMetrics);
@@ -15542,8 +15627,7 @@
             pkg = pp.parsePackage(tmpPackageFile, parseFlags);
             DexMetadataHelper.validatePackageDexMetadata(pkg);
         } catch (PackageParserException e) {
-            res.setError("Failed parse during installPackageLI", e);
-            return;
+            throw new PrepareFailure("Failed parse during installPackageLI", e);
         } finally {
             Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
         }
@@ -15553,16 +15637,14 @@
             if (pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.O) {
                 Slog.w(TAG,
                         "Instant app package " + pkg.packageName + " does not target at least O");
-                res.setError(INSTALL_FAILED_INSTANT_APP_INVALID,
+                throw new PrepareFailure(INSTALL_FAILED_INSTANT_APP_INVALID,
                         "Instant app package must target at least O");
-                return;
             }
             if (pkg.mSharedUserId != null) {
                 Slog.w(TAG, "Instant app package " + pkg.packageName
                         + " may not declare sharedUserId.");
-                res.setError(INSTALL_FAILED_INSTANT_APP_INVALID,
+                throw new PrepareFailure(INSTALL_FAILED_INSTANT_APP_INVALID,
                         "Instant app package may not declare a sharedUserId");
-                return;
             }
         }
 
@@ -15573,9 +15655,8 @@
             // No static shared libs on external storage
             if (onExternal) {
                 Slog.i(TAG, "Static shared libs can only be installed on internal storage.");
-                res.setError(INSTALL_FAILED_INVALID_INSTALL_LOCATION,
+                throw new PrepareFailure(INSTALL_FAILED_INVALID_INSTALL_LOCATION,
                         "Packages declaring static-shared libs cannot be updated");
-                return;
             }
         }
 
@@ -15614,10 +15695,9 @@
         }
 
         String pkgName = res.name = pkg.packageName;
-        if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_TEST_ONLY) != 0) {
+        if ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_TEST_ONLY) != 0) {
             if ((installFlags & PackageManager.INSTALL_ALLOW_TEST) == 0) {
-                res.setError(INSTALL_FAILED_TEST_ONLY, "installPackageLI");
-                return;
+                throw new PrepareFailure(INSTALL_FAILED_TEST_ONLY, "installPackageLI");
             }
         }
 
@@ -15629,22 +15709,21 @@
                 PackageParser.collectCertificates(pkg, false /* skipVerify */);
             }
         } catch (PackageParserException e) {
-            res.setError("Failed collect during installPackageLI", e);
-            return;
+            throw new PrepareFailure("Failed collect during installPackageLI", e);
         }
 
         if (instantApp && pkg.mSigningDetails.signatureSchemeVersion
                 < SignatureSchemeVersion.SIGNING_BLOCK_V2) {
             Slog.w(TAG, "Instant app package " + pkg.packageName
                     + " is not signed with at least APK Signature Scheme v2");
-            res.setError(INSTALL_FAILED_INSTANT_APP_INVALID,
+            throw new PrepareFailure(INSTALL_FAILED_INSTANT_APP_INVALID,
                     "Instant app package must be signed with APK Signature Scheme v2 or greater");
-            return;
         }
 
         // Get rid of all references to package scan path via parser.
         pp = null;
         boolean systemApp = false;
+        boolean replace = false;
         synchronized (mPackages) {
             // Check if installing already existing package
             if ((installFlags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
@@ -15659,8 +15738,10 @@
                     pkg.setPackageName(oldName);
                     pkgName = pkg.packageName;
                     replace = true;
-                    if (DEBUG_INSTALL) Slog.d(TAG, "Replacing existing renamed package: oldName="
-                            + oldName + " pkgName=" + pkgName);
+                    if (DEBUG_INSTALL) {
+                        Slog.d(TAG, "Replacing existing renamed package: oldName="
+                                + oldName + " pkgName=" + pkgName);
+                    }
                 } else if (mPackages.containsKey(pkgName)) {
                     // This package, under its official name, already exists
                     // on the device; we should replace it.
@@ -15670,11 +15751,11 @@
 
                 // Child packages are installed through the parent package
                 if (pkg.parentPackage != null) {
-                    res.setError(PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME,
+                    throw new PrepareFailure(
+                            PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME,
                             "Package " + pkg.packageName + " is child of package "
                                     + pkg.parentPackage.parentPackage + ". Child packages "
                                     + "can be updated only through the parent package.");
-                    return;
                 }
 
                 if (replace) {
@@ -15684,26 +15765,25 @@
                     final int newTargetSdk = pkg.applicationInfo.targetSdkVersion;
                     if (oldTargetSdk > Build.VERSION_CODES.LOLLIPOP_MR1
                             && newTargetSdk <= Build.VERSION_CODES.LOLLIPOP_MR1) {
-                        res.setError(PackageManager.INSTALL_FAILED_PERMISSION_MODEL_DOWNGRADE,
+                        throw new PrepareFailure(
+                                PackageManager.INSTALL_FAILED_PERMISSION_MODEL_DOWNGRADE,
                                 "Package " + pkg.packageName + " new target SDK " + newTargetSdk
                                         + " doesn't support runtime permissions but the old"
                                         + " target SDK " + oldTargetSdk + " does.");
-                        return;
                     }
                     // Prevent persistent apps from being updated
                     if ((oldPackage.applicationInfo.flags & ApplicationInfo.FLAG_PERSISTENT) != 0) {
-                        res.setError(PackageManager.INSTALL_FAILED_INVALID_APK,
+                        throw new PrepareFailure(PackageManager.INSTALL_FAILED_INVALID_APK,
                                 "Package " + oldPackage.packageName + " is a persistent app. "
                                         + "Persistent apps are not updateable.");
-                        return;
                     }
                     // Prevent installing of child packages
                     if (oldPackage.parentPackage != null) {
-                        res.setError(PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME,
+                        throw new PrepareFailure(
+                                PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME,
                                 "Package " + pkg.packageName + " is child of package "
                                         + oldPackage.parentPackage + ". Child packages "
                                         + "can be updated only through the parent package.");
-                        return;
                     }
                 }
             }
@@ -15730,10 +15810,9 @@
                 final KeySetManagerService ksms = mSettings.mKeySetManagerService;
                 if (ksms.shouldCheckUpgradeKeySetLocked(signatureCheckPs, scanFlags)) {
                     if (!ksms.checkUpgradeKeySetLocked(signatureCheckPs, pkg)) {
-                        res.setError(INSTALL_FAILED_UPDATE_INCOMPATIBLE, "Package "
+                        throw new PrepareFailure(INSTALL_FAILED_UPDATE_INCOMPATIBLE, "Package "
                                 + pkg.packageName + " upgrade keys do not match the "
                                 + "previously installed version");
-                        return;
                     }
                 } else {
                     try {
@@ -15750,8 +15829,7 @@
                             }
                         }
                     } catch (PackageManagerException e) {
-                        res.setError(e.error, e.getMessage());
-                        return;
+                        throw new PrepareFailure(e.error, e.getMessage());
                     }
                 }
 
@@ -15762,8 +15840,9 @@
                 res.origUsers = ps.queryInstalledUsers(sUserManager.getUserIds(), true);
             }
 
+
             int N = pkg.permissions.size();
-            for (int i = N-1; i >= 0; i--) {
+            for (int i = N - 1; i >= 0; i--) {
                 final PackageParser.Permission perm = pkg.permissions.get(i);
                 final BasePermission bp =
                         (BasePermission) mPermissionManager.getPermissionTEMP(perm.info.name);
@@ -15788,7 +15867,7 @@
                     final KeySetManagerService ksms = mSettings.mKeySetManagerService;
                     if (sourcePackageName.equals(pkg.packageName)
                             && (ksms.shouldCheckUpgradeKeySetLocked(
-                                    sourcePackageSetting, scanFlags))) {
+                            sourcePackageSetting, scanFlags))) {
                         sigsOk = ksms.checkUpgradeKeySetLocked(sourcePackageSetting, pkg);
                     } else {
 
@@ -15796,12 +15875,12 @@
                         // package's certificate has rotated from the current one, or if it is an
                         // older certificate with which the current is ok with sharing permissions
                         if (sourcePackageSetting.signatures.mSigningDetails.checkCapability(
-                                        pkg.mSigningDetails,
-                                        PackageParser.SigningDetails.CertCapabilities.PERMISSION)) {
+                                pkg.mSigningDetails,
+                                PackageParser.SigningDetails.CertCapabilities.PERMISSION)) {
                             sigsOk = true;
                         } else if (pkg.mSigningDetails.checkCapability(
-                                        sourcePackageSetting.signatures.mSigningDetails,
-                                        PackageParser.SigningDetails.CertCapabilities.PERMISSION)) {
+                                sourcePackageSetting.signatures.mSigningDetails,
+                                PackageParser.SigningDetails.CertCapabilities.PERMISSION)) {
 
                             // the scanned package checks out, has signing certificate rotation
                             // history, and is newer; bring it over
@@ -15816,12 +15895,13 @@
                         // install to proceed; we fail the install on all other permission
                         // redefinitions.
                         if (!sourcePackageName.equals("android")) {
-                            res.setError(INSTALL_FAILED_DUPLICATE_PERMISSION, "Package "
-                                    + pkg.packageName + " attempting to redeclare permission "
-                                    + perm.info.name + " already owned by " + sourcePackageName);
-                            res.origPermission = perm.info.name;
-                            res.origPackage = sourcePackageName;
-                            return;
+                            throw new PrepareFailure(INSTALL_FAILED_DUPLICATE_PERMISSION, "Package "
+                                    + pkg.packageName
+                                    + " attempting to redeclare permission "
+                                    + perm.info.name + " already owned by "
+                                    + sourcePackageName)
+                                    .conflictsWithExistingPermission(perm.info.name,
+                                            sourcePackageName);
                         } else {
                             Slog.w(TAG, "Package " + pkg.packageName
                                     + " attempting to redeclare system permission "
@@ -15850,14 +15930,12 @@
         if (systemApp) {
             if (onExternal) {
                 // Abort update; system app can't be replaced with app on sdcard
-                res.setError(INSTALL_FAILED_INVALID_INSTALL_LOCATION,
+                throw new PrepareFailure(INSTALL_FAILED_INVALID_INSTALL_LOCATION,
                         "Cannot install updates to system apps on sdcard");
-                return;
             } else if (instantApp) {
                 // Abort update; system app can't be replaced with an instant app
-                res.setError(INSTALL_FAILED_INSTANT_APP_INVALID,
+                throw new PrepareFailure(INSTALL_FAILED_INSTANT_APP_INVALID,
                         "Cannot update a system app with an instant app");
-                return;
             }
         }
 
@@ -15885,13 +15963,13 @@
 
             try {
                 String abiOverride = (TextUtils.isEmpty(pkg.cpuAbiOverride) ?
-                    args.abiOverride : pkg.cpuAbiOverride);
+                        args.abiOverride : pkg.cpuAbiOverride);
                 final boolean extractNativeLibs = !pkg.isLibrary();
                 derivePackageAbi(pkg, abiOverride, extractNativeLibs);
             } catch (PackageManagerException pme) {
                 Slog.e(TAG, "Error deriving application ABI", pme);
-                res.setError(INSTALL_FAILED_INTERNAL_ERROR, "Error deriving application ABI");
-                return;
+                throw new PrepareFailure(INSTALL_FAILED_INTERNAL_ERROR,
+                        "Error deriving application ABI");
             }
 
             // Shared libraries for the package need to be updated.
@@ -15905,8 +15983,7 @@
         }
 
         if (!args.doRename(res.returnCode, pkg)) {
-            res.setError(INSTALL_FAILED_INSUFFICIENT_STORAGE, "Failed rename");
-            return;
+            throw new PrepareFailure(INSTALL_FAILED_INSUFFICIENT_STORAGE, "Failed rename");
         }
 
         if (PackageManagerServiceUtils.isApkVerityEnabled()) {
@@ -15920,7 +15997,6 @@
                     apkPath = pkg.baseCodePath;
                 }
             }
-
             if (apkPath != null) {
                 final VerityUtils.SetupResult result =
                         VerityUtils.generateApkVeritySetupData(apkPath);
@@ -15932,16 +16008,15 @@
                         mInstaller.installApkVerity(apkPath, fd, result.getContentSize());
                         mInstaller.assertFsverityRootHashMatches(apkPath, signedRootHash);
                     } catch (InstallerException | IOException | DigestException |
-                             NoSuchAlgorithmException e) {
-                        res.setError(INSTALL_FAILED_INTERNAL_ERROR,
+                            NoSuchAlgorithmException e) {
+                        throw new PrepareFailure(INSTALL_FAILED_INTERNAL_ERROR,
                                 "Failed to set up verity: " + e);
-                        return;
                     } finally {
                         IoUtils.closeQuietly(fd);
                     }
                 } else if (result.isFailed()) {
-                    res.setError(INSTALL_FAILED_INTERNAL_ERROR, "Failed to generate verity");
-                    return;
+                    throw new PrepareFailure(INSTALL_FAILED_INTERNAL_ERROR,
+                            "Failed to generate verity");
                 } else {
                     // Do nothing if verity is skipped. Will fall back to full apk verification on
                     // reboot.
@@ -15956,109 +16031,293 @@
                 Slog.d(TAG, "Not verifying instant app install for app links: " + pkgName);
             }
         }
+        final PackageFreezer freezer =
+                freezePackageForInstall(pkgName, installFlags, "installPackageLI");
+        boolean shouldCloseFreezerBeforeReturn = true;
+        try {
+            final PackageParser.Package existingPackage;
+            String renamedPackage = null;
+            boolean clearCodeCache = false;
+            boolean sysPkg = false;
+            String targetVolumeUuid = volumeUuid;
+            int targetScanFlags = scanFlags;
+            int targetParseFlags = parseFlags;
 
-        try (PackageFreezer freezer = freezePackageForInstall(pkgName, installFlags,
-                "installPackageLI")) {
             if (replace) {
+                targetVolumeUuid = null;
                 if (pkg.applicationInfo.isStaticSharedLibrary()) {
                     // Static libs have a synthetic package name containing the version
                     // and cannot be updated as an update would get a new package name,
                     // unless this is the exact same version code which is useful for
                     // development.
                     PackageParser.Package existingPkg = mPackages.get(pkg.packageName);
-                    if (existingPkg != null &&
-                            existingPkg.getLongVersionCode() != pkg.getLongVersionCode()) {
-                        res.setError(INSTALL_FAILED_DUPLICATE_PACKAGE, "Packages declaring "
-                                + "static-shared libs cannot be updated");
-                        return;
+                    if (existingPkg != null
+                            && existingPkg.getLongVersionCode() != pkg.getLongVersionCode()) {
+                        throw new PrepareFailure(INSTALL_FAILED_DUPLICATE_PACKAGE,
+                                "Packages declaring "
+                                        + "static-shared libs cannot be updated");
                     }
                 }
-                replacePackageLIF(pkg, parseFlags, scanFlags, args.user,
-                        installerPackageName, res, args.installReason);
-            } else {
-                installNewPackageLIF(pkg, parseFlags, scanFlags,
-                        args.user, installerPackageName, volumeUuid, res, args.installReason);
-            }
-        }
 
-        // Prepare the application profiles for the new code paths.
-        // This needs to be done before invoking dexopt so that any install-time profile
-        // can be used for optimizations.
-        mArtManagerService.prepareAppProfiles(pkg, resolveUserIds(args.user.getIdentifier()));
+                final boolean isInstantApp = (scanFlags & SCAN_AS_INSTANT_APP) != 0;
 
-        // Check whether we need to dexopt the app.
-        //
-        // NOTE: it is IMPORTANT to call dexopt:
-        //   - after doRename which will sync the package data from PackageParser.Package and its
-        //     corresponding ApplicationInfo.
-        //   - after installNewPackageLIF or replacePackageLIF which will update result with the
-        //     uid of the application (pkg.applicationInfo.uid).
-        //     This update happens in place!
-        //
-        // We only need to dexopt if the package meets ALL of the following conditions:
-        //   1) it is not forward locked.
-        //   2) it is not on on an external ASEC container.
-        //   3) it is not an instant app or if it is then dexopt is enabled via gservices.
-        //   4) it is not debuggable.
-        //
-        // Note that we do not dexopt instant apps by default. dexopt can take some time to
-        // complete, so we skip this step during installation. Instead, we'll take extra time
-        // the first time the instant app starts. It's preferred to do it this way to provide
-        // continuous progress to the useur instead of mysteriously blocking somewhere in the
-        // middle of running an instant app. The default behaviour can be overridden
-        // via gservices.
-        final boolean performDexopt = (res.returnCode == PackageManager.INSTALL_SUCCEEDED)
-                && !forwardLocked
-                && !pkg.applicationInfo.isExternalAsec()
-                && (!instantApp || Global.getInt(mContext.getContentResolver(),
-                Global.INSTANT_APP_DEXOPT_ENABLED, 0) != 0)
-                && ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) == 0);
+                final PackageParser.Package oldPackage;
+                final PackageSetting ps;
+                final String pkgName11 = pkg.packageName;
+                final int[] allUsers;
+                final int[] installedUsers;
 
-        if (performDexopt) {
-            Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt");
-            // Do not run PackageDexOptimizer through the local performDexOpt
-            // method because `pkg` may not be in `mPackages` yet.
-            //
-            // Also, don't fail application installs if the dexopt step fails.
-            DexoptOptions dexoptOptions = new DexoptOptions(pkg.packageName,
-                    REASON_INSTALL,
-                    DexoptOptions.DEXOPT_BOOT_COMPLETE |
-                    DexoptOptions.DEXOPT_INSTALL_WITH_DEX_METADATA_FILE);
-            mPackageDexOptimizer.performDexOpt(pkg, pkg.usesLibraryFiles,
-                    null /* instructionSets */,
-                    getOrCreateCompilerPackageStats(pkg),
-                    mDexManager.getPackageUseInfoOrDefault(pkg.packageName),
-                    dexoptOptions);
-            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
-        }
+                synchronized (mPackages) {
+                    oldPackage = mPackages.get(pkgName11);
+                    existingPackage = oldPackage;
+                    if (DEBUG_INSTALL) {
+                        Slog.d(TAG,
+                                "replacePackageLI: new=" + pkg + ", old=" + oldPackage);
+                    }
 
-        // Notify BackgroundDexOptService that the package has been changed.
-        // If this is an update of a package which used to fail to compile,
-        // BackgroundDexOptService will remove it from its blacklist.
-        // TODO: Layering violation
-        BackgroundDexOptService.notifyPackageChanged(pkg.packageName);
+                    // don't allow upgrade to target a release SDK from a pre-release SDK
+                    final boolean oldTargetsPreRelease = oldPackage.applicationInfo.targetSdkVersion
+                            == Build.VERSION_CODES.CUR_DEVELOPMENT;
+                    final boolean newTargetsPreRelease = pkg.applicationInfo.targetSdkVersion
+                            == Build.VERSION_CODES.CUR_DEVELOPMENT;
+                    if (oldTargetsPreRelease
+                            && !newTargetsPreRelease
+                            && ((parseFlags & PackageParser.PARSE_FORCE_SDK) == 0)) {
+                        Slog.w(TAG, "Can't install package targeting released sdk");
+                        throw new PrepareFailure(
+                                PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE);
+                    }
 
-        synchronized (mPackages) {
-            final PackageSetting ps = mSettings.mPackages.get(pkgName);
-            if (ps != null) {
-                res.newUsers = ps.queryInstalledUsers(sUserManager.getUserIds(), true);
-                ps.setUpdateAvailable(false /*updateAvailable*/);
-            }
+                    ps = mSettings.mPackages.get(pkgName11);
 
-            final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
-            for (int i = 0; i < childCount; i++) {
-                PackageParser.Package childPkg = pkg.childPackages.get(i);
-                PackageInstalledInfo childRes = res.addedChildPackages.get(childPkg.packageName);
-                PackageSetting childPs = mSettings.getPackageLPr(childPkg.packageName);
-                if (childPs != null) {
-                    childRes.newUsers = childPs.queryInstalledUsers(
-                            sUserManager.getUserIds(), true);
+                    // verify signatures are valid
+                    final KeySetManagerService ksms = mSettings.mKeySetManagerService;
+                    if (ksms.shouldCheckUpgradeKeySetLocked(ps, scanFlags)) {
+                        if (!ksms.checkUpgradeKeySetLocked(ps, pkg)) {
+                            throw new PrepareFailure(INSTALL_FAILED_UPDATE_INCOMPATIBLE,
+                                    "New package not signed by keys specified by upgrade-keysets: "
+                                            + pkgName11);
+                        }
+                    } else {
+                        // default to original signature matching
+                        if (!pkg.mSigningDetails.checkCapability(oldPackage.mSigningDetails,
+                                SigningDetails.CertCapabilities.INSTALLED_DATA)
+                                && !oldPackage.mSigningDetails.checkCapability(
+                                pkg.mSigningDetails,
+                                SigningDetails.CertCapabilities.ROLLBACK)) {
+                            throw new PrepareFailure(INSTALL_FAILED_UPDATE_INCOMPATIBLE,
+                                    "New package has a different signature: " + pkgName11);
+                        }
+                    }
+
+                    // don't allow a system upgrade unless the upgrade hash matches
+                    if (oldPackage.restrictUpdateHash != null && oldPackage.isSystem()) {
+                        final byte[] digestBytes;
+                        try {
+                            final MessageDigest digest = MessageDigest.getInstance("SHA-512");
+                            updateDigest(digest, new File(pkg.baseCodePath));
+                            if (!ArrayUtils.isEmpty(pkg.splitCodePaths)) {
+                                for (String path : pkg.splitCodePaths) {
+                                    updateDigest(digest, new File(path));
+                                }
+                            }
+                            digestBytes = digest.digest();
+                        } catch (NoSuchAlgorithmException | IOException e) {
+                            throw new PrepareFailure(INSTALL_FAILED_INVALID_APK,
+                                    "Could not compute hash: " + pkgName11);
+                        }
+                        if (!Arrays.equals(oldPackage.restrictUpdateHash, digestBytes)) {
+                            throw new PrepareFailure(INSTALL_FAILED_INVALID_APK,
+                                    "New package fails restrict-update check: " + pkgName11);
+                        }
+                        // retain upgrade restriction
+                        pkg.restrictUpdateHash = oldPackage.restrictUpdateHash;
+                    }
+
+                    // Check for shared user id changes
+                    String invalidPackageName =
+                            getParentOrChildPackageChangedSharedUser(oldPackage, pkg);
+                    if (invalidPackageName != null) {
+                        throw new PrepareFailure(INSTALL_FAILED_SHARED_USER_INCOMPATIBLE,
+                                "Package " + invalidPackageName + " tried to change user "
+                                        + oldPackage.mSharedUserId);
+                    }
+
+                    // check if the new package supports all of the abis which the old package
+                    // supports
+                    boolean oldPkgSupportMultiArch =
+                            oldPackage.applicationInfo.secondaryCpuAbi != null;
+                    boolean newPkgSupportMultiArch = pkg.applicationInfo.secondaryCpuAbi != null;
+                    if (isSystemApp(oldPackage) && oldPkgSupportMultiArch
+                            && !newPkgSupportMultiArch) {
+                        throw new PrepareFailure(INSTALL_FAILED_UPDATE_INCOMPATIBLE,
+                                "Update to package " + pkgName11 + " doesn't support multi arch");
+                    }
+
+                    // In case of rollback, remember per-user/profile install state
+                    allUsers = sUserManager.getUserIds();
+                    installedUsers = ps.queryInstalledUsers(allUsers, true);
+
+
+                    // don't allow an upgrade from full to ephemeral
+                    if (isInstantApp) {
+                        if (args.user == null || args.user.getIdentifier() == UserHandle.USER_ALL) {
+                            for (int currentUser : allUsers) {
+                                if (!ps.getInstantApp(currentUser)) {
+                                    // can't downgrade from full to instant
+                                    Slog.w(TAG,
+                                            "Can't replace full app with instant app: " + pkgName11
+                                                    + " for user: " + currentUser);
+                                    throw new PrepareFailure(
+                                            PackageManager.INSTALL_FAILED_INSTANT_APP_INVALID);
+                                }
+                            }
+                        } else if (!ps.getInstantApp(args.user.getIdentifier())) {
+                            // can't downgrade from full to instant
+                            Slog.w(TAG, "Can't replace full app with instant app: " + pkgName11
+                                    + " for user: " + args.user.getIdentifier());
+                            throw new PrepareFailure(
+                                    PackageManager.INSTALL_FAILED_INSTANT_APP_INVALID);
+                        }
+                    }
+                }
+
+                // Update what is removed
+                res.removedInfo = new PackageRemovedInfo(this);
+                res.removedInfo.uid = oldPackage.applicationInfo.uid;
+                res.removedInfo.removedPackage = oldPackage.packageName;
+                res.removedInfo.installerPackageName = ps.installerPackageName;
+                res.removedInfo.isStaticSharedLib = pkg.staticSharedLibName != null;
+                res.removedInfo.isUpdate = true;
+                res.removedInfo.origUsers = installedUsers;
+                res.removedInfo.installReasons = new SparseArray<>(installedUsers.length);
+                for (int i = 0; i < installedUsers.length; i++) {
+                    final int userId = installedUsers[i];
+                    res.removedInfo.installReasons.put(userId, ps.getInstallReason(userId));
+                }
+
+                final int childCount = (oldPackage.childPackages != null)
+                        ? oldPackage.childPackages.size() : 0;
+                for (int i = 0; i < childCount; i++) {
+                    boolean childPackageUpdated = false;
+                    PackageParser.Package childPkg = oldPackage.childPackages.get(i);
+                    final PackageSetting childPs = mSettings.getPackageLPr(childPkg.packageName);
+                    if (res.addedChildPackages != null) {
+                        PackageInstalledInfo childRes = res.addedChildPackages.get(
+                                childPkg.packageName);
+                        if (childRes != null) {
+                            childRes.removedInfo.uid = childPkg.applicationInfo.uid;
+                            childRes.removedInfo.removedPackage = childPkg.packageName;
+                            if (childPs != null) {
+                                childRes.removedInfo.installerPackageName =
+                                        childPs.installerPackageName;
+                            }
+                            childRes.removedInfo.isUpdate = true;
+                            childRes.removedInfo.installReasons = res.removedInfo.installReasons;
+                            childPackageUpdated = true;
+                        }
+                    }
+                    if (!childPackageUpdated) {
+                        PackageRemovedInfo childRemovedRes = new PackageRemovedInfo(this);
+                        childRemovedRes.removedPackage = childPkg.packageName;
+                        if (childPs != null) {
+                            childRemovedRes.installerPackageName = childPs.installerPackageName;
+                        }
+                        childRemovedRes.isUpdate = false;
+                        childRemovedRes.dataRemoved = true;
+                        synchronized (mPackages) {
+                            if (childPs != null) {
+                                childRemovedRes.origUsers = childPs.queryInstalledUsers(allUsers,
+                                        true);
+                            }
+                        }
+                        if (res.removedInfo.removedChildPackages == null) {
+                            res.removedInfo.removedChildPackages = new ArrayMap<>();
+                        }
+                        res.removedInfo.removedChildPackages.put(childPkg.packageName,
+                                childRemovedRes);
+                    }
+                }
+
+                sysPkg = (isSystemApp(oldPackage));
+                if (sysPkg) {
+                    // Set the system/privileged/oem/vendor/product flags as needed
+                    final boolean privileged = isPrivilegedApp(oldPackage);
+                    final boolean oem = isOemApp(oldPackage);
+                    final boolean vendor = isVendorApp(oldPackage);
+                    final boolean product = isProductApp(oldPackage);
+                    final @ParseFlags int systemParseFlags = parseFlags;
+                    final @ScanFlags int systemScanFlags = scanFlags
+                            | SCAN_AS_SYSTEM
+                            | (privileged ? SCAN_AS_PRIVILEGED : 0)
+                            | (oem ? SCAN_AS_OEM : 0)
+                            | (vendor ? SCAN_AS_VENDOR : 0)
+                            | (product ? SCAN_AS_PRODUCT : 0);
+
+                    if (DEBUG_INSTALL) {
+                        Slog.d(TAG, "replaceSystemPackageLI: new=" + pkg
+                                + ", old=" + oldPackage);
+                    }
+                    clearCodeCache = true;
+                    res.setReturnCode(PackageManager.INSTALL_SUCCEEDED);
+                    pkg.setApplicationInfoFlags(ApplicationInfo.FLAG_UPDATED_SYSTEM_APP,
+                            ApplicationInfo.FLAG_UPDATED_SYSTEM_APP);
+                    targetParseFlags = systemParseFlags;
+                    targetScanFlags = systemScanFlags;
+                } else { // non system replace
+                    replace = true;
+                    if (DEBUG_INSTALL) {
+                        Slog.d(TAG,
+                                "replaceNonSystemPackageLI: new=" + pkg + ", old="
+                                        + oldPackage);
+                    }
+
+                    String pkgName1 = oldPackage.packageName;
+                    boolean deletedPkg = true;
+                    boolean addedPkg = false;
+                    boolean updatedSettings = false;
+
+                    final long origUpdateTime = (pkg.mExtras != null)
+                            ? ((PackageSetting) pkg.mExtras).lastUpdateTime : 0;
+
+                }
+            } else { // new package install
+                replace = false;
+                existingPackage = null;
+                // Remember this for later, in case we need to rollback this install
+                String pkgName1 = pkg.packageName;
+
+                if (DEBUG_INSTALL) Slog.d(TAG, "installNewPackageLI: " + pkg);
+
+                // TODO(patb): MOVE TO RECONCILE
+                synchronized (mPackages) {
+                    renamedPackage = mSettings.getRenamedPackageLPr(pkgName1);
+                    if (renamedPackage != null) {
+                        // A package with the same name is already installed, though
+                        // it has been renamed to an older name.  The package we
+                        // are trying to install should be installed as an update to
+                        // the existing one, but that has not been requested, so bail.
+                        throw new PrepareFailure(INSTALL_FAILED_ALREADY_EXISTS,
+                                "Attempt to re-install " + pkgName1
+                                        + " without first uninstalling package running as "
+                                        + renamedPackage);
+                    }
+                    if (mPackages.containsKey(pkgName1)) {
+                        // Don't allow installation over an existing package with the same name.
+                        throw new PrepareFailure(INSTALL_FAILED_ALREADY_EXISTS,
+                                "Attempt to re-install " + pkgName1
+                                        + " without first uninstalling.");
+                    }
                 }
             }
-
-            if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
-                updateSequenceNumberLP(ps, res.newUsers);
-                updateInstantAppInstallerLocked(pkgName);
+            // we're passing the freezer back to be closed in a later phase of install
+            shouldCloseFreezerBeforeReturn = false;
+            return new PrepareResult(args.installReason, targetVolumeUuid, installerPackageName,
+                    args.user, replace, targetScanFlags, targetParseFlags, existingPackage, pkg,
+                    clearCodeCache, sysPkg, renamedPackage, freezer);
+        } finally {
+            if (shouldCloseFreezerBeforeReturn) {
+                freezer.close();
             }
         }
     }
@@ -16868,7 +17127,7 @@
             }
         }
 
-        removePackageLI(ps, (flags & PackageManager.DELETE_CHATTY) != 0);
+        removePackageLI(ps.name, (flags & PackageManager.DELETE_CHATTY) != 0);
 
         if ((flags & PackageManager.DELETE_KEEP_DATA) == 0) {
             final PackageParser.Package resolvedPkg;
@@ -21979,6 +22238,22 @@
         }
 
         @Override
+        public boolean isPlatformSigned(String packageName) {
+            PackageSetting packageSetting = mSettings.mPackages.get(packageName);
+            if (packageSetting == null) {
+                return false;
+            }
+            PackageParser.Package pkg = packageSetting.pkg;
+            if (pkg == null) {
+                // May happen if package in on a removable sd card
+                return false;
+            }
+            return pkg.mSigningDetails.hasAncestorOrSelf(mPlatformPackage.mSigningDetails)
+                    || mPlatformPackage.mSigningDetails.checkCapability(pkg.mSigningDetails,
+                    PackageParser.SigningDetails.CertCapabilities.PERMISSION);
+        }
+
+        @Override
         public boolean isDataRestoreSafe(byte[] restoringFromSigHash, String packageName) {
             SigningDetails sd = getSigningDetails(packageName);
             if (sd == null) {
@@ -22090,7 +22365,7 @@
         }
 
         @Override
-        public PackageParser.Package getDisabledPackage(String packageName) {
+        public PackageParser.Package getDisabledSystemPackage(String packageName) {
             synchronized (mPackages) {
                 final PackageSetting ps = mSettings.getDisabledSystemPkgLPr(packageName);
                 return (ps != null) ? ps.pkg : null;
@@ -22098,6 +22373,12 @@
         }
 
         @Override
+        public @Nullable String getDisabledSystemPackageName(@NonNull String packageName) {
+            PackageParser.Package pkg = getDisabledSystemPackage(packageName);
+            return pkg == null ? null : pkg.packageName;
+        }
+
+        @Override
         public String getKnownPackageName(int knownPackage, int userId) {
             switch(knownPackage) {
                 case PackageManagerInternal.PACKAGE_BROWSER:
@@ -22135,21 +22416,6 @@
         }
 
         @Override
-        public void setSmsAppPackagesProvider(PackagesProvider provider) {
-            mDefaultPermissionPolicy.setSmsAppPackagesProvider(provider);
-        }
-
-        @Override
-        public void setDialerAppPackagesProvider(PackagesProvider provider) {
-            mDefaultPermissionPolicy.setDialerAppPackagesProvider(provider);
-        }
-
-        @Override
-        public void setSimCallManagerPackagesProvider(PackagesProvider provider) {
-            mDefaultPermissionPolicy.setSimCallManagerPackagesProvider(provider);
-        }
-
-        @Override
         public void setUseOpenWifiAppPackagesProvider(PackagesProvider provider) {
             mDefaultPermissionPolicy.setUseOpenWifiAppPackagesProvider(provider);
         }
@@ -22160,22 +22426,10 @@
         }
 
         @Override
-        public void grantDefaultPermissionsToDefaultSmsApp(String packageName, int userId) {
-            mDefaultPermissionPolicy.grantDefaultPermissionsToDefaultSmsApp(packageName, userId);
-        }
-
-        @Override
-        public void grantDefaultPermissionsToDefaultDialerApp(String packageName, int userId) {
+        public void onDefaultDialerAppChanged(String packageName, int userId) {
             synchronized (mPackages) {
                 mSettings.setDefaultDialerPackageNameLPw(packageName, userId);
             }
-            mDefaultPermissionPolicy.grantDefaultPermissionsToDefaultDialerApp(packageName, userId);
-        }
-
-        @Override
-        public void grantDefaultPermissionsToDefaultSimCallManager(String packageName, int userId) {
-            mDefaultPermissionPolicy.grantDefaultPermissionsToDefaultSimCallManager(
-                    packageName, userId);
         }
 
         @Override
diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java
index 727fb15..b850613 100644
--- a/services/core/java/com/android/server/pm/PackageSetting.java
+++ b/services/core/java/com/android/server/pm/PackageSetting.java
@@ -207,4 +207,13 @@
         writeUsersInfoToProto(proto, PackageProto.USERS);
         proto.end(packageToken);
     }
+
+    /** Updates all fields in the current setting from another. */
+    public void updateFrom(PackageSetting other) {
+        super.updateFrom(other);
+        appId = other.appId;
+        pkg = other.pkg;
+        sharedUserId = other.sharedUserId;
+        sharedUser = other.sharedUser;
+    }
 }
diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java
index 138594c..fd6aceb 100644
--- a/services/core/java/com/android/server/pm/PackageSettingBase.java
+++ b/services/core/java/com/android/server/pm/PackageSettingBase.java
@@ -26,7 +26,6 @@
 import android.content.pm.PackageParser;
 import android.content.pm.PackageUserState;
 import android.content.pm.Signature;
-import android.os.BaseBundle;
 import android.os.PersistableBundle;
 import android.service.pm.PackageProto;
 import android.util.ArraySet;
@@ -109,7 +108,7 @@
 
     // Whether this package is currently stopped, thus can not be
     // started until explicitly launched by the user.
-    private final SparseArray<PackageUserState> userState = new SparseArray<PackageUserState>();
+    private final SparseArray<PackageUserState> mUserState = new SparseArray<>();
 
     /**
      * Non-persisted value. During an "upgrade without restart", we need the set
@@ -118,7 +117,7 @@
      * restart, this field will be cleared since the classloader would be created
      * using the full set of code paths when the package's process is started.
      */
-    Set<String> oldCodePaths;
+    Set<String> mOldCodePaths;
 
     /** Package name of the app that installed this package */
     String installerPackageName;
@@ -223,7 +222,7 @@
     /**
      * Makes a shallow copy of the given package settings.
      *
-     * NOTE: For some fields [such as keySetData, signatures, userState, verificationInfo, etc...],
+     * NOTE: For some fields [such as keySetData, signatures, mUserState, verificationInfo, etc...],
      * the original object is copied and a new one is not created.
      */
     public void copyFrom(PackageSettingBase orig) {
@@ -244,7 +243,7 @@
         keySetData = orig.keySetData;
         lastUpdateTime = orig.lastUpdateTime;
         legacyNativeLibraryPathString = orig.legacyNativeLibraryPathString;
-        // Intentionally skip oldCodePaths; it's not relevant for copies
+        // Intentionally skip mOldCodePaths; it's not relevant for copies
         parentPackageName = orig.parentPackageName;
         primaryCpuAbiString = orig.primaryCpuAbiString;
         resourcePath = orig.resourcePath;
@@ -253,9 +252,9 @@
         signatures = orig.signatures;
         timeStamp = orig.timeStamp;
         uidError = orig.uidError;
-        userState.clear();
-        for (int i=0; i<orig.userState.size(); i++) {
-            userState.put(orig.userState.keyAt(i), orig.userState.valueAt(i));
+        mUserState.clear();
+        for (int i = 0; i < orig.mUserState.size(); i++) {
+            mUserState.put(orig.mUserState.keyAt(i), orig.mUserState.valueAt(i));
         }
         verificationInfo = orig.verificationInfo;
         versionCode = orig.versionCode;
@@ -271,16 +270,16 @@
     }
 
     private PackageUserState modifyUserState(int userId) {
-        PackageUserState state = userState.get(userId);
+        PackageUserState state = mUserState.get(userId);
         if (state == null) {
             state = new PackageUserState();
-            userState.put(userId, state);
+            mUserState.put(userId, state);
         }
         return state;
     }
 
     public PackageUserState readUserState(int userId) {
-        PackageUserState state = userState.get(userId);
+        PackageUserState state = mUserState.get(userId);
         if (state == null) {
             return DEFAULT_USER_STATE;
         }
@@ -330,7 +329,7 @@
     /** Only use for testing. Do NOT use in production code. */
     @VisibleForTesting
     SparseArray<PackageUserState> getUserState() {
-        return userState;
+        return mUserState;
     }
 
     boolean isAnyInstalled(int[] users) {
@@ -536,14 +535,14 @@
     }
 
     void removeUser(int userId) {
-        userState.delete(userId);
+        mUserState.delete(userId);
     }
 
     public int[] getNotInstalledUserIds() {
         int count = 0;
-        int userStateCount = userState.size();
+        int userStateCount = mUserState.size();
         for (int i = 0; i < userStateCount; i++) {
-            if (userState.valueAt(i).installed == false) {
+            if (!mUserState.valueAt(i).installed) {
                 count++;
             }
         }
@@ -551,8 +550,8 @@
         int[] excludedUserIds = new int[count];
         int idx = 0;
         for (int i = 0; i < userStateCount; i++) {
-            if (userState.valueAt(i).installed == false) {
-                excludedUserIds[idx++] = userState.keyAt(i);
+            if (!mUserState.valueAt(i).installed) {
+                excludedUserIds[idx++] = mUserState.keyAt(i);
             }
         }
         return excludedUserIds;
@@ -591,11 +590,11 @@
     }
 
     protected void writeUsersInfoToProto(ProtoOutputStream proto, long fieldId) {
-        int count = userState.size();
+        int count = mUserState.size();
         for (int i = 0; i < count; i++) {
             final long userToken = proto.start(fieldId);
-            final int userId = userState.keyAt(i);
-            final PackageUserState state = userState.valueAt(i);
+            final int userId = mUserState.keyAt(i);
+            final PackageUserState state = mUserState.valueAt(i);
             proto.write(PackageProto.UserInfoProto.ID, userId);
             final int installType;
             if (state.instantApp) {
@@ -630,4 +629,48 @@
         PackageUserState userState = readUserState(userId);
         return userState.harmfulAppWarning;
     }
+
+    protected PackageSettingBase updateFrom(PackageSettingBase other) {
+        super.copyFrom(other);
+        this.parentPackageName = other.parentPackageName;
+        this.childPackageNames = other.childPackageNames;
+        this.codePath = other.codePath;
+        this.codePathString = other.codePathString;
+        this.resourcePath = other.resourcePath;
+        this.resourcePathString = other.resourcePathString;
+        this.usesStaticLibraries = other.usesStaticLibraries;
+        this.usesStaticLibrariesVersions = other.usesStaticLibrariesVersions;
+        this.legacyNativeLibraryPathString = other.legacyNativeLibraryPathString;
+        this.primaryCpuAbiString = other.primaryCpuAbiString;
+        this.secondaryCpuAbiString = other.secondaryCpuAbiString;
+        this.cpuAbiOverrideString = other.cpuAbiOverrideString;
+        this.timeStamp = other.timeStamp;
+        this.firstInstallTime = other.firstInstallTime;
+        this.lastUpdateTime = other.lastUpdateTime;
+        this.versionCode = other.versionCode;
+        this.uidError = other.uidError;
+        this.signatures = other.signatures;
+        this.installPermissionsFixed = other.installPermissionsFixed;
+        this.keySetData = other.keySetData;
+        this.installerPackageName = other.installerPackageName;
+        this.isOrphaned = other.isOrphaned;
+        this.volumeUuid = other.volumeUuid;
+        this.categoryHint = other.categoryHint;
+        this.updateAvailable = other.updateAvailable;
+        this.verificationInfo = other.verificationInfo;
+
+        if (mOldCodePaths != null) {
+            if (other.mOldCodePaths != null) {
+                mOldCodePaths.clear();
+                mOldCodePaths.addAll(other.mOldCodePaths);
+            } else {
+                mOldCodePaths = null;
+            }
+        }
+        mUserState.clear();
+        for (int i = 0; i < other.mUserState.size(); i++) {
+            mUserState.put(other.mUserState.keyAt(i), other.mUserState.valueAt(i));
+        }
+        return this;
+    }
 }
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 6d242f4..5c88e06 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -539,16 +539,18 @@
             if((p.pkg != null) && (p.pkg.applicationInfo != null)) {
                 p.pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
             }
-            mDisabledSysPackages.put(name, p);
-
+            final PackageSetting disabled;
             if (replaced) {
                 // a little trick...  when we install the new package, we don't
                 // want to modify the existing PackageSetting for the built-in
-                // version.  so at this point we need a new PackageSetting that
-                // is okay to muck with.
-                PackageSetting newp = new PackageSetting(p);
-                replacePackageLPw(name, newp);
+                // version.  so at this point we make a copy to place into the
+                // disabled set.
+                disabled = new PackageSetting(p);
+            } else {
+                disabled = p;
             }
+            mDisabledSysPackages.put(name, disabled);
+
             return true;
         }
         return false;
@@ -1105,19 +1107,6 @@
         mInstallerPackages.remove(packageName);
     }
 
-    private void replacePackageLPw(String name, PackageSetting newp) {
-        final PackageSetting p = mPackages.get(name);
-        if (p != null) {
-            if (p.sharedUser != null) {
-                p.sharedUser.removePackage(p);
-                p.sharedUser.addPackage(newp);
-            } else {
-                replaceUserIdLPw(p.appId, newp);
-            }
-        }
-        mPackages.put(name, newp);
-    }
-
     private boolean addUserIdLPw(int uid, Object obj, Object name) {
         if (uid > Process.LAST_APPLICATION_UID) {
             return false;
diff --git a/services/core/java/com/android/server/pm/SharedUserSetting.java b/services/core/java/com/android/server/pm/SharedUserSetting.java
index c94d209..1a8b2af 100644
--- a/services/core/java/com/android/server/pm/SharedUserSetting.java
+++ b/services/core/java/com/android/server/pm/SharedUserSetting.java
@@ -24,7 +24,6 @@
 import android.util.proto.ProtoOutputStream;
 
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.List;
 
 /**
@@ -69,24 +68,26 @@
         proto.end(token);
     }
 
-    void removePackage(PackageSetting packageSetting) {
-        if (packages.remove(packageSetting)) {
-            // recalculate the pkgFlags for this shared user if needed
-            if ((this.pkgFlags & packageSetting.pkgFlags) != 0) {
-                int aggregatedFlags = uidFlags;
-                for (PackageSetting ps : packages) {
-                    aggregatedFlags |= ps.pkgFlags;
-                }
-                setFlags(aggregatedFlags);
-            }
-            if ((this.pkgPrivateFlags & packageSetting.pkgPrivateFlags) != 0) {
-                int aggregatedPrivateFlags = uidPrivateFlags;
-                for (PackageSetting ps : packages) {
-                    aggregatedPrivateFlags |= ps.pkgPrivateFlags;
-                }
-                setPrivateFlags(aggregatedPrivateFlags);
-            }
+    boolean removePackage(PackageSetting packageSetting) {
+        if (!packages.remove(packageSetting)) {
+            return false;
         }
+        // recalculate the pkgFlags for this shared user if needed
+        if ((this.pkgFlags & packageSetting.pkgFlags) != 0) {
+            int aggregatedFlags = uidFlags;
+            for (PackageSetting ps : packages) {
+                aggregatedFlags |= ps.pkgFlags;
+            }
+            setFlags(aggregatedFlags);
+        }
+        if ((this.pkgPrivateFlags & packageSetting.pkgPrivateFlags) != 0) {
+            int aggregatedPrivateFlags = uidPrivateFlags;
+            for (PackageSetting ps : packages) {
+                aggregatedPrivateFlags |= ps.pkgPrivateFlags;
+            }
+            setPrivateFlags(aggregatedPrivateFlags);
+        }
+        return true;
     }
 
     void addPackage(PackageSetting packageSetting) {
@@ -143,4 +144,16 @@
         }
     }
 
+    /** Updates all fields in this shared user setting from another. */
+    public SharedUserSetting updateFrom(SharedUserSetting sharedUser) {
+        copyFrom(sharedUser);
+        this.userId = sharedUser.userId;
+        this.uidFlags = sharedUser.uidFlags;
+        this.uidPrivateFlags = sharedUser.uidPrivateFlags;
+        this.seInfoTargetSdkVersion = sharedUser.seInfoTargetSdkVersion;
+        this.packages.clear();
+        this.packages.addAll(sharedUser.packages);
+        this.signaturesChanged = sharedUser.signaturesChanged;
+        return this;
+    }
 }
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 846c7b7..d9eb7e8 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -23,12 +23,13 @@
 import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.app.DownloadManager;
+import android.app.SearchManager;
 import android.app.admin.DevicePolicyManager;
 import android.companion.CompanionDeviceManager;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageList;
+import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManagerInternal;
 import android.content.pm.PackageManagerInternal.PackagesProvider;
@@ -53,6 +54,7 @@
 import android.provider.MediaStore;
 import android.provider.Telephony.Sms.Intents;
 import android.security.Credentials;
+import android.speech.RecognitionService;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
 import android.util.ArrayMap;
@@ -61,6 +63,7 @@
 import android.util.Slog;
 import android.util.Xml;
 
+import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.XmlUtils;
 import com.android.server.LocalServices;
 
@@ -73,6 +76,7 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
@@ -94,10 +98,15 @@
     private static final String TAG = "DefaultPermGrantPolicy"; // must be <= 23 chars
     private static final boolean DEBUG = false;
 
-    private static final int DEFAULT_FLAGS =
+    @PackageManager.ResolveInfoFlags
+    private static final int DEFAULT_INTENT_QUERY_FLAGS =
             PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
                     | PackageManager.MATCH_UNINSTALLED_PACKAGES;
 
+    @PackageManager.PackageInfoFlags
+    private static final int DEFAULT_PACKAGE_INFO_QUERY_FLAGS =
+            PackageManager.MATCH_UNINSTALLED_PACKAGES | PackageManager.GET_PERMISSIONS;
+
     private static final String AUDIO_MIME_TYPE = "audio/mpeg";
 
     private static final String TAG_EXCEPTIONS = "exceptions";
@@ -108,6 +117,8 @@
     private static final String ATTR_FIXED = "fixed";
 
     private static final Set<String> PHONE_PERMISSIONS = new ArraySet<>();
+
+
     static {
         PHONE_PERMISSIONS.add(Manifest.permission.READ_PHONE_STATE);
         PHONE_PERMISSIONS.add(Manifest.permission.CALL_PHONE);
@@ -219,7 +230,7 @@
     private final DefaultPermissionGrantedCallback mPermissionGrantedCallback;
     public interface DefaultPermissionGrantedCallback {
         /** Callback when permissions have been granted */
-        public void onDefaultRuntimePermissionsGranted(int userId);
+        void onDefaultRuntimePermissionsGranted(int userId);
     }
 
     public DefaultPermissionGrantPolicy(Context context, Looper looper,
@@ -291,9 +302,9 @@
         grantDefaultPermissionExceptions(userId);
     }
 
-    private void grantRuntimePermissionsForPackage(int userId, PackageParser.Package pkg) {
+    private void grantRuntimePermissionsForSystemPackage(int userId, PackageInfo pkg) {
         Set<String> permissions = new ArraySet<>();
-        for (String permission :  pkg.requestedPermissions) {
+        for (String permission : pkg.requestedPermissions) {
             final BasePermission bp = mPermissionManager.getPermission(permission);
             if (bp == null) {
                 continue;
@@ -307,36 +318,71 @@
         }
     }
 
-    private void grantAllRuntimePermissions(int userId) {
-        Log.i(TAG, "Granting all runtime permissions for user " + userId);
-        final PackageList packageList = mServiceInternal.getPackageList();
-        for (String packageName : packageList.getPackageNames()) {
-            final PackageParser.Package pkg = mServiceInternal.getPackage(packageName);
-            if (pkg == null) {
-                continue;
-            }
-            grantRuntimePermissionsForPackage(userId, pkg);
-        }
-    }
-
     public void scheduleReadDefaultPermissionExceptions() {
         mHandler.sendEmptyMessage(MSG_READ_DEFAULT_PERMISSION_EXCEPTIONS);
     }
 
     private void grantPermissionsToSysComponentsAndPrivApps(int userId) {
         Log.i(TAG, "Granting permissions to platform components for user " + userId);
-        final PackageList packageList = mServiceInternal.getPackageList();
-        for (String packageName : packageList.getPackageNames()) {
-            final PackageParser.Package pkg = mServiceInternal.getPackage(packageName);
+        List<PackageInfo> packages = mContext.getPackageManager().getInstalledPackagesAsUser(
+                DEFAULT_PACKAGE_INFO_QUERY_FLAGS, UserHandle.USER_SYSTEM);
+        for (PackageInfo pkg : packages) {
             if (pkg == null) {
                 continue;
             }
             if (!isSysComponentOrPersistentPlatformSignedPrivApp(pkg)
                     || !doesPackageSupportRuntimePermissions(pkg)
-                    || pkg.requestedPermissions.isEmpty()) {
+                    || ArrayUtils.isEmpty(pkg.requestedPermissions)) {
                 continue;
             }
-            grantRuntimePermissionsForPackage(userId, pkg);
+            grantRuntimePermissionsForSystemPackage(userId, pkg);
+        }
+    }
+
+    @SafeVarargs
+    private final void grantIgnoringSystemPackage(String packageName, int userId,
+            Set<String>... permissionGroups) {
+        grantPermissionsToSystemPackage(packageName, userId, false, true, permissionGroups);
+    }
+
+    @SafeVarargs
+    private final void grantSystemFixedPermissionsToSystemPackage(String packageName, int userId,
+            Set<String>... permissionGroups) {
+        grantPermissionsToSystemPackage(packageName, userId, true, false, permissionGroups);
+    }
+
+    @SafeVarargs
+    private final void grantPermissionsToSystemPackage(
+            String packageName, int userId, Set<String>... permissionGroups) {
+        grantPermissionsToSystemPackage(packageName, userId, false, false, permissionGroups);
+    }
+
+    @SafeVarargs
+    private final void grantPermissionsToSystemPackage(String packageName, int userId,
+            boolean systemFixed, boolean ignoreSystemPackage, Set<String>... permissionGroups) {
+        if (!ignoreSystemPackage && !isSystemPackage(packageName)) {
+            return;
+        }
+        grantRuntimePermissionsToPackage(getSystemPackageInfo(packageName),
+                userId, systemFixed, ignoreSystemPackage, permissionGroups);
+    }
+
+    @SafeVarargs
+    private final void grantRuntimePermissionsToPackage(String packageName, int userId,
+            boolean systemFixed, boolean ignoreSystemPackage, Set<String>... permissionGroups) {
+        grantRuntimePermissionsToPackage(getPackageInfo(packageName),
+                userId, systemFixed, ignoreSystemPackage, permissionGroups);
+    }
+
+    @SafeVarargs
+    private final void grantRuntimePermissionsToPackage(PackageInfo packageName, int userId,
+            boolean systemFixed, boolean ignoreSystemPackage, Set<String>... permissionGroups) {
+        if (packageName == null) return;
+        if (doesPackageSupportRuntimePermissions(packageName)) {
+            for (Set<String> permissionGroup : permissionGroups) {
+                grantRuntimePermissions(packageName, permissionGroup, systemFixed,
+                        ignoreSystemPackage, userId);
+            }
         }
     }
 
@@ -379,594 +425,373 @@
                 syncAdapterPackagesProvider.getPackages(CalendarContract.AUTHORITY, userId) : null;
 
         // Installer
-        final String installerPackageName = mServiceInternal.getKnownPackageName(
-                PackageManagerInternal.PACKAGE_INSTALLER, userId);
-        PackageParser.Package installerPackage = getSystemPackage(installerPackageName);
-        if (installerPackage != null
-                && doesPackageSupportRuntimePermissions(installerPackage)) {
-            grantRuntimePermissions(installerPackage, STORAGE_PERMISSIONS, true, userId);
-        }
+        grantSystemFixedPermissionsToSystemPackage(
+                getKnownPackage(PackageManagerInternal.PACKAGE_INSTALLER, userId),
+                userId, STORAGE_PERMISSIONS);
 
         // Verifier
-        final String verifierPackageName = mServiceInternal.getKnownPackageName(
-                PackageManagerInternal.PACKAGE_VERIFIER, userId);
-        PackageParser.Package verifierPackage = getSystemPackage(verifierPackageName);
-        if (verifierPackage != null
-                && doesPackageSupportRuntimePermissions(verifierPackage)) {
-            grantRuntimePermissions(verifierPackage, STORAGE_PERMISSIONS, true, userId);
-            grantRuntimePermissions(verifierPackage, PHONE_PERMISSIONS, false, userId);
-            grantRuntimePermissions(verifierPackage, SMS_PERMISSIONS, false, userId);
-        }
+        final String verifier = getKnownPackage(PackageManagerInternal.PACKAGE_VERIFIER, userId);
+        grantSystemFixedPermissionsToSystemPackage(verifier, userId, STORAGE_PERMISSIONS);
+        grantPermissionsToSystemPackage(verifier, userId, PHONE_PERMISSIONS, SMS_PERMISSIONS);
 
         // SetupWizard
-        final String setupWizardPackageName = mServiceInternal.getKnownPackageName(
-                PackageManagerInternal.PACKAGE_SETUP_WIZARD, userId);
-        PackageParser.Package setupPackage = getSystemPackage(setupWizardPackageName);
-        if (setupPackage != null
-                && doesPackageSupportRuntimePermissions(setupPackage)) {
-            grantRuntimePermissions(setupPackage, PHONE_PERMISSIONS, userId);
-            grantRuntimePermissions(setupPackage, CONTACTS_PERMISSIONS, userId);
-            grantRuntimePermissions(setupPackage, LOCATION_PERMISSIONS, userId);
-            grantRuntimePermissions(setupPackage, CAMERA_PERMISSIONS, userId);
-        }
+        grantPermissionsToSystemPackage(
+                getKnownPackage(PackageManagerInternal.PACKAGE_SETUP_WIZARD, userId), userId,
+                PHONE_PERMISSIONS, CONTACTS_PERMISSIONS, LOCATION_PERMISSIONS, CAMERA_PERMISSIONS);
 
         // Camera
-        Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
-        PackageParser.Package cameraPackage = getDefaultSystemHandlerActivityPackage(
-                cameraIntent, userId);
-        if (cameraPackage != null
-                && doesPackageSupportRuntimePermissions(cameraPackage)) {
-            grantRuntimePermissions(cameraPackage, CAMERA_PERMISSIONS, userId);
-            grantRuntimePermissions(cameraPackage, MICROPHONE_PERMISSIONS, userId);
-            grantRuntimePermissions(cameraPackage, STORAGE_PERMISSIONS, userId);
-        }
+        grantPermissionsToSystemPackage(
+                getDefaultSystemHandlerActivityPackage(MediaStore.ACTION_IMAGE_CAPTURE, userId),
+                userId, CAMERA_PERMISSIONS, MICROPHONE_PERMISSIONS, STORAGE_PERMISSIONS);
 
         // Media provider
-        PackageParser.Package mediaStorePackage = getDefaultProviderAuthorityPackage(
-                MediaStore.AUTHORITY, userId);
-        if (mediaStorePackage != null) {
-            grantRuntimePermissions(mediaStorePackage, STORAGE_PERMISSIONS, true, userId);
-            grantRuntimePermissions(mediaStorePackage, MEDIA_AURAL_PERMISSIONS, true, userId);
-            grantRuntimePermissions(mediaStorePackage, MEDIA_VISUAL_PERMISSIONS, true, userId);
-            grantRuntimePermissions(mediaStorePackage, PHONE_PERMISSIONS, true, userId);
-        }
+        grantSystemFixedPermissionsToSystemPackage(
+                getDefaultProviderAuthorityPackage(MediaStore.AUTHORITY, userId), userId,
+                STORAGE_PERMISSIONS, MEDIA_AURAL_PERMISSIONS, MEDIA_VISUAL_PERMISSIONS,
+                PHONE_PERMISSIONS);
 
         // Downloads provider
-        PackageParser.Package downloadsPackage = getDefaultProviderAuthorityPackage(
-                "downloads", userId);
-        if (downloadsPackage != null) {
-            grantRuntimePermissions(downloadsPackage, STORAGE_PERMISSIONS, true, userId);
-        }
+        grantSystemFixedPermissionsToSystemPackage(
+                getDefaultProviderAuthorityPackage("downloads", userId), userId,
+                STORAGE_PERMISSIONS);
 
         // Downloads UI
-        Intent downloadsUiIntent = new Intent(DownloadManager.ACTION_VIEW_DOWNLOADS);
-        PackageParser.Package downloadsUiPackage = getDefaultSystemHandlerActivityPackage(
-                downloadsUiIntent, userId);
-        if (downloadsUiPackage != null
-                && doesPackageSupportRuntimePermissions(downloadsUiPackage)) {
-            grantRuntimePermissions(downloadsUiPackage, STORAGE_PERMISSIONS, true, userId);
-        }
+        grantSystemFixedPermissionsToSystemPackage(
+                getDefaultSystemHandlerActivityPackage(
+                        DownloadManager.ACTION_VIEW_DOWNLOADS, userId),
+                userId, STORAGE_PERMISSIONS);
 
         // Storage provider
-        PackageParser.Package storagePackage = getDefaultProviderAuthorityPackage(
-                "com.android.externalstorage.documents", userId);
-        if (storagePackage != null) {
-            grantRuntimePermissions(storagePackage, STORAGE_PERMISSIONS, true, userId);
-        }
+        grantSystemFixedPermissionsToSystemPackage(
+                getDefaultProviderAuthorityPackage("com.android.externalstorage.documents", userId),
+                userId, STORAGE_PERMISSIONS);
 
         // CertInstaller
-        Intent certInstallerIntent = new Intent(Credentials.INSTALL_ACTION);
-        PackageParser.Package certInstallerPackage = getDefaultSystemHandlerActivityPackage(
-                certInstallerIntent, userId);
-        if (certInstallerPackage != null
-                && doesPackageSupportRuntimePermissions(certInstallerPackage)) {
-            grantRuntimePermissions(certInstallerPackage, STORAGE_PERMISSIONS, true, userId);
-        }
+        grantSystemFixedPermissionsToSystemPackage(
+                getDefaultSystemHandlerActivityPackage(Credentials.INSTALL_ACTION, userId), userId,
+                STORAGE_PERMISSIONS);
 
         // Dialer
         if (dialerAppPackageNames == null) {
-            Intent dialerIntent = new Intent(Intent.ACTION_DIAL);
-            PackageParser.Package dialerPackage = getDefaultSystemHandlerActivityPackage(
-                    dialerIntent, userId);
-            if (dialerPackage != null) {
-                grantDefaultPermissionsToDefaultSystemDialerApp(dialerPackage, userId);
-            }
+            String dialerPackage =
+                    getDefaultSystemHandlerActivityPackage(Intent.ACTION_DIAL, userId);
+            grantDefaultPermissionsToDefaultSystemDialerApp(dialerPackage, userId);
         } else {
             for (String dialerAppPackageName : dialerAppPackageNames) {
-                PackageParser.Package dialerPackage = getSystemPackage(dialerAppPackageName);
-                if (dialerPackage != null) {
-                    grantDefaultPermissionsToDefaultSystemDialerApp(dialerPackage, userId);
-                }
+                grantDefaultPermissionsToDefaultSystemDialerApp(dialerAppPackageName, userId);
             }
         }
 
         // Sim call manager
         if (simCallManagerPackageNames != null) {
             for (String simCallManagerPackageName : simCallManagerPackageNames) {
-                PackageParser.Package simCallManagerPackage =
-                        getSystemPackage(simCallManagerPackageName);
-                if (simCallManagerPackage != null) {
-                    grantDefaultPermissionsToDefaultSimCallManager(simCallManagerPackage,
-                            userId);
-                }
+                grantDefaultPermissionsToDefaultSystemSimCallManager(
+                        simCallManagerPackageName, userId);
             }
         }
 
         // Use Open Wifi
         if (useOpenWifiAppPackageNames != null) {
             for (String useOpenWifiPackageName : useOpenWifiAppPackageNames) {
-                PackageParser.Package useOpenWifiPackage =
-                        getSystemPackage(useOpenWifiPackageName);
-                if (useOpenWifiPackage != null) {
-                    grantDefaultPermissionsToDefaultSystemUseOpenWifiApp(useOpenWifiPackage,
-                            userId);
-                }
+                grantDefaultPermissionsToDefaultSystemUseOpenWifiApp(
+                        useOpenWifiPackageName, userId);
             }
         }
 
         // SMS
         if (smsAppPackageNames == null) {
-            Intent smsIntent = new Intent(Intent.ACTION_MAIN);
-            smsIntent.addCategory(Intent.CATEGORY_APP_MESSAGING);
-            PackageParser.Package smsPackage = getDefaultSystemHandlerActivityPackage(
-                    smsIntent, userId);
-            if (smsPackage != null) {
-               grantDefaultPermissionsToDefaultSystemSmsApp(smsPackage, userId);
-            }
+            String smsPackage = getDefaultSystemHandlerActivityPackageForCategory(
+                    Intent.CATEGORY_APP_MESSAGING, userId);
+            grantDefaultPermissionsToDefaultSystemSmsApp(smsPackage, userId);
         } else {
-            for (String smsPackageName : smsAppPackageNames) {
-                PackageParser.Package smsPackage = getSystemPackage(smsPackageName);
-                if (smsPackage != null) {
-                    grantDefaultPermissionsToDefaultSystemSmsApp(smsPackage, userId);
-                }
+            for (String smsPackage : smsAppPackageNames) {
+                grantDefaultPermissionsToDefaultSystemSmsApp(smsPackage, userId);
             }
         }
 
         // Cell Broadcast Receiver
-        Intent cbrIntent = new Intent(Intents.SMS_CB_RECEIVED_ACTION);
-        PackageParser.Package cbrPackage =
-                getDefaultSystemHandlerActivityPackage(cbrIntent, userId);
-        if (cbrPackage != null && doesPackageSupportRuntimePermissions(cbrPackage)) {
-            grantRuntimePermissions(cbrPackage, SMS_PERMISSIONS, userId);
-        }
+        grantPermissionsToSystemPackage(
+                getDefaultSystemHandlerActivityPackage(Intents.SMS_CB_RECEIVED_ACTION, userId),
+                userId, SMS_PERMISSIONS);
 
         // Carrier Provisioning Service
-        Intent carrierProvIntent = new Intent(Intents.SMS_CARRIER_PROVISION_ACTION);
-        PackageParser.Package carrierProvPackage =
-                getDefaultSystemHandlerServicePackage(carrierProvIntent, userId);
-        if (carrierProvPackage != null
-                && doesPackageSupportRuntimePermissions(carrierProvPackage)) {
-            grantRuntimePermissions(carrierProvPackage, SMS_PERMISSIONS, false, userId);
-        }
+        grantPermissionsToSystemPackage(
+                getDefaultSystemHandlerServicePackage(Intents.SMS_CARRIER_PROVISION_ACTION, userId),
+                userId, SMS_PERMISSIONS);
 
         // Calendar
-        Intent calendarIntent = new Intent(Intent.ACTION_MAIN);
-        calendarIntent.addCategory(Intent.CATEGORY_APP_CALENDAR);
-        PackageParser.Package calendarPackage = getDefaultSystemHandlerActivityPackage(
-                calendarIntent, userId);
-        if (calendarPackage != null
-                && doesPackageSupportRuntimePermissions(calendarPackage)) {
-            grantRuntimePermissions(calendarPackage, CALENDAR_PERMISSIONS, userId);
-            grantRuntimePermissions(calendarPackage, CONTACTS_PERMISSIONS, userId);
-        }
+        grantPermissionsToSystemPackage(
+                getDefaultSystemHandlerActivityPackageForCategory(
+                        Intent.CATEGORY_APP_CALENDAR, userId),
+                userId, CALENDAR_PERMISSIONS, CONTACTS_PERMISSIONS);
 
         // Calendar provider
-        PackageParser.Package calendarProviderPackage = getDefaultProviderAuthorityPackage(
-                CalendarContract.AUTHORITY, userId);
-        if (calendarProviderPackage != null) {
-            grantRuntimePermissions(calendarProviderPackage, CONTACTS_PERMISSIONS, userId);
-            grantRuntimePermissions(calendarProviderPackage, CALENDAR_PERMISSIONS,
-                    true, userId);
-            grantRuntimePermissions(calendarProviderPackage, STORAGE_PERMISSIONS, userId);
-        }
+        String calendarProvider =
+                getDefaultProviderAuthorityPackage(CalendarContract.AUTHORITY, userId);
+        grantPermissionsToSystemPackage(calendarProvider, userId,
+                CONTACTS_PERMISSIONS, STORAGE_PERMISSIONS);
+        grantSystemFixedPermissionsToSystemPackage(calendarProvider, userId, CALENDAR_PERMISSIONS);
 
         // Calendar provider sync adapters
-        List<PackageParser.Package> calendarSyncAdapters = getHeadlessSyncAdapterPackages(
-                calendarSyncAdapterPackages, userId);
-        final int calendarSyncAdapterCount = calendarSyncAdapters.size();
-        for (int i = 0; i < calendarSyncAdapterCount; i++) {
-            PackageParser.Package calendarSyncAdapter = calendarSyncAdapters.get(i);
-            if (doesPackageSupportRuntimePermissions(calendarSyncAdapter)) {
-                grantRuntimePermissions(calendarSyncAdapter, CALENDAR_PERMISSIONS, userId);
-            }
-        }
+        grantPermissionToEachSystemPackage(
+                getHeadlessSyncAdapterPackages(calendarSyncAdapterPackages, userId),
+                userId, CALENDAR_PERMISSIONS);
 
         // Contacts
-        Intent contactsIntent = new Intent(Intent.ACTION_MAIN);
-        contactsIntent.addCategory(Intent.CATEGORY_APP_CONTACTS);
-        PackageParser.Package contactsPackage = getDefaultSystemHandlerActivityPackage(
-                contactsIntent, userId);
-        if (contactsPackage != null
-                && doesPackageSupportRuntimePermissions(contactsPackage)) {
-            grantRuntimePermissions(contactsPackage, CONTACTS_PERMISSIONS, userId);
-            grantRuntimePermissions(contactsPackage, PHONE_PERMISSIONS, userId);
-        }
+        grantPermissionsToSystemPackage(
+                getDefaultSystemHandlerActivityPackageForCategory(
+                        Intent.CATEGORY_APP_CONTACTS, userId),
+                userId, CONTACTS_PERMISSIONS, PHONE_PERMISSIONS);
 
         // Contacts provider sync adapters
-        List<PackageParser.Package> contactsSyncAdapters = getHeadlessSyncAdapterPackages(
-                contactsSyncAdapterPackages, userId);
-        final int contactsSyncAdapterCount = contactsSyncAdapters.size();
-        for (int i = 0; i < contactsSyncAdapterCount; i++) {
-            PackageParser.Package contactsSyncAdapter = contactsSyncAdapters.get(i);
-            if (doesPackageSupportRuntimePermissions(contactsSyncAdapter)) {
-                grantRuntimePermissions(contactsSyncAdapter, CONTACTS_PERMISSIONS, userId);
-            }
-        }
+        grantPermissionToEachSystemPackage(
+                getHeadlessSyncAdapterPackages(contactsSyncAdapterPackages, userId),
+                userId, CONTACTS_PERMISSIONS);
 
         // Contacts provider
-        PackageParser.Package contactsProviderPackage = getDefaultProviderAuthorityPackage(
-                ContactsContract.AUTHORITY, userId);
-        if (contactsProviderPackage != null) {
-            grantRuntimePermissions(contactsProviderPackage, CONTACTS_PERMISSIONS,
-                    true, userId);
-            grantRuntimePermissions(contactsProviderPackage, PHONE_PERMISSIONS,
-                    true, userId);
-            grantRuntimePermissions(contactsProviderPackage, STORAGE_PERMISSIONS, userId);
-        }
+        String contactsProviderPackage =
+                getDefaultProviderAuthorityPackage(ContactsContract.AUTHORITY, userId);
+        grantSystemFixedPermissionsToSystemPackage(contactsProviderPackage, userId,
+                CONTACTS_PERMISSIONS, PHONE_PERMISSIONS);
+        grantPermissionsToSystemPackage(contactsProviderPackage, userId, STORAGE_PERMISSIONS);
 
         // Device provisioning
-        Intent deviceProvisionIntent = new Intent(
-                DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE);
-        PackageParser.Package deviceProvisionPackage =
-                getDefaultSystemHandlerActivityPackage(deviceProvisionIntent, userId);
-        if (deviceProvisionPackage != null
-                && doesPackageSupportRuntimePermissions(deviceProvisionPackage)) {
-            grantRuntimePermissions(deviceProvisionPackage, CONTACTS_PERMISSIONS, userId);
-        }
+        grantPermissionsToSystemPackage(
+                getDefaultSystemHandlerActivityPackage(
+                        DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE, userId),
+                userId, CONTACTS_PERMISSIONS);
 
         // Maps
-        Intent mapsIntent = new Intent(Intent.ACTION_MAIN);
-        mapsIntent.addCategory(Intent.CATEGORY_APP_MAPS);
-        PackageParser.Package mapsPackage = getDefaultSystemHandlerActivityPackage(
-                mapsIntent, userId);
-        if (mapsPackage != null
-                && doesPackageSupportRuntimePermissions(mapsPackage)) {
-            grantRuntimePermissions(mapsPackage, LOCATION_PERMISSIONS, userId);
-        }
+        grantPermissionsToSystemPackage(
+                getDefaultSystemHandlerActivityPackageForCategory(Intent.CATEGORY_APP_MAPS, userId),
+                userId, LOCATION_PERMISSIONS);
 
         // Gallery
-        Intent galleryIntent = new Intent(Intent.ACTION_MAIN);
-        galleryIntent.addCategory(Intent.CATEGORY_APP_GALLERY);
-        PackageParser.Package galleryPackage = getDefaultSystemHandlerActivityPackage(
-                galleryIntent, userId);
-        if (galleryPackage != null
-                && doesPackageSupportRuntimePermissions(galleryPackage)) {
-            grantRuntimePermissions(galleryPackage, STORAGE_PERMISSIONS, userId);
-            grantRuntimePermissions(galleryPackage, MEDIA_VISUAL_PERMISSIONS, userId);
-        }
+        grantPermissionsToSystemPackage(
+                getDefaultSystemHandlerActivityPackageForCategory(
+                        Intent.CATEGORY_APP_GALLERY, userId),
+                userId, STORAGE_PERMISSIONS, MEDIA_VISUAL_PERMISSIONS);
 
         // Email
-        Intent emailIntent = new Intent(Intent.ACTION_MAIN);
-        emailIntent.addCategory(Intent.CATEGORY_APP_EMAIL);
-        PackageParser.Package emailPackage = getDefaultSystemHandlerActivityPackage(
-                emailIntent, userId);
-        if (emailPackage != null
-                && doesPackageSupportRuntimePermissions(emailPackage)) {
-            grantRuntimePermissions(emailPackage, CONTACTS_PERMISSIONS, userId);
-            grantRuntimePermissions(emailPackage, CALENDAR_PERMISSIONS, userId);
-        }
+        grantPermissionsToSystemPackage(
+                getDefaultSystemHandlerActivityPackageForCategory(
+                        Intent.CATEGORY_APP_EMAIL, userId),
+                userId, CONTACTS_PERMISSIONS, CALENDAR_PERMISSIONS);
 
         // Browser
-        PackageParser.Package browserPackage = null;
-        String defaultBrowserPackage = mServiceInternal.getKnownPackageName(
-                PackageManagerInternal.PACKAGE_BROWSER, userId);
-        if (defaultBrowserPackage != null) {
-            browserPackage = getPackage(defaultBrowserPackage);
-        }
+        String browserPackage = getKnownPackage(PackageManagerInternal.PACKAGE_BROWSER, userId);
         if (browserPackage == null) {
-            Intent browserIntent = new Intent(Intent.ACTION_MAIN);
-            browserIntent.addCategory(Intent.CATEGORY_APP_BROWSER);
-            browserPackage = getDefaultSystemHandlerActivityPackage(
-                    browserIntent, userId);
+            browserPackage = getDefaultSystemHandlerActivityPackageForCategory(
+                    Intent.CATEGORY_APP_BROWSER, userId);
+            if (!isSystemPackage(browserPackage)) {
+                browserPackage = null;
+            }
         }
-        if (browserPackage != null
-                && doesPackageSupportRuntimePermissions(browserPackage)) {
-            grantRuntimePermissions(browserPackage, LOCATION_PERMISSIONS, userId);
-        }
+        grantRuntimePermissionsToPackage(browserPackage, userId,
+                false /* systemFixed */, false /* ignoreSystemPackage */,
+                LOCATION_PERMISSIONS);
 
         // Voice interaction
         if (voiceInteractPackageNames != null) {
             for (String voiceInteractPackageName : voiceInteractPackageNames) {
-                PackageParser.Package voiceInteractPackage = getSystemPackage(
-                        voiceInteractPackageName);
-                if (voiceInteractPackage != null
-                        && doesPackageSupportRuntimePermissions(voiceInteractPackage)) {
-                    grantRuntimePermissions(voiceInteractPackage,
-                            CONTACTS_PERMISSIONS, userId);
-                    grantRuntimePermissions(voiceInteractPackage,
-                            CALENDAR_PERMISSIONS, userId);
-                    grantRuntimePermissions(voiceInteractPackage,
-                            MICROPHONE_PERMISSIONS, userId);
-                    grantRuntimePermissions(voiceInteractPackage,
-                            PHONE_PERMISSIONS, userId);
-                    grantRuntimePermissions(voiceInteractPackage,
-                            SMS_PERMISSIONS, userId);
-                    grantRuntimePermissions(voiceInteractPackage,
-                            LOCATION_PERMISSIONS, userId);
-                }
+                grantPermissionsToSystemPackage(voiceInteractPackageName, userId,
+                        CONTACTS_PERMISSIONS, CALENDAR_PERMISSIONS, MICROPHONE_PERMISSIONS,
+                        PHONE_PERMISSIONS, SMS_PERMISSIONS, LOCATION_PERMISSIONS);
             }
         }
 
         if (ActivityManager.isLowRamDeviceStatic()) {
             // Allow voice search on low-ram devices
-            Intent globalSearchIntent = new Intent("android.search.action.GLOBAL_SEARCH");
-            PackageParser.Package globalSearchPickerPackage =
-                getDefaultSystemHandlerActivityPackage(globalSearchIntent, userId);
-
-            if (globalSearchPickerPackage != null
-                    && doesPackageSupportRuntimePermissions(globalSearchPickerPackage)) {
-                grantRuntimePermissions(globalSearchPickerPackage,
-                    MICROPHONE_PERMISSIONS, false, userId);
-                grantRuntimePermissions(globalSearchPickerPackage,
-                    LOCATION_PERMISSIONS, false, userId);
-            }
+            grantPermissionsToSystemPackage(
+                    getDefaultSystemHandlerActivityPackage(
+                            SearchManager.INTENT_ACTION_GLOBAL_SEARCH, userId),
+                    userId, MICROPHONE_PERMISSIONS, LOCATION_PERMISSIONS);
         }
 
         // Voice recognition
-        Intent voiceRecoIntent = new Intent("android.speech.RecognitionService");
-        voiceRecoIntent.addCategory(Intent.CATEGORY_DEFAULT);
-        PackageParser.Package voiceRecoPackage = getDefaultSystemHandlerServicePackage(
-                voiceRecoIntent, userId);
-        if (voiceRecoPackage != null
-                && doesPackageSupportRuntimePermissions(voiceRecoPackage)) {
-            grantRuntimePermissions(voiceRecoPackage, MICROPHONE_PERMISSIONS, userId);
-        }
+        Intent voiceRecoIntent = new Intent(RecognitionService.SERVICE_INTERFACE)
+                .addCategory(Intent.CATEGORY_DEFAULT);
+        grantPermissionsToSystemPackage(
+                getDefaultSystemHandlerServicePackage(voiceRecoIntent, userId), userId,
+                MICROPHONE_PERMISSIONS);
 
         // Location
         if (locationPackageNames != null) {
             for (String packageName : locationPackageNames) {
-                PackageParser.Package locationPackage = getSystemPackage(packageName);
-                if (locationPackage != null
-                        && doesPackageSupportRuntimePermissions(locationPackage)) {
-                    grantRuntimePermissions(locationPackage, CONTACTS_PERMISSIONS, userId);
-                    grantRuntimePermissions(locationPackage, CALENDAR_PERMISSIONS, userId);
-                    grantRuntimePermissions(locationPackage, MICROPHONE_PERMISSIONS, userId);
-                    grantRuntimePermissions(locationPackage, PHONE_PERMISSIONS, userId);
-                    grantRuntimePermissions(locationPackage, SMS_PERMISSIONS, userId);
-                    grantRuntimePermissions(locationPackage, LOCATION_PERMISSIONS,
-                            true, userId);
-                    grantRuntimePermissions(locationPackage, CAMERA_PERMISSIONS, userId);
-                    grantRuntimePermissions(locationPackage, SENSORS_PERMISSIONS, userId);
-                    grantRuntimePermissions(locationPackage, STORAGE_PERMISSIONS, userId);
-                }
+                grantPermissionsToSystemPackage(packageName, userId,
+                        CONTACTS_PERMISSIONS, CALENDAR_PERMISSIONS, MICROPHONE_PERMISSIONS,
+                        PHONE_PERMISSIONS, SMS_PERMISSIONS, CAMERA_PERMISSIONS,
+                        SENSORS_PERMISSIONS, STORAGE_PERMISSIONS);
+                grantSystemFixedPermissionsToSystemPackage(packageName, userId,
+                        LOCATION_PERMISSIONS);
             }
         }
 
         // Music
-        Intent musicIntent = new Intent(Intent.ACTION_VIEW);
-        musicIntent.addCategory(Intent.CATEGORY_DEFAULT);
-        musicIntent.setDataAndType(Uri.fromFile(new File("foo.mp3")),
-                AUDIO_MIME_TYPE);
-        PackageParser.Package musicPackage = getDefaultSystemHandlerActivityPackage(
-                musicIntent, userId);
-        if (musicPackage != null
-                && doesPackageSupportRuntimePermissions(musicPackage)) {
-            grantRuntimePermissions(musicPackage, STORAGE_PERMISSIONS, userId);
-            grantRuntimePermissions(musicPackage, MEDIA_AURAL_PERMISSIONS, userId);
-        }
+        Intent musicIntent = new Intent(Intent.ACTION_VIEW)
+                .addCategory(Intent.CATEGORY_DEFAULT)
+                .setDataAndType(Uri.fromFile(new File("foo.mp3")), AUDIO_MIME_TYPE);
+        grantPermissionsToSystemPackage(
+                getDefaultSystemHandlerActivityPackage(musicIntent, userId), userId,
+                STORAGE_PERMISSIONS, MEDIA_AURAL_PERMISSIONS);
 
         // Home
-        Intent homeIntent = new Intent(Intent.ACTION_MAIN);
-        homeIntent.addCategory(Intent.CATEGORY_HOME);
-        homeIntent.addCategory(Intent.CATEGORY_LAUNCHER_APP);
-        PackageParser.Package homePackage = getDefaultSystemHandlerActivityPackage(
-                homeIntent, userId);
-        if (homePackage != null
-                && doesPackageSupportRuntimePermissions(homePackage)) {
-            grantRuntimePermissions(homePackage, LOCATION_PERMISSIONS, false, userId);
-        }
+        Intent homeIntent = new Intent(Intent.ACTION_MAIN)
+                .addCategory(Intent.CATEGORY_HOME)
+                .addCategory(Intent.CATEGORY_LAUNCHER_APP);
+        grantPermissionsToSystemPackage(
+                getDefaultSystemHandlerActivityPackage(homeIntent, userId), userId,
+                LOCATION_PERMISSIONS);
 
         // Watches
         if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH, 0)) {
             // Home application on watches
-            Intent wearHomeIntent = new Intent(Intent.ACTION_MAIN);
-            wearHomeIntent.addCategory(Intent.CATEGORY_HOME_MAIN);
 
-            PackageParser.Package wearHomePackage = getDefaultSystemHandlerActivityPackage(
-                    wearHomeIntent, userId);
-
-            if (wearHomePackage != null
-                    && doesPackageSupportRuntimePermissions(wearHomePackage)) {
-                grantRuntimePermissions(wearHomePackage, CONTACTS_PERMISSIONS, false,
-                        userId);
-                grantRuntimePermissions(wearHomePackage, PHONE_PERMISSIONS, true, userId);
-                grantRuntimePermissions(wearHomePackage, MICROPHONE_PERMISSIONS, false,
-                        userId);
-                grantRuntimePermissions(wearHomePackage, LOCATION_PERMISSIONS, false,
-                        userId);
-            }
+            String wearPackage = getDefaultSystemHandlerActivityPackageForCategory(
+                    Intent.CATEGORY_HOME_MAIN, userId);
+            grantPermissionsToSystemPackage(wearPackage, userId,
+                    CONTACTS_PERMISSIONS, MICROPHONE_PERMISSIONS, LOCATION_PERMISSIONS);
+            grantSystemFixedPermissionsToSystemPackage(wearPackage, userId, PHONE_PERMISSIONS);
 
             // Fitness tracking on watches
-            Intent trackIntent = new Intent(ACTION_TRACK);
-            PackageParser.Package trackPackage = getDefaultSystemHandlerActivityPackage(
-                    trackIntent, userId);
-            if (trackPackage != null
-                    && doesPackageSupportRuntimePermissions(trackPackage)) {
-                grantRuntimePermissions(trackPackage, SENSORS_PERMISSIONS, false, userId);
-                grantRuntimePermissions(trackPackage, LOCATION_PERMISSIONS, false, userId);
-            }
+            grantPermissionsToSystemPackage(
+                    getDefaultSystemHandlerActivityPackage(ACTION_TRACK, userId), userId,
+                    SENSORS_PERMISSIONS, LOCATION_PERMISSIONS);
         }
 
         // Print Spooler
-        PackageParser.Package printSpoolerPackage = getSystemPackage(
-                PrintManager.PRINT_SPOOLER_PACKAGE_NAME);
-        if (printSpoolerPackage != null
-                && doesPackageSupportRuntimePermissions(printSpoolerPackage)) {
-            grantRuntimePermissions(printSpoolerPackage, LOCATION_PERMISSIONS, true, userId);
-        }
+        grantSystemFixedPermissionsToSystemPackage(PrintManager.PRINT_SPOOLER_PACKAGE_NAME, userId,
+                LOCATION_PERMISSIONS);
 
         // EmergencyInfo
-        Intent emergencyInfoIntent = new Intent(TelephonyManager.ACTION_EMERGENCY_ASSISTANCE);
-        PackageParser.Package emergencyInfoPckg = getDefaultSystemHandlerActivityPackage(
-                emergencyInfoIntent, userId);
-        if (emergencyInfoPckg != null
-                && doesPackageSupportRuntimePermissions(emergencyInfoPckg)) {
-            grantRuntimePermissions(emergencyInfoPckg, CONTACTS_PERMISSIONS, true, userId);
-            grantRuntimePermissions(emergencyInfoPckg, PHONE_PERMISSIONS, true, userId);
-        }
+        grantSystemFixedPermissionsToSystemPackage(
+                getDefaultSystemHandlerActivityPackage(
+                        TelephonyManager.ACTION_EMERGENCY_ASSISTANCE, userId),
+                userId, CONTACTS_PERMISSIONS, PHONE_PERMISSIONS);
 
         // NFC Tag viewer
-        Intent nfcTagIntent = new Intent(Intent.ACTION_VIEW);
-        nfcTagIntent.setType("vnd.android.cursor.item/ndef_msg");
-        PackageParser.Package nfcTagPkg = getDefaultSystemHandlerActivityPackage(
-                nfcTagIntent, userId);
-        if (nfcTagPkg != null
-                && doesPackageSupportRuntimePermissions(nfcTagPkg)) {
-            grantRuntimePermissions(nfcTagPkg, CONTACTS_PERMISSIONS, false, userId);
-            grantRuntimePermissions(nfcTagPkg, PHONE_PERMISSIONS, false, userId);
-        }
+        Intent nfcTagIntent = new Intent(Intent.ACTION_VIEW)
+                .setType("vnd.android.cursor.item/ndef_msg");
+        grantPermissionsToSystemPackage(
+                getDefaultSystemHandlerActivityPackage(nfcTagIntent, userId), userId,
+                CONTACTS_PERMISSIONS, PHONE_PERMISSIONS);
 
         // Storage Manager
-        Intent storageManagerIntent = new Intent(StorageManager.ACTION_MANAGE_STORAGE);
-        PackageParser.Package storageManagerPckg = getDefaultSystemHandlerActivityPackage(
-                storageManagerIntent, userId);
-        if (storageManagerPckg != null
-                && doesPackageSupportRuntimePermissions(storageManagerPckg)) {
-            grantRuntimePermissions(storageManagerPckg, STORAGE_PERMISSIONS, true, userId);
-        }
+        grantSystemFixedPermissionsToSystemPackage(
+                getDefaultSystemHandlerActivityPackage(
+                        StorageManager.ACTION_MANAGE_STORAGE, userId),
+                userId, STORAGE_PERMISSIONS);
 
         // Companion devices
-        PackageParser.Package companionDeviceDiscoveryPackage = getSystemPackage(
-                CompanionDeviceManager.COMPANION_DEVICE_DISCOVERY_PACKAGE_NAME);
-        if (companionDeviceDiscoveryPackage != null
-                && doesPackageSupportRuntimePermissions(companionDeviceDiscoveryPackage)) {
-            grantRuntimePermissions(companionDeviceDiscoveryPackage,
-                    LOCATION_PERMISSIONS, true, userId);
-        }
+        grantSystemFixedPermissionsToSystemPackage(
+                CompanionDeviceManager.COMPANION_DEVICE_DISCOVERY_PACKAGE_NAME, userId,
+                LOCATION_PERMISSIONS);
 
         // Ringtone Picker
-        Intent ringtonePickerIntent = new Intent(RingtoneManager.ACTION_RINGTONE_PICKER);
-        PackageParser.Package ringtonePickerPackage =
-                getDefaultSystemHandlerActivityPackage(ringtonePickerIntent, userId);
-        if (ringtonePickerPackage != null
-                && doesPackageSupportRuntimePermissions(ringtonePickerPackage)) {
-            grantRuntimePermissions(ringtonePickerPackage,
-                    STORAGE_PERMISSIONS, true, userId);
-        }
+        grantSystemFixedPermissionsToSystemPackage(
+                getDefaultSystemHandlerActivityPackage(
+                        RingtoneManager.ACTION_RINGTONE_PICKER, userId),
+                userId, STORAGE_PERMISSIONS);
 
         // TextClassifier Service
         String textClassifierPackageName =
                 mContext.getPackageManager().getSystemTextClassifierPackageName();
         if (!TextUtils.isEmpty(textClassifierPackageName)) {
-            PackageParser.Package textClassifierPackage =
-                    getSystemPackage(textClassifierPackageName);
-            if (textClassifierPackage != null
-                    && doesPackageSupportRuntimePermissions(textClassifierPackage)) {
-                grantRuntimePermissions(textClassifierPackage, PHONE_PERMISSIONS, false, userId);
-                grantRuntimePermissions(textClassifierPackage, SMS_PERMISSIONS, false, userId);
-                grantRuntimePermissions(textClassifierPackage, CALENDAR_PERMISSIONS, false, userId);
-                grantRuntimePermissions(textClassifierPackage, LOCATION_PERMISSIONS, false, userId);
-                grantRuntimePermissions(textClassifierPackage, CONTACTS_PERMISSIONS, false, userId);
-            }
+            grantPermissionsToSystemPackage(textClassifierPackageName, userId,
+                    PHONE_PERMISSIONS, SMS_PERMISSIONS, CALENDAR_PERMISSIONS,
+                    LOCATION_PERMISSIONS, CONTACTS_PERMISSIONS);
         }
 
         // There is no real "marker" interface to identify the shared storage backup, it is
         // hardcoded in BackupManagerService.SHARED_BACKUP_AGENT_PACKAGE.
-        PackageParser.Package sharedStorageBackupPackage = getSystemPackage(
-                "com.android.sharedstoragebackup");
-        if (sharedStorageBackupPackage != null) {
-            grantRuntimePermissions(sharedStorageBackupPackage, STORAGE_PERMISSIONS, true, userId);
-        }
+        grantSystemFixedPermissionsToSystemPackage("com.android.sharedstoragebackup", userId,
+                STORAGE_PERMISSIONS);
 
         if (mPermissionGrantedCallback != null) {
             mPermissionGrantedCallback.onDefaultRuntimePermissionsGranted(userId);
         }
     }
 
-    private void grantDefaultPermissionsToDefaultSystemDialerApp(
-            PackageParser.Package dialerPackage, int userId) {
-        if (doesPackageSupportRuntimePermissions(dialerPackage)) {
-            boolean isPhonePermFixed =
-                    mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH, 0);
-            grantRuntimePermissions(
-                    dialerPackage, PHONE_PERMISSIONS, isPhonePermFixed, userId);
-            grantRuntimePermissions(dialerPackage, CONTACTS_PERMISSIONS, userId);
-            grantRuntimePermissions(dialerPackage, SMS_PERMISSIONS, userId);
-            grantRuntimePermissions(dialerPackage, MICROPHONE_PERMISSIONS, userId);
-            grantRuntimePermissions(dialerPackage, CAMERA_PERMISSIONS, userId);
+    private String getDefaultSystemHandlerActivityPackageForCategory(String category, int userId) {
+        return getDefaultSystemHandlerActivityPackage(
+                new Intent(Intent.ACTION_MAIN).addCategory(category), userId);
+    }
+
+    @SafeVarargs
+    private final void grantPermissionToEachSystemPackage(
+            ArrayList<String> packages, int userId, Set<String>... permissions) {
+        if (packages == null) return;
+        final int count = packages.size();
+        for (int i = 0; i < count; i++) {
+            grantPermissionsToSystemPackage(packages.get(i), userId, permissions);
         }
     }
 
-    private void grantDefaultPermissionsToDefaultSystemSmsApp(
-            PackageParser.Package smsPackage, int userId) {
-        if (doesPackageSupportRuntimePermissions(smsPackage)) {
-            grantRuntimePermissions(smsPackage, PHONE_PERMISSIONS, userId);
-            grantRuntimePermissions(smsPackage, CONTACTS_PERMISSIONS, userId);
-            grantRuntimePermissions(smsPackage, SMS_PERMISSIONS, userId);
-            grantRuntimePermissions(smsPackage, STORAGE_PERMISSIONS, userId);
-            grantRuntimePermissions(smsPackage, MICROPHONE_PERMISSIONS, userId);
-            grantRuntimePermissions(smsPackage, CAMERA_PERMISSIONS, userId);
+    private String getKnownPackage(int knownPkgId, int userId) {
+        return mServiceInternal.getKnownPackageName(knownPkgId, userId);
+    }
+
+    private void grantDefaultPermissionsToDefaultSystemDialerApp(
+            String dialerPackage, int userId) {
+        if (dialerPackage == null) {
+            return;
         }
+        boolean isPhonePermFixed =
+                mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH, 0);
+        if (isPhonePermFixed) {
+            grantSystemFixedPermissionsToSystemPackage(dialerPackage, userId, PHONE_PERMISSIONS);
+        } else {
+            grantPermissionsToSystemPackage(dialerPackage, userId, PHONE_PERMISSIONS);
+        }
+        grantPermissionsToSystemPackage(dialerPackage, userId,
+                CONTACTS_PERMISSIONS, SMS_PERMISSIONS, MICROPHONE_PERMISSIONS, CAMERA_PERMISSIONS);
+    }
+
+    private void grantDefaultPermissionsToDefaultSystemSmsApp(String smsPackage, int userId) {
+        grantPermissionsToSystemPackage(smsPackage, userId,
+                PHONE_PERMISSIONS, CONTACTS_PERMISSIONS, SMS_PERMISSIONS,
+                STORAGE_PERMISSIONS, MICROPHONE_PERMISSIONS, CAMERA_PERMISSIONS);
     }
 
     private void grantDefaultPermissionsToDefaultSystemUseOpenWifiApp(
-            PackageParser.Package useOpenWifiPackage, int userId) {
-        if (doesPackageSupportRuntimePermissions(useOpenWifiPackage)) {
-            grantRuntimePermissions(useOpenWifiPackage, COARSE_LOCATION_PERMISSIONS, userId);
-        }
+            String useOpenWifiPackage, int userId) {
+        grantPermissionsToSystemPackage(
+                useOpenWifiPackage, userId, COARSE_LOCATION_PERMISSIONS);
     }
 
     public void grantDefaultPermissionsToDefaultSmsApp(String packageName, int userId) {
         Log.i(TAG, "Granting permissions to default sms app for user:" + userId);
-        if (packageName == null) {
-            return;
-        }
-        PackageParser.Package smsPackage = getPackage(packageName);
-        if (smsPackage != null && doesPackageSupportRuntimePermissions(smsPackage)) {
-            grantRuntimePermissions(smsPackage, PHONE_PERMISSIONS, false, true, userId);
-            grantRuntimePermissions(smsPackage, CONTACTS_PERMISSIONS, false, true, userId);
-            grantRuntimePermissions(smsPackage, SMS_PERMISSIONS, false, true, userId);
-            grantRuntimePermissions(smsPackage, STORAGE_PERMISSIONS, false, true, userId);
-            grantRuntimePermissions(smsPackage, MICROPHONE_PERMISSIONS, false, true, userId);
-            grantRuntimePermissions(smsPackage, CAMERA_PERMISSIONS, false, true, userId);
-        }
+        grantIgnoringSystemPackage(packageName, userId,
+                PHONE_PERMISSIONS, CONTACTS_PERMISSIONS, SMS_PERMISSIONS, STORAGE_PERMISSIONS,
+                MICROPHONE_PERMISSIONS, CAMERA_PERMISSIONS);
     }
 
     public void grantDefaultPermissionsToDefaultDialerApp(String packageName, int userId) {
+        mServiceInternal.onDefaultDialerAppChanged(packageName, userId);
         Log.i(TAG, "Granting permissions to default dialer app for user:" + userId);
-        if (packageName == null) {
-            return;
-        }
-        PackageParser.Package dialerPackage = getPackage(packageName);
-        if (dialerPackage != null
-                && doesPackageSupportRuntimePermissions(dialerPackage)) {
-            grantRuntimePermissions(dialerPackage, PHONE_PERMISSIONS, false, true, userId);
-            grantRuntimePermissions(dialerPackage, CONTACTS_PERMISSIONS, false, true, userId);
-            grantRuntimePermissions(dialerPackage, SMS_PERMISSIONS, false, true, userId);
-            grantRuntimePermissions(dialerPackage, MICROPHONE_PERMISSIONS, false, true, userId);
-            grantRuntimePermissions(dialerPackage, CAMERA_PERMISSIONS, false, true, userId);
-        }
+        grantIgnoringSystemPackage(packageName, userId,
+                PHONE_PERMISSIONS, CONTACTS_PERMISSIONS, SMS_PERMISSIONS,
+                MICROPHONE_PERMISSIONS, CAMERA_PERMISSIONS);
     }
 
     public void grantDefaultPermissionsToDefaultUseOpenWifiApp(String packageName, int userId) {
         Log.i(TAG, "Granting permissions to default Use Open WiFi app for user:" + userId);
-        if (packageName == null) {
-            return;
-        }
-        PackageParser.Package useOpenWifiPackage = getPackage(packageName);
-        if (useOpenWifiPackage != null
-                && doesPackageSupportRuntimePermissions(useOpenWifiPackage)) {
-            grantRuntimePermissions(
-                    useOpenWifiPackage, COARSE_LOCATION_PERMISSIONS, false, true, userId);
-        }
-    }
-
-    private void grantDefaultPermissionsToDefaultSimCallManager(
-            PackageParser.Package simCallManagerPackage, int userId) {
-        Log.i(TAG, "Granting permissions to sim call manager for user:" + userId);
-        if (doesPackageSupportRuntimePermissions(simCallManagerPackage)) {
-            grantRuntimePermissions(simCallManagerPackage, PHONE_PERMISSIONS, userId);
-            grantRuntimePermissions(simCallManagerPackage, MICROPHONE_PERMISSIONS, userId);
-        }
+        grantIgnoringSystemPackage(packageName, userId, COARSE_LOCATION_PERMISSIONS);
     }
 
     public void grantDefaultPermissionsToDefaultSimCallManager(String packageName, int userId) {
         if (packageName == null) {
             return;
         }
-        PackageParser.Package simCallManagerPackage = getPackage(packageName);
-        if (simCallManagerPackage != null) {
-            grantDefaultPermissionsToDefaultSimCallManager(simCallManagerPackage, userId);
+        Log.i(TAG, "Granting permissions to sim call manager for user:" + userId);
+        grantRuntimePermissionsToPackage(packageName, userId, false, false,
+                PHONE_PERMISSIONS, MICROPHONE_PERMISSIONS);
+    }
+
+    private void grantDefaultPermissionsToDefaultSystemSimCallManager(
+            String packageName, int userId) {
+        if (isSystemPackage(packageName)) {
+            grantDefaultPermissionsToDefaultSimCallManager(packageName, userId);
         }
     }
 
@@ -976,13 +801,8 @@
             return;
         }
         for (String packageName : packageNames) {
-            PackageParser.Package carrierPackage = getSystemPackage(packageName);
-            if (carrierPackage != null
-                    && doesPackageSupportRuntimePermissions(carrierPackage)) {
-                grantRuntimePermissions(carrierPackage, PHONE_PERMISSIONS, userId);
-                grantRuntimePermissions(carrierPackage, LOCATION_PERMISSIONS, userId);
-                grantRuntimePermissions(carrierPackage, SMS_PERMISSIONS, userId);
-            }
+            grantPermissionsToSystemPackage(packageName, userId,
+                    PHONE_PERMISSIONS, LOCATION_PERMISSIONS, SMS_PERMISSIONS);
         }
     }
 
@@ -992,15 +812,9 @@
             return;
         }
         for (String packageName : packageNames) {
-            PackageParser.Package imsServicePackage = getSystemPackage(packageName);
-            if (imsServicePackage != null
-                    && doesPackageSupportRuntimePermissions(imsServicePackage)) {
-                grantRuntimePermissions(imsServicePackage, PHONE_PERMISSIONS, userId);
-                grantRuntimePermissions(imsServicePackage, MICROPHONE_PERMISSIONS, userId);
-                grantRuntimePermissions(imsServicePackage, LOCATION_PERMISSIONS, userId);
-                grantRuntimePermissions(imsServicePackage, CAMERA_PERMISSIONS, userId);
-                grantRuntimePermissions(imsServicePackage, CONTACTS_PERMISSIONS, userId);
-            }
+            grantPermissionsToSystemPackage(packageName, userId,
+                    PHONE_PERMISSIONS, MICROPHONE_PERMISSIONS, LOCATION_PERMISSIONS,
+                    CAMERA_PERMISSIONS, CONTACTS_PERMISSIONS);
         }
     }
 
@@ -1011,15 +825,12 @@
             return;
         }
         for (String packageName : packageNames) {
-            PackageParser.Package dataServicePackage = getSystemPackage(packageName);
-            if (dataServicePackage != null
-                    && doesPackageSupportRuntimePermissions(dataServicePackage)) {
-                // Grant these permissions as system-fixed, so that nobody can accidentally
-                // break cellular data.
-                grantRuntimePermissions(dataServicePackage, PHONE_PERMISSIONS, true, userId);
-                grantRuntimePermissions(dataServicePackage, LOCATION_PERMISSIONS, true, userId);
-            }
+            // Grant these permissions as system-fixed, so that nobody can accidentally
+            // break cellular data.
+            grantSystemFixedPermissionsToSystemPackage(packageName, userId,
+                    PHONE_PERMISSIONS, LOCATION_PERMISSIONS);
         }
+
     }
 
     public void revokeDefaultPermissionsFromDisabledTelephonyDataServices(
@@ -1029,25 +840,17 @@
             return;
         }
         for (String packageName : packageNames) {
-            PackageParser.Package dataServicePackage = getSystemPackage(packageName);
-            if (dataServicePackage != null
-                    && doesPackageSupportRuntimePermissions(dataServicePackage)) {
-                revokeRuntimePermissions(dataServicePackage, PHONE_PERMISSIONS, true, userId);
-                revokeRuntimePermissions(dataServicePackage, LOCATION_PERMISSIONS, true, userId);
+            PackageInfo pkg = getSystemPackageInfo(packageName);
+            if (isSystemPackage(pkg) && doesPackageSupportRuntimePermissions(pkg)) {
+                revokeRuntimePermissions(packageName, PHONE_PERMISSIONS, true, userId);
+                revokeRuntimePermissions(packageName, LOCATION_PERMISSIONS, true, userId);
             }
         }
     }
 
     public void grantDefaultPermissionsToActiveLuiApp(String packageName, int userId) {
         Log.i(TAG, "Granting permissions to active LUI app for user:" + userId);
-        if (packageName == null) {
-            return;
-        }
-        PackageParser.Package luiAppPackage = getSystemPackage(packageName);
-        if (luiAppPackage != null
-                && doesPackageSupportRuntimePermissions(luiAppPackage)) {
-            grantRuntimePermissions(luiAppPackage, CAMERA_PERMISSIONS, true, userId);
-        }
+        grantSystemFixedPermissionsToSystemPackage(packageName, userId, CAMERA_PERMISSIONS);
     }
 
     public void revokeDefaultPermissionsFromLuiApps(String[] packageNames, int userId) {
@@ -1056,123 +859,116 @@
             return;
         }
         for (String packageName : packageNames) {
-            PackageParser.Package luiAppPackage = getSystemPackage(packageName);
-            if (luiAppPackage != null
-                    && doesPackageSupportRuntimePermissions(luiAppPackage)) {
-                revokeRuntimePermissions(luiAppPackage, CAMERA_PERMISSIONS, true, userId);
+            PackageInfo pkg = getSystemPackageInfo(packageName);
+            if (isSystemPackage(pkg) && doesPackageSupportRuntimePermissions(pkg)) {
+                revokeRuntimePermissions(packageName, CAMERA_PERMISSIONS, true, userId);
             }
         }
     }
 
     public void grantDefaultPermissionsToDefaultBrowser(String packageName, int userId) {
         Log.i(TAG, "Granting permissions to default browser for user:" + userId);
-        if (packageName == null) {
-            return;
-        }
-        PackageParser.Package browserPackage = getSystemPackage(packageName);
-        if (browserPackage != null
-                && doesPackageSupportRuntimePermissions(browserPackage)) {
-            grantRuntimePermissions(browserPackage, LOCATION_PERMISSIONS, false, false, userId);
-        }
+        grantPermissionsToSystemPackage(packageName, userId, LOCATION_PERMISSIONS);
     }
 
-    private PackageParser.Package getDefaultSystemHandlerActivityPackage(
-            Intent intent, int userId) {
+    private String getDefaultSystemHandlerActivityPackage(String intentAction, int userId) {
+        return getDefaultSystemHandlerActivityPackage(new Intent(intentAction), userId);
+    }
+
+    private String getDefaultSystemHandlerActivityPackage(Intent intent, int userId) {
         ResolveInfo handler = mServiceInternal.resolveIntent(intent,
-                intent.resolveType(mContext.getContentResolver()), DEFAULT_FLAGS, userId, false,
-                Binder.getCallingUid());
+                intent.resolveType(mContext.getContentResolver()), DEFAULT_INTENT_QUERY_FLAGS,
+                userId, false, Binder.getCallingUid());
         if (handler == null || handler.activityInfo == null) {
             return null;
         }
         if (mServiceInternal.isResolveActivityComponent(handler.activityInfo)) {
             return null;
         }
-        return getSystemPackage(handler.activityInfo.packageName);
+        String packageName = handler.activityInfo.packageName;
+        return isSystemPackage(packageName) ? packageName : null;
     }
 
-    private PackageParser.Package getDefaultSystemHandlerServicePackage(
+    private String getDefaultSystemHandlerServicePackage(String intentAction, int userId) {
+        return getDefaultSystemHandlerServicePackage(new Intent(intentAction), userId);
+    }
+
+    private String getDefaultSystemHandlerServicePackage(
             Intent intent, int userId) {
         List<ResolveInfo> handlers = mServiceInternal.queryIntentServices(
-                intent, DEFAULT_FLAGS, Binder.getCallingUid(), userId);
+                intent, DEFAULT_INTENT_QUERY_FLAGS, Binder.getCallingUid(), userId);
         if (handlers == null) {
             return null;
         }
         final int handlerCount = handlers.size();
         for (int i = 0; i < handlerCount; i++) {
             ResolveInfo handler = handlers.get(i);
-            PackageParser.Package handlerPackage = getSystemPackage(
-                    handler.serviceInfo.packageName);
-            if (handlerPackage != null) {
+            String handlerPackage = handler.serviceInfo.packageName;
+            if (isSystemPackage(handlerPackage)) {
                 return handlerPackage;
             }
         }
         return null;
     }
 
-    private List<PackageParser.Package> getHeadlessSyncAdapterPackages(
+    private ArrayList<String> getHeadlessSyncAdapterPackages(
             String[] syncAdapterPackageNames, int userId) {
-        List<PackageParser.Package> syncAdapterPackages = new ArrayList<>();
+        ArrayList<String> syncAdapterPackages = new ArrayList<>();
 
-        Intent homeIntent = new Intent(Intent.ACTION_MAIN);
-        homeIntent.addCategory(Intent.CATEGORY_LAUNCHER);
+        Intent homeIntent = new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_LAUNCHER);
 
         for (String syncAdapterPackageName : syncAdapterPackageNames) {
             homeIntent.setPackage(syncAdapterPackageName);
 
             ResolveInfo homeActivity = mServiceInternal.resolveIntent(homeIntent,
-                    homeIntent.resolveType(mContext.getContentResolver()), DEFAULT_FLAGS,
+                    homeIntent.resolveType(mContext.getContentResolver()),
+                    DEFAULT_INTENT_QUERY_FLAGS,
                     userId, false, Binder.getCallingUid());
             if (homeActivity != null) {
                 continue;
             }
 
-            PackageParser.Package syncAdapterPackage = getSystemPackage(syncAdapterPackageName);
-            if (syncAdapterPackage != null) {
-                syncAdapterPackages.add(syncAdapterPackage);
+            if (isSystemPackage(syncAdapterPackageName)) {
+                syncAdapterPackages.add(syncAdapterPackageName);
             }
         }
 
         return syncAdapterPackages;
     }
 
-    private PackageParser.Package getDefaultProviderAuthorityPackage(
-            String authority, int userId) {
-        ProviderInfo provider =
-                mServiceInternal.resolveContentProvider(authority, DEFAULT_FLAGS, userId);
+    private String getDefaultProviderAuthorityPackage(String authority, int userId) {
+        ProviderInfo provider = mServiceInternal.resolveContentProvider(
+                authority, DEFAULT_INTENT_QUERY_FLAGS, userId);
         if (provider != null) {
-            return getSystemPackage(provider.packageName);
+            return provider.packageName;
         }
         return null;
     }
 
-    private PackageParser.Package getPackage(String packageName) {
-        return mServiceInternal.getPackage(packageName);
+    private boolean isSystemPackage(String packageName) {
+        return isSystemPackage(getSystemPackageInfo(packageName));
     }
 
-    private PackageParser.Package getSystemPackage(String packageName) {
-        PackageParser.Package pkg = getPackage(packageName);
-        if (pkg != null && pkg.isSystem()) {
-            return !isSysComponentOrPersistentPlatformSignedPrivApp(pkg) ? pkg : null;
+    private boolean isSystemPackage(PackageInfo pkg) {
+        if (pkg == null) {
+            return false;
         }
-        return null;
+        return pkg.applicationInfo.isSystemApp()
+                && !isSysComponentOrPersistentPlatformSignedPrivApp(pkg);
     }
 
-    private void grantRuntimePermissions(PackageParser.Package pkg, Set<String> permissions,
-            int userId) {
-        grantRuntimePermissions(pkg, permissions, false, false, userId);
-    }
-
-    private void grantRuntimePermissions(PackageParser.Package pkg, Set<String> permissions,
+    private void grantRuntimePermissions(PackageInfo pkg, Set<String> permissions,
             boolean systemFixed, int userId) {
         grantRuntimePermissions(pkg, permissions, systemFixed, false, userId);
     }
 
-    private void revokeRuntimePermissions(PackageParser.Package pkg, Set<String> permissions,
+    private void revokeRuntimePermissions(String packageName, Set<String> permissions,
             boolean systemFixed, int userId) {
-        if (pkg.requestedPermissions.isEmpty()) {
+        PackageInfo pkg = getSystemPackageInfo(packageName);
+        if (ArrayUtils.isEmpty(pkg.requestedPermissions)) {
             return;
         }
-        Set<String> revokablePermissions = new ArraySet<>(pkg.requestedPermissions);
+        Set<String> revokablePermissions = new ArraySet<>(Arrays.asList(pkg.requestedPermissions));
 
         for (String permission : permissions) {
             // We can't revoke what wasn't requested.
@@ -1181,7 +977,7 @@
             }
 
             final int flags = mServiceInternal.getPermissionFlagsTEMP(
-                    permission, pkg.packageName, userId);
+                    permission, packageName, userId);
 
             // We didn't get this through the default grant policy. Move along.
             if ((flags & PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT) == 0) {
@@ -1197,29 +993,35 @@
             if ((flags & PackageManager.FLAG_PERMISSION_SYSTEM_FIXED) != 0 && !systemFixed) {
                 continue;
             }
-            mServiceInternal.revokeRuntimePermission(pkg.packageName, permission, userId, false);
+            mServiceInternal.revokeRuntimePermission(packageName, permission, userId, false);
 
             if (DEBUG) {
                 Log.i(TAG, "revoked " + (systemFixed ? "fixed " : "not fixed ")
-                        + permission + " to " + pkg.packageName);
+                        + permission + " to " + packageName);
             }
 
             // Remove the GRANTED_BY_DEFAULT flag without touching the others.
             // Note that we do not revoke FLAG_PERMISSION_SYSTEM_FIXED. That bit remains
             // sticky once set.
-            mServiceInternal.updatePermissionFlagsTEMP(permission, pkg.packageName,
+            mServiceInternal.updatePermissionFlagsTEMP(permission, packageName,
                     PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT, 0, userId);
         }
     }
 
-    private void grantRuntimePermissions(PackageParser.Package pkg,
+    private void grantRuntimePermissions(PackageInfo pkg,
             Set<String> permissionsWithoutSplits, boolean systemFixed, boolean ignoreSystemPackage,
             int userId) {
-        if (pkg.requestedPermissions.isEmpty()) {
+        if (pkg == null) {
+            return;
+        }
+
+        String[] requestedPermissions = pkg.requestedPermissions;
+        if (ArrayUtils.isEmpty(requestedPermissions)) {
             return;
         }
 
         final ArraySet<String> permissions = new ArraySet<>(permissionsWithoutSplits);
+        ApplicationInfo applicationInfo = pkg.applicationInfo;
 
         // Automatically attempt to grant split permissions to older APKs
         final int numSplitPerms = PackageParser.SPLIT_PERMISSIONS.length;
@@ -1227,13 +1029,13 @@
             final PackageParser.SplitPermissionInfo splitPerm =
                     PackageParser.SPLIT_PERMISSIONS[splitPermNum];
 
-            if (pkg.applicationInfo.targetSdkVersion < splitPerm.targetSdk
+            if (applicationInfo != null
+                    && applicationInfo.targetSdkVersion < splitPerm.targetSdk
                     && permissionsWithoutSplits.contains(splitPerm.rootPerm)) {
                 Collections.addAll(permissions, splitPerm.newPerms);
             }
         }
 
-        List<String> requestedPermissions = pkg.requestedPermissions;
         Set<String> grantablePermissions = null;
 
         // In some cases, like for the Phone or SMS app, we grant permissions regardless
@@ -1242,23 +1044,25 @@
         // choice to grant this app the permissions needed to function. For all other
         // apps, (default grants on first boot and user creation) we don't grant default
         // permissions if the version on the system image does not declare them.
-        if (!ignoreSystemPackage && pkg.isUpdatedSystemApp()) {
-            final PackageParser.Package disabledPkg =
-                    mServiceInternal.getDisabledPackage(pkg.packageName);
+        if (!ignoreSystemPackage
+                && applicationInfo != null
+                && applicationInfo.isUpdatedSystemApp()) {
+            final PackageInfo disabledPkg = getSystemPackageInfo(
+                    mServiceInternal.getDisabledSystemPackageName(pkg.packageName));
             if (disabledPkg != null) {
-                if (disabledPkg.requestedPermissions.isEmpty()) {
+                if (ArrayUtils.isEmpty(disabledPkg.requestedPermissions)) {
                     return;
                 }
                 if (!requestedPermissions.equals(disabledPkg.requestedPermissions)) {
-                    grantablePermissions = new ArraySet<>(requestedPermissions);
+                    grantablePermissions = new ArraySet<>(Arrays.asList(requestedPermissions));
                     requestedPermissions = disabledPkg.requestedPermissions;
                 }
             }
         }
 
-        final int grantablePermissionCount = requestedPermissions.size();
+        final int grantablePermissionCount = requestedPermissions.length;
         for (int i = 0; i < grantablePermissionCount; i++) {
-            String permission = requestedPermissions.get(i);
+            String permission = requestedPermissions[i];
 
             // If there is a disabled system app it may request a permission the updated
             // version ot the data partition doesn't, In this case skip the permission.
@@ -1288,7 +1092,7 @@
                             pkg.packageName, permission, userId, false);
                     if (DEBUG) {
                         Log.i(TAG, "Granted " + (systemFixed ? "fixed " : "not fixed ")
-                                + permission + " to default handler " + pkg.packageName);
+                                + permission + " to default handler " + pkg);
                     }
 
                     int newFlags = PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT;
@@ -1307,7 +1111,7 @@
                         && !systemFixed) {
                     if (DEBUG) {
                         Log.i(TAG, "Granted not fixed " + permission + " to default handler "
-                                + pkg.packageName);
+                                + pkg);
                     }
                     mServiceInternal.updatePermissionFlagsTEMP(permission, pkg.packageName,
                             PackageManager.FLAG_PERMISSION_SYSTEM_FIXED, 0, userId);
@@ -1316,28 +1120,42 @@
         }
     }
 
-    private boolean isSysComponentOrPersistentPlatformSignedPrivApp(PackageParser.Package pkg) {
+    private PackageInfo getSystemPackageInfo(String pkg) {
+        //TODO not MATCH_SYSTEM_ONLY?
+        return getPackageInfo(pkg, PackageManager.MATCH_FACTORY_ONLY);
+    }
+
+    private PackageInfo getPackageInfo(String pkg) {
+        return getPackageInfo(pkg, 0 /* extraFlags */);
+    }
+
+    private PackageInfo getPackageInfo(String pkg,
+            @PackageManager.PackageInfoFlags int extraFlags) {
+        return mServiceInternal.getPackageInfo(pkg,
+                DEFAULT_PACKAGE_INFO_QUERY_FLAGS | extraFlags,
+                //TODO is this the right filterCallingUid?
+                UserHandle.USER_SYSTEM, UserHandle.USER_SYSTEM);
+    }
+
+    private boolean isSysComponentOrPersistentPlatformSignedPrivApp(PackageInfo pkg) {
         if (UserHandle.getAppId(pkg.applicationInfo.uid) < FIRST_APPLICATION_UID) {
             return true;
         }
-        if (!pkg.isPrivileged()) {
+        if (!pkg.applicationInfo.isPrivilegedApp()) {
             return false;
         }
-        final PackageParser.Package disabledPkg =
-                mServiceInternal.getDisabledPackage(pkg.packageName);
+        final PackageInfo disabledPkg = getSystemPackageInfo(
+                mServiceInternal.getDisabledSystemPackageName(pkg.applicationInfo.packageName));
         if (disabledPkg != null) {
-            if ((disabledPkg.applicationInfo.flags & ApplicationInfo.FLAG_PERSISTENT) == 0) {
+            ApplicationInfo disabledPackageAppInfo = disabledPkg.applicationInfo;
+            if (disabledPackageAppInfo != null
+                    && (disabledPackageAppInfo.flags & ApplicationInfo.FLAG_PERSISTENT) == 0) {
                 return false;
             }
         } else if ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_PERSISTENT) == 0) {
             return false;
         }
-        final String systemPackageName = mServiceInternal.getKnownPackageName(
-                PackageManagerInternal.PACKAGE_SYSTEM, UserHandle.USER_SYSTEM);
-        final PackageParser.Package systemPackage = getPackage(systemPackageName);
-        return pkg.mSigningDetails.hasAncestorOrSelf(systemPackage.mSigningDetails)
-                || systemPackage.mSigningDetails.checkCapability(pkg.mSigningDetails,
-                        PackageParser.SigningDetails.CertCapabilities.PERMISSION);
+        return mServiceInternal.isPlatformSigned(pkg.packageName);
     }
 
     private void grantDefaultPermissionExceptions(int userId) {
@@ -1357,7 +1175,7 @@
         final int exceptionCount = mGrantExceptions.size();
         for (int i = 0; i < exceptionCount; i++) {
             String packageName = mGrantExceptions.keyAt(i);
-            PackageParser.Package pkg = getSystemPackage(packageName);
+            PackageInfo pkg = getSystemPackageInfo(packageName);
             List<DefaultPermissionGrant> permissionGrants = mGrantExceptions.valueAt(i);
             final int permissionGrantCount = permissionGrants.size();
             for (int j = 0; j < permissionGrantCount; j++) {
@@ -1368,8 +1186,7 @@
                     permissions.clear();
                 }
                 permissions.add(permissionGrant.name);
-                grantRuntimePermissions(pkg, permissions,
-                        permissionGrant.fixed, userId);
+                grantRuntimePermissions(pkg, permissions, permissionGrant.fixed, userId);
             }
         }
     }
@@ -1474,15 +1291,14 @@
                         outGrantExceptions.get(packageName);
                 if (packageExceptions == null) {
                     // The package must be on the system image
-                    PackageParser.Package pkg = getSystemPackage(packageName);
-                    if (pkg == null) {
+                    if (!isSystemPackage(packageName)) {
                         Log.w(TAG, "Unknown package:" + packageName);
                         XmlUtils.skipCurrentTag(parser);
                         continue;
                     }
 
                     // The package must support runtime permissions
-                    if (!doesPackageSupportRuntimePermissions(pkg)) {
+                    if (!doesPackageSupportRuntimePermissions(getSystemPackageInfo(packageName))) {
                         Log.w(TAG, "Skipping non supporting runtime permissions package:"
                                 + packageName);
                         XmlUtils.skipCurrentTag(parser);
@@ -1527,8 +1343,9 @@
         }
     }
 
-    private static boolean doesPackageSupportRuntimePermissions(PackageParser.Package pkg) {
-        return pkg.applicationInfo.targetSdkVersion > Build.VERSION_CODES.LOLLIPOP_MR1;
+    private static boolean doesPackageSupportRuntimePermissions(PackageInfo pkg) {
+        return pkg.applicationInfo != null
+                && pkg.applicationInfo.targetSdkVersion > Build.VERSION_CODES.LOLLIPOP_MR1;
     }
 
     private static final class DefaultPermissionGrant {
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index c4f90a12..4b6760c 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -1189,7 +1189,7 @@
                 // is granted only if it had been defined by the original application.
                 if (pkg.isUpdatedSystemApp()) {
                     final PackageParser.Package disabledPkg =
-                            mPackageManagerInt.getDisabledPackage(pkg.packageName);
+                            mPackageManagerInt.getDisabledSystemPackage(pkg.packageName);
                     final PackageSetting disabledPs =
                             (disabledPkg != null) ? (PackageSetting) disabledPkg.mExtras : null;
                     if (disabledPs != null
@@ -1221,7 +1221,7 @@
                         // packages can also get the permission.
                         if (pkg.parentPackage != null) {
                             final PackageParser.Package disabledParentPkg = mPackageManagerInt
-                                    .getDisabledPackage(pkg.parentPackage.packageName);
+                                    .getDisabledSystemPackage(pkg.parentPackage.packageName);
                             final PackageSetting disabledParentPs = (disabledParentPkg != null)
                                     ? (PackageSetting) disabledParentPkg.mExtras : null;
                             if (disabledParentPkg != null
@@ -1372,7 +1372,7 @@
             return;
         }
         final PackageParser.Package disabledPkg =
-                mPackageManagerInt.getDisabledPackage(pkg.parentPackage.packageName);
+                mPackageManagerInt.getDisabledSystemPackage(pkg.parentPackage.packageName);
         if (disabledPkg == null || disabledPkg.mExtras == null) {
             return;
         }
diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java
index 6f9d803..2091899 100644
--- a/services/core/java/com/android/server/stats/StatsCompanionService.java
+++ b/services/core/java/com/android/server/stats/StatsCompanionService.java
@@ -44,6 +44,8 @@
 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,6 +55,7 @@
 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;
@@ -169,6 +172,8 @@
     private KernelUidCpuClusterTimeReader mKernelUidCpuClusterTimeReader =
             new KernelUidCpuClusterTimeReader();
 
+    private static IThermalService sThermalService;
+
     public StatsCompanionService(Context context) {
         super();
         mContext = context;
@@ -213,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
@@ -906,6 +929,7 @@
         }
 
         List<ExportedCallStat> callStats = binderStats.getExportedCallStats();
+        binderStats.reset();
         long elapsedNanos = SystemClock.elapsedRealtimeNanos();
         for (ExportedCallStat callStat : callStats) {
             StatsLogEventWrapper e = new StatsLogEventWrapper(elapsedNanos, tagId, 13 /* fields */);
@@ -934,6 +958,8 @@
         }
 
         ArrayMap<String, Integer> exceptionStats = binderStats.getExportedExceptionStats();
+        // TODO: decouple binder calls exceptions with the rest of the binder calls data so that we
+        // can reset the exception stats.
         long elapsedNanos = SystemClock.elapsedRealtimeNanos();
         for (Entry<String, Integer> entry : exceptionStats.entrySet()) {
             StatsLogEventWrapper e = new StatsLogEventWrapper(elapsedNanos, tagId, 2 /* fields */);
@@ -1456,4 +1482,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 14294ec..c2d8188 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -566,6 +566,7 @@
 
     @Override
     public void showBiometricDialog(Bundle bundle, IBiometricPromptReceiver receiver, int type) {
+        enforceBiometricDialog();
         if (mBar != null) {
             try {
                 mBar.showBiometricDialog(bundle, receiver, type);
@@ -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/telecom/TelecomLoaderService.java b/services/core/java/com/android/server/telecom/TelecomLoaderService.java
index 6c5452a..7a3f030 100644
--- a/services/core/java/com/android/server/telecom/TelecomLoaderService.java
+++ b/services/core/java/com/android/server/telecom/TelecomLoaderService.java
@@ -22,7 +22,6 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.ServiceConnection;
-import android.content.pm.PackageManagerInternal;
 import android.database.ContentObserver;
 import android.net.Uri;
 import android.os.Handler;
@@ -39,12 +38,13 @@
 import android.util.IntArray;
 import android.util.Slog;
 
-import android.util.SparseBooleanArray;
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.telephony.SmsApplication;
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
 import com.android.server.pm.UserManagerService;
+import com.android.server.pm.permission.DefaultPermissionGrantPolicy;
+import com.android.server.pm.permission.PermissionManagerInternal;
 
 /**
  * Starts the telecom component by binding to its ITelecomService implementation. Telecom is setup
@@ -72,8 +72,8 @@
                 synchronized (mLock) {
                     if (mDefaultSmsAppRequests != null || mDefaultDialerAppRequests != null
                             || mDefaultSimCallManagerRequests != null) {
-                        final PackageManagerInternal packageManagerInternal = LocalServices
-                                .getService(PackageManagerInternal.class);
+                        final DefaultPermissionGrantPolicy permissionPolicy =
+                                getDefaultPermissionGrantPolicy();
 
                         if (mDefaultSmsAppRequests != null) {
                             ComponentName smsComponent = SmsApplication.getDefaultSmsApplication(
@@ -83,7 +83,7 @@
                                 for (int i = requestCount - 1; i >= 0; i--) {
                                     final int userid = mDefaultSmsAppRequests.get(i);
                                     mDefaultSmsAppRequests.remove(i);
-                                    packageManagerInternal.grantDefaultPermissionsToDefaultSmsApp(
+                                    permissionPolicy.grantDefaultPermissionsToDefaultSmsApp(
                                             smsComponent.getPackageName(), userid);
                                 }
                             }
@@ -97,7 +97,7 @@
                                 for (int i = requestCount - 1; i >= 0; i--) {
                                     final int userId = mDefaultDialerAppRequests.get(i);
                                     mDefaultDialerAppRequests.remove(i);
-                                    packageManagerInternal.grantDefaultPermissionsToDefaultDialerApp(
+                                    permissionPolicy.grantDefaultPermissionsToDefaultDialerApp(
                                             packageName, userId);
                                 }
                             }
@@ -113,7 +113,7 @@
                                 for (int i = requestCount - 1; i >= 0; i--) {
                                     final int userId = mDefaultSimCallManagerRequests.get(i);
                                     mDefaultSimCallManagerRequests.remove(i);
-                                    packageManagerInternal
+                                    permissionPolicy
                                             .grantDefaultPermissionsToDefaultSimCallManager(
                                                     packageName, userId);
                                 }
@@ -132,6 +132,11 @@
         }
     }
 
+    private DefaultPermissionGrantPolicy getDefaultPermissionGrantPolicy() {
+        return LocalServices.getService(PermissionManagerInternal.class)
+                .getDefaultPermissionGrantPolicy();
+    }
+
     private static final ComponentName SERVICE_COMPONENT = new ComponentName(
             "com.android.server.telecom",
             "com.android.server.telecom.components.TelecomService");
@@ -196,82 +201,68 @@
 
 
     private void registerDefaultAppProviders() {
-        final PackageManagerInternal packageManagerInternal = LocalServices.getService(
-                PackageManagerInternal.class);
+        final DefaultPermissionGrantPolicy permissionPolicy = getDefaultPermissionGrantPolicy();
 
-        // Set a callback for the package manager to query the default sms app.
-        packageManagerInternal.setSmsAppPackagesProvider(
-                new PackageManagerInternal.PackagesProvider() {
-            @Override
-            public String[] getPackages(int userId) {
-                synchronized (mLock) {
-                    if (mServiceConnection == null) {
-                        if (mDefaultSmsAppRequests == null) {
-                            mDefaultSmsAppRequests = new IntArray();
-                        }
-                        mDefaultSmsAppRequests.add(userId);
-                        return null;
+        // Set a callback for the permission grant policy to query the default sms app.
+        permissionPolicy.setSmsAppPackagesProvider(userId -> {
+            synchronized (mLock) {
+                if (mServiceConnection == null) {
+                    if (mDefaultSmsAppRequests == null) {
+                        mDefaultSmsAppRequests = new IntArray();
                     }
+                    mDefaultSmsAppRequests.add(userId);
+                    return null;
                 }
-                ComponentName smsComponent = SmsApplication.getDefaultSmsApplication(
-                        mContext, true);
-                if (smsComponent != null) {
-                    return new String[]{smsComponent.getPackageName()};
-                }
-                return null;
             }
+            ComponentName smsComponent = SmsApplication.getDefaultSmsApplication(
+                    mContext, true);
+            if (smsComponent != null) {
+                return new String[]{smsComponent.getPackageName()};
+            }
+            return null;
         });
 
-        // Set a callback for the package manager to query the default dialer app.
-        packageManagerInternal.setDialerAppPackagesProvider(
-                new PackageManagerInternal.PackagesProvider() {
-            @Override
-            public String[] getPackages(int userId) {
-                synchronized (mLock) {
-                    if (mServiceConnection == null) {
-                        if (mDefaultDialerAppRequests == null) {
-                            mDefaultDialerAppRequests = new IntArray();
-                        }
-                        mDefaultDialerAppRequests.add(userId);
-                        return null;
+        // Set a callback for the permission grant policy to query the default dialer app.
+        permissionPolicy.setDialerAppPackagesProvider(userId -> {
+            synchronized (mLock) {
+                if (mServiceConnection == null) {
+                    if (mDefaultDialerAppRequests == null) {
+                        mDefaultDialerAppRequests = new IntArray();
                     }
+                    mDefaultDialerAppRequests.add(userId);
+                    return null;
                 }
-                String packageName = DefaultDialerManager.getDefaultDialerApplication(mContext);
-                if (packageName != null) {
-                    return new String[]{packageName};
-                }
-                return null;
             }
+            String packageName = DefaultDialerManager.getDefaultDialerApplication(mContext);
+            if (packageName != null) {
+                return new String[]{packageName};
+            }
+            return null;
         });
 
-        // Set a callback for the package manager to query the default sim call manager.
-        packageManagerInternal.setSimCallManagerPackagesProvider(
-                new PackageManagerInternal.PackagesProvider() {
-            @Override
-            public String[] getPackages(int userId) {
-                synchronized (mLock) {
-                    if (mServiceConnection == null) {
-                        if (mDefaultSimCallManagerRequests == null) {
-                            mDefaultSimCallManagerRequests = new IntArray();
-                        }
-                        mDefaultSimCallManagerRequests.add(userId);
-                        return null;
+        // Set a callback for the permission grant policy to query the default sim call manager.
+        permissionPolicy.setSimCallManagerPackagesProvider(userId -> {
+            synchronized (mLock) {
+                if (mServiceConnection == null) {
+                    if (mDefaultSimCallManagerRequests == null) {
+                        mDefaultSimCallManagerRequests = new IntArray();
                     }
+                    mDefaultSimCallManagerRequests.add(userId);
+                    return null;
                 }
-                TelecomManager telecomManager =
+            }
+            TelecomManager telecomManager =
                     (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
-                PhoneAccountHandle phoneAccount = telecomManager.getSimCallManager(userId);
-                if (phoneAccount != null) {
-                    return new String[]{phoneAccount.getComponentName().getPackageName()};
-                }
-                return null;
+            PhoneAccountHandle phoneAccount = telecomManager.getSimCallManager(userId);
+            if (phoneAccount != null) {
+                return new String[]{phoneAccount.getComponentName().getPackageName()};
             }
+            return null;
         });
     }
 
     private void registerDefaultAppNotifier() {
-        final PackageManagerInternal packageManagerInternal = LocalServices.getService(
-                PackageManagerInternal.class);
+        final DefaultPermissionGrantPolicy permissionPolicy = getDefaultPermissionGrantPolicy();
 
         // Notify the package manager on default app changes
         final Uri defaultSmsAppUri = Settings.Secure.getUriFor(
@@ -287,17 +278,17 @@
                     ComponentName smsComponent = SmsApplication.getDefaultSmsApplication(
                             mContext, true);
                     if (smsComponent != null) {
-                        packageManagerInternal.grantDefaultPermissionsToDefaultSmsApp(
+                        permissionPolicy.grantDefaultPermissionsToDefaultSmsApp(
                                 smsComponent.getPackageName(), userId);
                     }
                 } else if (defaultDialerAppUri.equals(uri)) {
                     String packageName = DefaultDialerManager.getDefaultDialerApplication(
                             mContext);
                     if (packageName != null) {
-                        packageManagerInternal.grantDefaultPermissionsToDefaultDialerApp(
+                        permissionPolicy.grantDefaultPermissionsToDefaultDialerApp(
                                 packageName, userId);
                     }
-                    updateSimCallManagerPermissions(packageManagerInternal, userId);
+                    updateSimCallManagerPermissions(permissionPolicy, userId);
                 }
             }
         };
@@ -310,14 +301,12 @@
 
 
     private void registerCarrierConfigChangedReceiver() {
-        final PackageManagerInternal packageManagerInternal = LocalServices.getService(
-                PackageManagerInternal.class);
         BroadcastReceiver receiver = new BroadcastReceiver() {
             @Override
             public void onReceive(Context context, Intent intent) {
                 if (intent.getAction().equals(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED)) {
                     for (int userId : UserManagerService.getInstance().getUserIds()) {
-                        updateSimCallManagerPermissions(packageManagerInternal, userId);
+                        updateSimCallManagerPermissions(getDefaultPermissionGrantPolicy(), userId);
                     }
                 }
             }
@@ -327,15 +316,15 @@
             new IntentFilter(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED), null, null);
     }
 
-    private void updateSimCallManagerPermissions(PackageManagerInternal packageManagerInternal,
-            int userId) {
+    private void updateSimCallManagerPermissions(
+            DefaultPermissionGrantPolicy permissionGrantPolicy, int userId) {
         TelecomManager telecomManager =
             (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
         PhoneAccountHandle phoneAccount = telecomManager.getSimCallManager(userId);
         if (phoneAccount != null) {
             Slog.i(TAG, "updating sim call manager permissions for userId:" + userId);
             String packageName = phoneAccount.getComponentName().getPackageName();
-            packageManagerInternal.grantDefaultPermissionsToDefaultSimCallManager(
+            permissionGrantPolicy.grantDefaultPermissionsToDefaultSimCallManager(
                 packageName, userId);
         }
     }
diff --git a/core/java/com/android/internal/textservice/LazyIntToIntMap.java b/services/core/java/com/android/server/textservices/LazyIntToIntMap.java
similarity index 91%
rename from core/java/com/android/internal/textservice/LazyIntToIntMap.java
rename to services/core/java/com/android/server/textservices/LazyIntToIntMap.java
index ca9936c..2e7f2a9 100644
--- a/core/java/com/android/internal/textservice/LazyIntToIntMap.java
+++ b/services/core/java/com/android/server/textservices/LazyIntToIntMap.java
@@ -14,21 +14,18 @@
  * limitations under the License.
  */
 
-package com.android.internal.textservice;
+package com.android.server.textservices;
 
 import android.annotation.NonNull;
 import android.util.SparseIntArray;
 
-import com.android.internal.annotations.VisibleForTesting;
-
 import java.util.function.IntUnaryOperator;
 
 /**
  * Simple int-to-int key-value-store that is to be lazily initialized with the given
  * {@link IntUnaryOperator}.
  */
-@VisibleForTesting
-public final class LazyIntToIntMap {
+final class LazyIntToIntMap {
 
     private final SparseIntArray mMap = new SparseIntArray();
 
diff --git a/services/core/java/com/android/server/textservices/LocaleUtils.java b/services/core/java/com/android/server/textservices/LocaleUtils.java
new file mode 100644
index 0000000..89d8c1e
--- /dev/null
+++ b/services/core/java/com/android/server/textservices/LocaleUtils.java
@@ -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.
+ */
+
+package com.android.server.textservices;
+
+import android.annotation.Nullable;
+import android.text.TextUtils;
+
+import java.util.ArrayList;
+import java.util.Locale;
+
+/**
+ * Provides {@code Locale} related utility methods for {@link TextServicesManagerService}.
+ * <p>This class is intentionally package-private.  Utility methods here are tightly coupled with
+ * implementation details in {@link TextServicesManagerService}.  Hence this class is not suitable
+ * for other components to directly use.</p>
+ */
+final class LocaleUtils {
+    /**
+     * Returns a list of {@link Locale} in the order of appropriateness for the default spell
+     * checker service.
+     *
+     * <p>If the system language is English, and the region is also explicitly specified in the
+     * system locale, the following fallback order will be applied.</p>
+     * <ul>
+     * <li>(system-locale-language, system-locale-region, system-locale-variant) (if exists)</li>
+     * <li>(system-locale-language, system-locale-region)</li>
+     * <li>("en", "US")</li>
+     * <li>("en", "GB")</li>
+     * <li>("en")</li>
+     * </ul>
+     *
+     * <p>If the system language is English, but no region is specified in the system locale,
+     * the following fallback order will be applied.</p>
+     * <ul>
+     * <li>("en")</li>
+     * <li>("en", "US")</li>
+     * <li>("en", "GB")</li>
+     * </ul>
+     *
+     * <p>If the system language is not English, the following fallback order will be applied.</p>
+     * <ul>
+     * <li>(system-locale-language, system-locale-region, system-locale-variant) (if exists)</li>
+     * <li>(system-locale-language, system-locale-region) (if exists)</li>
+     * <li>(system-locale-language) (if exists)</li>
+     * <li>("en", "US")</li>
+     * <li>("en", "GB")</li>
+     * <li>("en")</li>
+     * </ul>
+     *
+     * @param systemLocale the current system locale to be taken into consideration.
+     * @return a list of {@link Locale}. The first one is considered to be most appropriate.
+     */
+    public static ArrayList<Locale> getSuitableLocalesForSpellChecker(
+            @Nullable final Locale systemLocale) {
+        final Locale systemLocaleLanguageCountryVariant;
+        final Locale systemLocaleLanguageCountry;
+        final Locale systemLocaleLanguage;
+        if (systemLocale != null) {
+            final String language = systemLocale.getLanguage();
+            final boolean hasLanguage = !TextUtils.isEmpty(language);
+            final String country = systemLocale.getCountry();
+            final boolean hasCountry = !TextUtils.isEmpty(country);
+            final String variant = systemLocale.getVariant();
+            final boolean hasVariant = !TextUtils.isEmpty(variant);
+            if (hasLanguage && hasCountry && hasVariant) {
+                systemLocaleLanguageCountryVariant = new Locale(language, country, variant);
+            } else {
+                systemLocaleLanguageCountryVariant = null;
+            }
+            if (hasLanguage && hasCountry) {
+                systemLocaleLanguageCountry = new Locale(language, country);
+            } else {
+                systemLocaleLanguageCountry = null;
+            }
+            if (hasLanguage) {
+                systemLocaleLanguage = new Locale(language);
+            } else {
+                systemLocaleLanguage = null;
+            }
+        } else {
+            systemLocaleLanguageCountryVariant = null;
+            systemLocaleLanguageCountry = null;
+            systemLocaleLanguage = null;
+        }
+
+        final ArrayList<Locale> locales = new ArrayList<>();
+        if (systemLocaleLanguageCountryVariant != null) {
+            locales.add(systemLocaleLanguageCountryVariant);
+        }
+
+        if (Locale.ENGLISH.equals(systemLocaleLanguage)) {
+            if (systemLocaleLanguageCountry != null) {
+                // If the system language is English, and the region is also explicitly specified,
+                // following fallback order will be applied.
+                // - systemLocaleLanguageCountry [if systemLocaleLanguageCountry is non-null]
+                // - en_US [if systemLocaleLanguageCountry is non-null and not en_US]
+                // - en_GB [if systemLocaleLanguageCountry is non-null and not en_GB]
+                // - en
+                if (systemLocaleLanguageCountry != null) {
+                    locales.add(systemLocaleLanguageCountry);
+                }
+                if (!Locale.US.equals(systemLocaleLanguageCountry)) {
+                    locales.add(Locale.US);
+                }
+                if (!Locale.UK.equals(systemLocaleLanguageCountry)) {
+                    locales.add(Locale.UK);
+                }
+                locales.add(Locale.ENGLISH);
+            } else {
+                // If the system language is English, but no region is specified, following
+                // fallback order will be applied.
+                // - en
+                // - en_US
+                // - en_GB
+                locales.add(Locale.ENGLISH);
+                locales.add(Locale.US);
+                locales.add(Locale.UK);
+            }
+        } else {
+            // If the system language is not English, the fallback order will be
+            // - systemLocaleLanguageCountry  [if non-null]
+            // - systemLocaleLanguage  [if non-null]
+            // - en_US
+            // - en_GB
+            // - en
+            if (systemLocaleLanguageCountry != null) {
+                locales.add(systemLocaleLanguageCountry);
+            }
+            if (systemLocaleLanguage != null) {
+                locales.add(systemLocaleLanguage);
+            }
+            locales.add(Locale.US);
+            locales.add(Locale.UK);
+            locales.add(Locale.ENGLISH);
+        }
+        return locales;
+    }
+}
diff --git a/services/core/java/com/android/server/TextServicesManagerService.java b/services/core/java/com/android/server/textservices/TextServicesManagerService.java
similarity index 98%
rename from services/core/java/com/android/server/TextServicesManagerService.java
rename to services/core/java/com/android/server/textservices/TextServicesManagerService.java
index 40f81b3..23c29f8 100644
--- a/services/core/java/com/android/server/TextServicesManagerService.java
+++ b/services/core/java/com/android/server/textservices/TextServicesManagerService.java
@@ -14,21 +14,21 @@
  * limitations under the License.
  */
 
-package com.android.server;
+package com.android.server.textservices;
 
 import static android.view.textservice.TextServicesManager.DISABLE_PER_PROFILE_SPELL_CHECKER;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.content.PackageMonitor;
-import com.android.internal.inputmethod.InputMethodUtils;
+import com.android.internal.inputmethod.SubtypeLocaleUtils;
 import com.android.internal.textservice.ISpellCheckerService;
 import com.android.internal.textservice.ISpellCheckerServiceCallback;
 import com.android.internal.textservice.ISpellCheckerSession;
 import com.android.internal.textservice.ISpellCheckerSessionListener;
 import com.android.internal.textservice.ITextServicesManager;
 import com.android.internal.textservice.ITextServicesSessionListener;
-import com.android.internal.textservice.LazyIntToIntMap;
 import com.android.internal.util.DumpUtils;
+import com.android.server.SystemService;
 
 import org.xmlpull.v1.XmlPullParserException;
 
@@ -461,7 +461,7 @@
         // is pre-installed or not.
         final Locale systemLocal = mContext.getResources().getConfiguration().locale;
         final ArrayList<Locale> suitableLocales =
-                InputMethodUtils.getSuitableLocalesForSpellChecker(systemLocal);
+                LocaleUtils.getSuitableLocalesForSpellChecker(systemLocal);
         if (DBG) {
             Slog.w(TAG, "findAvailSystemSpellCheckerLocked suitableLocales="
                     + Arrays.toString(suitableLocales.toArray(new Locale[suitableLocales.size()])));
@@ -475,7 +475,7 @@
                 final int subtypeCount = info.getSubtypeCount();
                 for (int subtypeIndex = 0; subtypeIndex < subtypeCount; ++subtypeIndex) {
                     final SpellCheckerSubtype subtype = info.getSubtypeAt(subtypeIndex);
-                    final Locale subtypeLocale = InputMethodUtils.constructLocaleFromString(
+                    final Locale subtypeLocale = SubtypeLocaleUtils.constructLocaleFromString(
                             subtype.getLocale());
                     if (locale.equals(subtypeLocale)) {
                         // TODO: We may have more spell checkers that fall into this category.
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 5d0101f..ac65826 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -3606,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/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index 3309798..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);
             }
         }
 
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/WindowFrames.java b/services/core/java/com/android/server/wm/WindowFrames.java
index 9381fc6..cbe7d9d 100644
--- a/services/core/java/com/android/server/wm/WindowFrames.java
+++ b/services/core/java/com/android/server/wm/WindowFrames.java
@@ -286,8 +286,9 @@
         boolean overrideBottomInset = !windowsAreFloating && !inFullscreenContainer
                 && mFrame.bottom > windowBounds.bottom;
 
-        mTmpRect.set(mFrame.left, mFrame.top, overrideRightInset ? mTmpRect.right : mFrame.right,
-                overrideBottomInset ? mTmpRect.bottom : mFrame.bottom);
+        mTmpRect.set(mFrame.left, mFrame.top,
+                overrideRightInset ? windowBounds.right : mFrame.right,
+                overrideBottomInset ? windowBounds.bottom : mFrame.bottom);
 
         InsetUtils.insetsBetweenFrames(mTmpRect, mContentFrame, mContentInsets);
         InsetUtils.insetsBetweenFrames(mTmpRect, mVisibleFrame, mVisibleInsets);
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index bb08345..9d63305 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -118,6 +118,7 @@
 import com.android.server.storage.DeviceStorageMonitorService;
 import com.android.server.telecom.TelecomLoaderService;
 import com.android.server.textclassifier.TextClassificationManagerService;
+import com.android.server.textservices.TextServicesManagerService;
 import com.android.server.trust.TrustManagerService;
 import com.android.server.tv.TvInputManagerService;
 import com.android.server.tv.TvRemoteService;
@@ -797,6 +798,9 @@
         boolean isWatch = context.getPackageManager().hasSystemFeature(
                 PackageManager.FEATURE_WATCH);
 
+        boolean enableVrService = context.getPackageManager().hasSystemFeature(
+                PackageManager.FEATURE_VR_MODE_HIGH_PERFORMANCE);
+
         // For debugging RescueParty
         if (Build.IS_DEBUGGABLE && SystemProperties.getBoolean("debug.crash_system", false)) {
             throw new RuntimeException();
@@ -930,7 +934,7 @@
                 traceLog.traceEnd();
             }, START_HIDL_SERVICES);
 
-            if (!isWatch) {
+            if (!isWatch && enableVrService) {
                 traceBeginAndSlog("StartVrManagerService");
                 mSystemServiceManager.startService(VrManagerService.class);
                 traceEnd();
diff --git a/services/net/java/android/net/ip/IpServer.java b/services/net/java/android/net/ip/IpServer.java
index 33010a1..823c0a1 100644
--- a/services/net/java/android/net/ip/IpServer.java
+++ b/services/net/java/android/net/ip/IpServer.java
@@ -430,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;
 
@@ -549,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 =
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityGestureDetectorTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityGestureDetectorTest.java
index 1c025cf..aad7230 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityGestureDetectorTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityGestureDetectorTest.java
@@ -18,23 +18,22 @@
 
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.when;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 import android.accessibilityservice.AccessibilityService;
 import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.Point;
 import android.graphics.PointF;
-import android.os.Looper;
 import android.util.DisplayMetrics;
 import android.view.GestureDetector;
 import android.view.MotionEvent;
-import java.util.ArrayList;
+
 import org.junit.Before;
-import org.junit.BeforeClass;
 import org.junit.Test;
 
+import java.util.ArrayList;
 
 /**
  * Tests for AccessibilityGestureDetector
@@ -50,14 +49,6 @@
     private AccessibilityGestureDetector mDetector;
     private AccessibilityGestureDetector.Listener mResultListener;
 
-
-    @BeforeClass
-    public static void oneTimeInitialization() {
-        if (Looper.myLooper() == null) {
-            Looper.prepare();
-        }
-    }
-
     @Before
     public void setUp() {
         // Construct a mock Context.
@@ -67,7 +58,6 @@
         Resources mockResources = mock(Resources.class);
         when(mockResources.getDisplayMetrics()).thenReturn(displayMetricsMock);
         Context contextMock = mock(Context.class);
-        when(contextMock.getMainLooper()).thenReturn(Looper.myLooper());
         when(contextMock.getResources()).thenReturn(mockResources);
 
         // Construct a testable AccessibilityGestureDetector.
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerTest.java
index 4c0f38a..b9b6d55 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerTest.java
@@ -29,7 +29,6 @@
 
 import android.accessibilityservice.AccessibilityServiceInfo;
 import android.app.Instrumentation;
-import android.os.Looper;
 import android.os.UserHandle;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityManager;
@@ -41,8 +40,8 @@
 
 import com.android.internal.util.IntPair;
 
+import org.junit.After;
 import org.junit.Before;
-import org.junit.BeforeClass;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
@@ -63,13 +62,6 @@
     private MessageCapturingHandler mHandler;
     private Instrumentation mInstrumentation;
 
-    @BeforeClass
-    public static void oneTimeInitialization() {
-        if (Looper.myLooper() == null) {
-            Looper.prepare();
-        }
-    }
-
     @Before
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
@@ -77,6 +69,12 @@
         mInstrumentation = InstrumentationRegistry.getInstrumentation();
     }
 
+    @After
+    public void tearDown() {
+        mHandler.removeAllMessages();
+    }
+
+
     private AccessibilityManager createManager(boolean enabled) throws Exception {
         long serviceReturnValue = IntPair.of(
                 (enabled) ? AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED : 0,
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityServiceConnectionTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityServiceConnectionTest.java
index 412e844..66d9345 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityServiceConnectionTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityServiceConnectionTest.java
@@ -33,16 +33,14 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
-import android.os.Handler;
 import android.os.IBinder;
-import android.os.Looper;
 import android.os.RemoteException;
 import android.os.UserHandle;
 
 import com.android.server.wm.WindowManagerInternal;
 
+import org.junit.After;
 import org.junit.Before;
-import org.junit.BeforeClass;
 import org.junit.Test;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
@@ -74,13 +72,6 @@
 
     MessageCapturingHandler mHandler = new MessageCapturingHandler(null);
 
-    @BeforeClass
-    public static void oneTimeInitialization() {
-        if (Looper.myLooper() == null) {
-            Looper.prepare();
-        }
-    }
-
     @Before
     public void setup() {
         MockitoAnnotations.initMocks(this);
@@ -98,6 +89,12 @@
                 mMockGlobalActionPerformer);
     }
 
+    @After
+    public void tearDown() {
+        mHandler.removeAllMessages();
+    }
+
+
     @Test
     public void bind_requestsContextToBindService() {
         mConnection.bindLocked();
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 a3decb9..44a514f 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/FingerprintGestureControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/FingerprintGestureControllerTest.java
@@ -16,19 +16,8 @@
 
 package com.android.server.accessibility;
 
-import android.accessibilityservice.FingerprintGestureController;
-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;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-import static android.accessibilityservice.FingerprintGestureController.FINGERPRINT_GESTURE_SWIPE_DOWN;
+import static android.accessibilityservice.FingerprintGestureController
+        .FINGERPRINT_GESTURE_SWIPE_DOWN;
 
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
@@ -38,6 +27,15 @@
 import static org.mockito.Mockito.verifyZeroInteractions;
 import static org.mockito.Mockito.when;
 
+import android.accessibilityservice.FingerprintGestureController;
+import android.accessibilityservice.FingerprintGestureController.FingerprintGestureCallback;
+import android.accessibilityservice.IAccessibilityServiceConnection;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
 /**
  * Tests for FingerprintGestureController.
  * TODO: These tests aren't really for server code, so this isn't their ideal home.
@@ -47,13 +45,6 @@
     @Mock FingerprintGestureCallback mMockFingerprintGestureCallback;
     FingerprintGestureController mFingerprintGestureController;
 
-    @BeforeClass
-    public static void oneTimeInitialization() {
-        if (Looper.myLooper() == null) {
-            Looper.prepare();
-        }
-    }
-
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
@@ -97,7 +88,6 @@
     }
 
     @Test
-    @FlakyTest
     public void testDetectionActiveCallback_withHandler_shouldPostRunnableToHandler() {
         MessageCapturingHandler messageCapturingHandler = new MessageCapturingHandler((message) -> {
             message.getCallback().run();
@@ -127,6 +117,8 @@
         mFingerprintGestureController.onGestureDetectionActiveChanged(false);
         assertFalse(messageCapturingHandler.hasMessages());
         verifyZeroInteractions(mMockFingerprintGestureCallback);
+
+        messageCapturingHandler.removeAllMessages();
     }
 
     @Test
@@ -145,7 +137,6 @@
     }
 
     @Test
-    @FlakyTest
     public void testGestureCallback_withHandler_shouldPostRunnableToHandler() {
         MessageCapturingHandler messageCapturingHandler = new MessageCapturingHandler((message) -> {
             message.getCallback().run();
@@ -167,5 +158,7 @@
         mFingerprintGestureController.onGesture(FINGERPRINT_GESTURE_SWIPE_DOWN);
         assertFalse(messageCapturingHandler.hasMessages());
         verifyZeroInteractions(mMockFingerprintGestureCallback);
+
+        messageCapturingHandler.removeAllMessages();
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/FingerprintGestureDispatcherTest.java b/services/tests/servicestests/src/com/android/server/accessibility/FingerprintGestureDispatcherTest.java
index 6ce7bbe..de7bc44 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/FingerprintGestureDispatcherTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/FingerprintGestureDispatcherTest.java
@@ -16,25 +16,6 @@
 
 package com.android.server.accessibility;
 
-import android.accessibilityservice.FingerprintGestureController;
-import android.content.res.Resources;
-import android.hardware.fingerprint.IFingerprintService;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.view.KeyEvent;
-
-import com.android.server.accessibility.FingerprintGestureDispatcher.FingerprintGestureClient;
-
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-import java.util.Arrays;
-import java.util.Collections;
-
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.Matchers.anyBoolean;
@@ -44,6 +25,22 @@
 import static org.mockito.Mockito.verifyNoMoreInteractions;
 import static org.mockito.Mockito.when;
 
+import android.accessibilityservice.FingerprintGestureController;
+import android.content.res.Resources;
+import android.hardware.fingerprint.IFingerprintService;
+import android.view.KeyEvent;
+
+import com.android.server.accessibility.FingerprintGestureDispatcher.FingerprintGestureClient;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.Arrays;
+import java.util.Collections;
+
 /**
  * Tests for FingerprintGestureDispatcher
  */
@@ -57,13 +54,6 @@
     private MessageCapturingHandler mMessageCapturingHandler;
     private FingerprintGestureDispatcher mFingerprintGestureDispatcher;
 
-    @BeforeClass
-    public static void oneTimeInitialization() {
-        if (Looper.myLooper() == null) {
-            Looper.prepare();
-        }
-    }
-
     @Before
     public void setup() {
         MockitoAnnotations.initMocks(this);
@@ -77,6 +67,12 @@
         when(mGestureCapturingClient.isCapturingFingerprintGestures()).thenReturn(true);
     }
 
+    @After
+    public void tearDown() {
+        mMessageCapturingHandler.removeAllMessages();
+    }
+
+
     @Test
     public void testNoServices_doesNotCrashOrConsumeGestures() {
         mFingerprintGestureDispatcher.onClientActiveChanged(true);
@@ -171,7 +167,7 @@
     }
 
     @Test
-    public void ifGestureDectionNotSupported_neverSaysAvailable() throws Exception {
+    public void ifGestureDetectionNotSupported_neverSaysAvailable() throws Exception {
         when(mMockResources.getBoolean(anyInt())).thenReturn(false);
         // Need to create a new dispatcher, since it picks up the resource value in its
         // constructor. This is fine since hardware config values don't change dynamically.
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/KeyEventDispatcherTest.java b/services/tests/servicestests/src/com/android/server/accessibility/KeyEventDispatcherTest.java
index 236b458..23ce483 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/KeyEventDispatcherTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/KeyEventDispatcherTest.java
@@ -40,6 +40,7 @@
 import android.os.RemoteException;
 import android.view.KeyEvent;
 
+import androidx.test.InstrumentationRegistry;
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.server.accessibility.KeyEventDispatcher.KeyEventFilter;
@@ -47,16 +48,14 @@
 
 import org.hamcrest.Description;
 import org.hamcrest.TypeSafeMatcher;
+import org.junit.After;
 import org.junit.Before;
-import org.junit.BeforeClass;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
 
-import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
-import java.util.List;
 
 /**
  * Tests for KeyEventDispatcher
@@ -68,7 +67,7 @@
     private final KeyEvent mKeyEvent = new KeyEvent(KeyEvent.ACTION_DOWN, 0x40);
     private final KeyEvent mOtherKeyEvent = new KeyEvent(KeyEvent.ACTION_DOWN, 0x50);
     private final Object mLock = new Object();
-    private MessageCapturingHandler mInputEventsHander;
+    private MessageCapturingHandler mInputEventsHandler;
     private KeyEventDispatcher mKeyEventDispatcher;
     private KeyEventFilter mKeyEventFilter1;
     private KeyEventFilter mKeyEventFilter2;
@@ -77,23 +76,17 @@
     private ArgumentCaptor<Integer> mFilter1SequenceCaptor = ArgumentCaptor.forClass(Integer.class);
     private ArgumentCaptor<Integer> mFilter2SequenceCaptor = ArgumentCaptor.forClass(Integer.class);
 
-    @BeforeClass
-    public static void oneTimeInitialization() {
-        if (Looper.myLooper() == null) {
-            Looper.prepare();
-        }
-    }
-
     @Before
     public void setUp() {
-        mInputEventsHander = new MessageCapturingHandler();
+        Looper looper = InstrumentationRegistry.getContext().getMainLooper();
+        mInputEventsHandler = new MessageCapturingHandler(looper, null);
         mMockPowerManagerService = mock(IPowerManager.class);
         // TODO: It would be better to mock PowerManager rather than its binder, but the class is
         // final.
         PowerManager powerManager =
-                new PowerManager(mock(Context.class), mMockPowerManagerService, new Handler());
-        mMessageCapturingHandler = new MessageCapturingHandler();
-        mKeyEventDispatcher = new KeyEventDispatcher(mInputEventsHander, SEND_FRAMEWORK_KEY_EVENT,
+                new PowerManager(mock(Context.class), mMockPowerManagerService, new Handler(looper));
+        mMessageCapturingHandler = new MessageCapturingHandler(looper, null);
+        mKeyEventDispatcher = new KeyEventDispatcher(mInputEventsHandler, SEND_FRAMEWORK_KEY_EVENT,
                 mLock, powerManager, mMessageCapturingHandler);
 
         mKeyEventFilter1 = mock(KeyEventFilter.class);
@@ -107,10 +100,17 @@
                 .thenReturn(true);
     }
 
+    @After
+    public void tearDown() {
+        mInputEventsHandler.removeAllMessages();
+        mMessageCapturingHandler.removeAllMessages();
+    }
+
+
     @Test
     public void testNotifyKeyEvent_withNoBoundServices_shouldReturnFalse() {
         assertFalse(mKeyEventDispatcher.notifyKeyEventLocked(mKeyEvent, 0, Collections.EMPTY_LIST));
-        assertFalse(mMessageCapturingHandler.isTimeoutPending());
+        assertFalse(isTimeoutPending(mMessageCapturingHandler));
     }
 
     @Test
@@ -119,7 +119,7 @@
         when(keyEventFilter.onKeyEvent((KeyEvent) anyObject(), anyInt())).thenReturn(false);
         assertFalse(mKeyEventDispatcher
                 .notifyKeyEventLocked(mKeyEvent, 0, Arrays.asList(keyEventFilter)));
-        assertFalse(mMessageCapturingHandler.isTimeoutPending());
+        assertFalse(isTimeoutPending(mMessageCapturingHandler));
     }
 
     @Test
@@ -152,9 +152,9 @@
         mKeyEventDispatcher.setOnKeyEventResult(mKeyEventFilter1, false,
                 mFilter1SequenceCaptor.getValue());
 
-        assertTrue(mInputEventsHander.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
+        assertTrue(mInputEventsHandler.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
         verifyZeroInteractions(mMockPowerManagerService);
-        assertFalse(mMessageCapturingHandler.isTimeoutPending());
+        assertFalse(isTimeoutPending(mMessageCapturingHandler));
     }
 
     @Test
@@ -166,10 +166,10 @@
         mKeyEventDispatcher.setOnKeyEventResult(mKeyEventFilter1, true,
                 mFilter1SequenceCaptor.getValue());
 
-        assertFalse(mInputEventsHander.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
+        assertFalse(mInputEventsHandler.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
         verify(mMockPowerManagerService, times(1)).userActivity(anyLong(),
                 eq(PowerManager.USER_ACTIVITY_EVENT_ACCESSIBILITY), eq(0));
-        assertFalse(mMessageCapturingHandler.isTimeoutPending());
+        assertFalse(isTimeoutPending(mMessageCapturingHandler));
     }
 
     @Test
@@ -182,9 +182,9 @@
         mKeyEventDispatcher.setOnKeyEventResult(mKeyEventFilter2, false,
                 mFilter2SequenceCaptor.getValue());
 
-        assertTrue(mInputEventsHander.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
+        assertTrue(mInputEventsHandler.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
         verifyZeroInteractions(mMockPowerManagerService);
-        assertFalse(mMessageCapturingHandler.isTimeoutPending());
+        assertFalse(isTimeoutPending(mMessageCapturingHandler));
     }
 
     @Test
@@ -198,10 +198,10 @@
         mKeyEventDispatcher.setOnKeyEventResult(mKeyEventFilter2, true,
                 mFilter2SequenceCaptor.getValue());
 
-        assertFalse(mInputEventsHander.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
+        assertFalse(mInputEventsHandler.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
         verify(mMockPowerManagerService, times(1)).userActivity(anyLong(),
                 eq(PowerManager.USER_ACTIVITY_EVENT_ACCESSIBILITY), eq(0));
-        assertFalse(mMessageCapturingHandler.isTimeoutPending());
+        assertFalse(isTimeoutPending(mMessageCapturingHandler));
     }
 
     @Test
@@ -215,10 +215,10 @@
         mKeyEventDispatcher.setOnKeyEventResult(mKeyEventFilter2, false,
                 mFilter2SequenceCaptor.getValue());
 
-        assertFalse(mInputEventsHander.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
+        assertFalse(mInputEventsHandler.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
         verify(mMockPowerManagerService, times(1)).userActivity(anyLong(),
                 eq(PowerManager.USER_ACTIVITY_EVENT_ACCESSIBILITY), eq(0));
-        assertFalse(mMessageCapturingHandler.isTimeoutPending());
+        assertFalse(isTimeoutPending(mMessageCapturingHandler));
     }
 
     @Test
@@ -232,10 +232,10 @@
         mKeyEventDispatcher.setOnKeyEventResult(mKeyEventFilter2, true,
                 mFilter2SequenceCaptor.getValue());
 
-        assertFalse(mInputEventsHander.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
+        assertFalse(mInputEventsHandler.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
         verify(mMockPowerManagerService, times(1)).userActivity(anyLong(),
                 eq(PowerManager.USER_ACTIVITY_EVENT_ACCESSIBILITY), eq(0));
-        assertFalse(mMessageCapturingHandler.isTimeoutPending());
+        assertFalse(isTimeoutPending(mMessageCapturingHandler));
     }
 
     // Each event should have its result set only once, but if it's set twice, we should ignore
@@ -249,14 +249,14 @@
                 mFilter1SequenceCaptor.getValue());
         mKeyEventDispatcher.setOnKeyEventResult(mKeyEventFilter1, false,
                 mFilter1SequenceCaptor.getValue());
-        assertFalse(mInputEventsHander.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
+        assertFalse(mInputEventsHandler.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
 
         // Verify event is sent properly when other service responds
         mKeyEventDispatcher.setOnKeyEventResult(mKeyEventFilter2, false,
                 mFilter2SequenceCaptor.getValue());
-        assertTrue(mInputEventsHander.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
+        assertTrue(mInputEventsHandler.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
         verifyZeroInteractions(mMockPowerManagerService);
-        assertFalse(mMessageCapturingHandler.isTimeoutPending());
+        assertFalse(isTimeoutPending(mMessageCapturingHandler));
     }
 
 
@@ -269,9 +269,9 @@
                 mKeyEvent, 0, Arrays.asList(mKeyEventFilter1, mKeyEventFilter2));
 
         assertEquals(1, mMessageCapturingHandler.timedMessages.size());
-        mKeyEventDispatcher.handleMessage(mMessageCapturingHandler.timedMessages.get(0));
+        mKeyEventDispatcher.handleMessage(getTimedMessage(mMessageCapturingHandler, 0));
 
-        assertTrue(mInputEventsHander.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
+        assertTrue(mInputEventsHandler.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
         verifyZeroInteractions(mMockPowerManagerService);
     }
 
@@ -284,9 +284,9 @@
                 mFilter1SequenceCaptor.getValue());
 
         assertEquals(1, mMessageCapturingHandler.timedMessages.size());
-        mKeyEventDispatcher.handleMessage(mMessageCapturingHandler.timedMessages.get(0));
+        mKeyEventDispatcher.handleMessage(getTimedMessage(mMessageCapturingHandler, 0));
 
-        assertTrue(mInputEventsHander.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
+        assertTrue(mInputEventsHandler.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
         verifyZeroInteractions(mMockPowerManagerService);
     }
 
@@ -300,9 +300,9 @@
                 mFilter1SequenceCaptor.getValue());
 
         assertEquals(1, mMessageCapturingHandler.timedMessages.size());
-        mKeyEventDispatcher.handleMessage(mMessageCapturingHandler.timedMessages.get(0));
+        mKeyEventDispatcher.handleMessage(getTimedMessage(mMessageCapturingHandler, 0));
 
-        assertFalse(mInputEventsHander.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
+        assertFalse(mInputEventsHandler.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
         verify(mMockPowerManagerService, times(1)).userActivity(anyLong(),
                 eq(PowerManager.USER_ACTIVITY_EVENT_ACCESSIBILITY), eq(0));
     }
@@ -310,34 +310,34 @@
     @Test
     public void testEventTimesOut_thenServiceReturnsFalse_shouldPassToFrameworkOnce() {
         mKeyEventDispatcher.notifyKeyEventLocked(mKeyEvent, 0, Arrays.asList(mKeyEventFilter1));
-        assertFalse(mInputEventsHander.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
+        assertFalse(mInputEventsHandler.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
 
         assertEquals(1, mMessageCapturingHandler.timedMessages.size());
-        mKeyEventDispatcher.handleMessage(mMessageCapturingHandler.timedMessages.get(0));
-        assertTrue(mInputEventsHander.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
+        mKeyEventDispatcher.handleMessage(getTimedMessage(mMessageCapturingHandler, 0));
+        assertTrue(mInputEventsHandler.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
 
-        mInputEventsHander.removeMessages(SEND_FRAMEWORK_KEY_EVENT);
+        mInputEventsHandler.removeMessages(SEND_FRAMEWORK_KEY_EVENT);
         mKeyEventDispatcher.setOnKeyEventResult(mKeyEventFilter1, false,
                 mFilter1SequenceCaptor.getValue());
 
-        assertFalse(mInputEventsHander.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
+        assertFalse(mInputEventsHandler.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
         verifyZeroInteractions(mMockPowerManagerService);
     }
 
     @Test
     public void testEventTimesOut_afterServiceReturnsFalse_shouldPassToFrameworkOnce() {
         mKeyEventDispatcher.notifyKeyEventLocked(mKeyEvent, 0, Arrays.asList(mKeyEventFilter1));
-        assertFalse(mInputEventsHander.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
+        assertFalse(mInputEventsHandler.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
 
         mKeyEventDispatcher.setOnKeyEventResult(mKeyEventFilter1, false,
                 mFilter1SequenceCaptor.getValue());
-        assertTrue(mInputEventsHander.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
+        assertTrue(mInputEventsHandler.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
 
-        mInputEventsHander.removeMessages(SEND_FRAMEWORK_KEY_EVENT);
+        mInputEventsHandler.removeMessages(SEND_FRAMEWORK_KEY_EVENT);
         assertEquals(1, mMessageCapturingHandler.timedMessages.size());
-        mKeyEventDispatcher.handleMessage(mMessageCapturingHandler.timedMessages.get(0));
+        mKeyEventDispatcher.handleMessage(getTimedMessage(mMessageCapturingHandler, 0));
 
-        assertFalse(mInputEventsHander.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
+        assertFalse(mInputEventsHandler.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
         verifyZeroInteractions(mMockPowerManagerService);
     }
 
@@ -349,9 +349,9 @@
         mKeyEventDispatcher.setOnKeyEventResult(mKeyEventFilter1, true,
                 mFilter1SequenceCaptor.getValue());
         assertEquals(1, mMessageCapturingHandler.timedMessages.size());
-        mKeyEventDispatcher.handleMessage(mMessageCapturingHandler.timedMessages.get(0));
+        mKeyEventDispatcher.handleMessage(getTimedMessage(mMessageCapturingHandler, 0));
 
-        assertFalse(mInputEventsHander.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
+        assertFalse(mInputEventsHandler.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
         verify(mMockPowerManagerService, times(1)).userActivity(anyLong(),
                 eq(PowerManager.USER_ACTIVITY_EVENT_ACCESSIBILITY), eq(0));
     }
@@ -362,11 +362,11 @@
     @Test
     public void testFlushService_withPendingEvent_shouldPassToFramework() {
         mKeyEventDispatcher.notifyKeyEventLocked(mKeyEvent, 0, Arrays.asList(mKeyEventFilter1));
-        assertFalse(mInputEventsHander.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
+        assertFalse(mInputEventsHandler.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
 
         mKeyEventDispatcher.flush(mKeyEventFilter1);
 
-        assertTrue(mInputEventsHander.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
+        assertTrue(mInputEventsHandler.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
     }
 
     @Test
@@ -377,7 +377,7 @@
         mKeyEventDispatcher.flush(mKeyEventFilter1);
         mKeyEventDispatcher.flush(mKeyEventFilter2);
 
-        assertTrue(mInputEventsHander.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
+        assertTrue(mInputEventsHandler.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
     }
 
     @Test
@@ -389,7 +389,7 @@
         mKeyEventDispatcher.setOnKeyEventResult(mKeyEventFilter2, true,
                 mFilter2SequenceCaptor.getValue());
 
-        assertFalse(mInputEventsHander.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
+        assertFalse(mInputEventsHandler.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
     }
 
     @Test
@@ -401,7 +401,7 @@
         mKeyEventDispatcher.setOnKeyEventResult(mKeyEventFilter2, false,
                 mFilter2SequenceCaptor.getValue());
 
-        assertTrue(mInputEventsHander.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
+        assertTrue(mInputEventsHandler.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
     }
 
     @Test
@@ -417,11 +417,11 @@
         mKeyEventDispatcher.notifyKeyEventLocked(mKeyEvent, 0, Arrays.asList(mKeyEventFilter1));
         mKeyEventDispatcher
                 .notifyKeyEventLocked(mOtherKeyEvent, 0, Arrays.asList(mKeyEventFilter1));
-        assertFalse(mInputEventsHander.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
+        assertFalse(mInputEventsHandler.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
 
         mKeyEventDispatcher.setOnKeyEventResult(mKeyEventFilter1, false,
                 mFilter1SequenceCaptor.getAllValues().get(0));
-        mInputEventsHander.removeMessages(SEND_FRAMEWORK_KEY_EVENT);
+        mInputEventsHandler.removeMessages(SEND_FRAMEWORK_KEY_EVENT);
         mKeyEventDispatcher.setOnKeyEventResult(mKeyEventFilter1, false,
                 mFilter1SequenceCaptor.getAllValues().get(1));
 
@@ -433,14 +433,14 @@
         mKeyEventDispatcher.notifyKeyEventLocked(mKeyEvent, 0, Arrays.asList(mKeyEventFilter1));
         mKeyEventDispatcher
                 .notifyKeyEventLocked(mOtherKeyEvent, 0, Arrays.asList(mKeyEventFilter1));
-        assertFalse(mInputEventsHander.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
+        assertFalse(mInputEventsHandler.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
 
         mKeyEventDispatcher.setOnKeyEventResult(mKeyEventFilter1, true,
                 mFilter1SequenceCaptor.getAllValues().get(0));
         mKeyEventDispatcher.setOnKeyEventResult(mKeyEventFilter1, true,
                 mFilter1SequenceCaptor.getAllValues().get(1));
 
-        assertFalse(mInputEventsHander.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
+        assertFalse(mInputEventsHandler.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
     }
 
     @Test
@@ -448,7 +448,7 @@
         mKeyEventDispatcher.notifyKeyEventLocked(mKeyEvent, 0, Arrays.asList(mKeyEventFilter1));
         mKeyEventDispatcher
                 .notifyKeyEventLocked(mOtherKeyEvent, 0, Arrays.asList(mKeyEventFilter1));
-        assertFalse(mInputEventsHander.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
+        assertFalse(mInputEventsHandler.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
 
         mKeyEventDispatcher.setOnKeyEventResult(mKeyEventFilter1, true,
                 mFilter1SequenceCaptor.getAllValues().get(0));
@@ -463,7 +463,7 @@
         mKeyEventDispatcher.notifyKeyEventLocked(mKeyEvent, 0, Arrays.asList(mKeyEventFilter1));
         mKeyEventDispatcher
                 .notifyKeyEventLocked(mOtherKeyEvent, 0, Arrays.asList(mKeyEventFilter1));
-        assertFalse(mInputEventsHander.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
+        assertFalse(mInputEventsHandler.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
 
         mKeyEventDispatcher.setOnKeyEventResult(mKeyEventFilter1, false,
                 mFilter1SequenceCaptor.getAllValues().get(0));
@@ -478,9 +478,9 @@
         mKeyEventDispatcher.notifyKeyEventLocked(mKeyEvent, 0, Arrays.asList(mKeyEventFilter1));
         mKeyEventDispatcher
                 .notifyKeyEventLocked(mOtherKeyEvent, 0, Arrays.asList(mKeyEventFilter1));
-        assertFalse(mInputEventsHander.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
+        assertFalse(mInputEventsHandler.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
 
-        mKeyEventDispatcher.handleMessage(mMessageCapturingHandler.timedMessages.get(0));
+        mKeyEventDispatcher.handleMessage(getTimedMessage(mMessageCapturingHandler, 0));
         mKeyEventDispatcher.setOnKeyEventResult(mKeyEventFilter1, true,
                 mFilter1SequenceCaptor.getAllValues().get(0));
         mKeyEventDispatcher.setOnKeyEventResult(mKeyEventFilter1, true,
@@ -494,7 +494,7 @@
         mKeyEventDispatcher.notifyKeyEventLocked(mKeyEvent, 0, Arrays.asList(mKeyEventFilter1));
         mKeyEventDispatcher.notifyKeyEventLocked(
                 mOtherKeyEvent, 0, Arrays.asList(mKeyEventFilter1, mKeyEventFilter2));
-        assertFalse(mInputEventsHander.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
+        assertFalse(mInputEventsHandler.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
 
         mKeyEventDispatcher.setOnKeyEventResult(mKeyEventFilter2, false,
                 mFilter2SequenceCaptor.getValue());
@@ -513,7 +513,7 @@
         mKeyEventDispatcher.flush(mKeyEventFilter1);
         mKeyEventDispatcher.notifyKeyEventLocked(
                 mOtherKeyEvent, 0, Arrays.asList(mKeyEventFilter2));
-        assertFalse(mInputEventsHander.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
+        assertFalse(mInputEventsHandler.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
 
         mKeyEventDispatcher.setOnKeyEventResult(mKeyEventFilter2, false,
                 mFilter2SequenceCaptor.getAllValues().get(0));
@@ -543,24 +543,34 @@
     }
 
     private void assertOneKeyEventSentToFramework(KeyEvent event) {
-        assertEquals(1, mInputEventsHander.timedMessages.size());
-        assertEquals(SEND_FRAMEWORK_KEY_EVENT, mInputEventsHander.timedMessages.get(0).what);
-        assertEquals(WindowManagerPolicy.FLAG_PASS_TO_USER,
-                mInputEventsHander.timedMessages.get(0).arg1);
-        assertTrue(new KeyEventMatcher(event).matches(mInputEventsHander.timedMessages.get(0).obj));
+        assertEquals(1, mInputEventsHandler.timedMessages.size());
+
+        Message m = getTimedMessage(mInputEventsHandler, 0);
+        assertEquals(SEND_FRAMEWORK_KEY_EVENT, m.what);
+        assertEquals(WindowManagerPolicy.FLAG_PASS_TO_USER, m.arg1);
+        assertTrue(new KeyEventMatcher(event).matches(m.obj));
     }
 
     private void assertTwoKeyEventsSentToFrameworkInOrder(KeyEvent first, KeyEvent second) {
-        assertEquals(2, mInputEventsHander.timedMessages.size());
-        assertEquals(SEND_FRAMEWORK_KEY_EVENT, mInputEventsHander.timedMessages.get(0).what);
-        assertEquals(WindowManagerPolicy.FLAG_PASS_TO_USER,
-                mInputEventsHander.timedMessages.get(0).arg1);
-        assertTrue(new KeyEventMatcher(first).matches(mInputEventsHander.timedMessages.get(0).obj));
-        assertEquals(SEND_FRAMEWORK_KEY_EVENT, mInputEventsHander.timedMessages.get(1).what);
-        assertEquals(WindowManagerPolicy.FLAG_PASS_TO_USER,
-                mInputEventsHander.timedMessages.get(1).arg1);
-        assertTrue(new KeyEventMatcher(second)
-                .matches(mInputEventsHander.timedMessages.get(1).obj));
+        assertEquals(2, mInputEventsHandler.timedMessages.size());
+
+        Message m0 = getTimedMessage(mInputEventsHandler, 0);
+        assertEquals(SEND_FRAMEWORK_KEY_EVENT, m0.what);
+        assertEquals(WindowManagerPolicy.FLAG_PASS_TO_USER, m0.arg1);
+        assertTrue(new KeyEventMatcher(first).matches(m0.obj));
+
+        Message m1 = getTimedMessage(mInputEventsHandler, 1);
+        assertEquals(SEND_FRAMEWORK_KEY_EVENT, m1.what);
+        assertEquals(WindowManagerPolicy.FLAG_PASS_TO_USER, m1.arg1);
+        assertTrue(new KeyEventMatcher(second).matches(m1.obj));
+    }
+
+    private static Message getTimedMessage(MessageCapturingHandler handler, int i) {
+        return handler.timedMessages.get(i).first;
+    }
+
+    private static boolean isTimeoutPending(MessageCapturingHandler handler) {
+        return handler.hasMessages(KeyEventDispatcher.MSG_ON_KEY_EVENT_TIMEOUT);
     }
 
     private class KeyEventMatcher extends TypeSafeMatcher<KeyEvent> {
@@ -581,18 +591,4 @@
             description.appendText("Key event matcher");
         }
     }
-
-    private class MessageCapturingHandler extends Handler {
-        List<Message> timedMessages = new ArrayList<>();
-
-        @Override
-        public boolean sendMessageAtTime(Message message, long uptimeMillis) {
-            timedMessages.add(Message.obtain(message));
-            return super.sendMessageAtTime(message, uptimeMillis);
-        }
-
-        public boolean isTimeoutPending() {
-            return hasMessages(KeyEventDispatcher.MSG_ON_KEY_EVENT_TIMEOUT);
-        }
-    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/KeyboardInterceptorTest.java b/services/tests/servicestests/src/com/android/server/accessibility/KeyboardInterceptorTest.java
index 851e221..9926a09 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/KeyboardInterceptorTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/KeyboardInterceptorTest.java
@@ -28,7 +28,6 @@
 import static org.mockito.Mockito.when;
 import static org.mockito.hamcrest.MockitoHamcrest.argThat;
 
-import android.os.Looper;
 import android.view.KeyEvent;
 
 import androidx.test.runner.AndroidJUnit4;
@@ -38,8 +37,8 @@
 
 import org.hamcrest.Description;
 import org.hamcrest.TypeSafeMatcher;
+import org.junit.After;
 import org.junit.Before;
-import org.junit.BeforeClass;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.InOrder;
@@ -58,19 +57,18 @@
     @Mock AccessibilityManagerService mMockAms;
     @Mock WindowManagerPolicy mMockPolicy;
 
-    @BeforeClass
-    public static void oneTimeInitialization() {
-        if (Looper.myLooper() == null) {
-            Looper.prepare();
-        }
-    }
-
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
         mInterceptor = new KeyboardInterceptor(mMockAms, mMockPolicy, mHandler);
     }
 
+    @After
+    public void tearDown() {
+        mHandler.removeAllMessages();
+    }
+
+
     @Test
     public void whenNonspecialKeyArrives_withNothingInQueue_eventGoesToAms() {
         KeyEvent event = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_0);
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 d6d21c6..c88b873 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/MagnificationControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/MagnificationControllerTest.java
@@ -43,9 +43,9 @@
 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.InstrumentationRegistry;
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.internal.R;
@@ -55,8 +55,8 @@
 import org.hamcrest.CoreMatchers;
 import org.hamcrest.Description;
 import org.hamcrest.TypeSafeMatcher;
+import org.junit.After;
 import org.junit.Before;
-import org.junit.BeforeClass;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
@@ -67,7 +67,6 @@
 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(
@@ -75,8 +74,10 @@
     static final PointF INITIAL_BOUNDS_UPPER_LEFT_2X_CENTER = new PointF(25, 50);
     static final PointF INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER = new PointF(75, 150);
     static final Rect OTHER_MAGNIFICATION_BOUNDS = new Rect(100, 200, 500, 600);
+    static final Rect OTHER_MAGNIFICATION_BOUNDS_COMPAT = new Rect(50, 100, 450, 500);
     static final PointF OTHER_BOUNDS_LOWER_RIGHT_2X_CENTER = new PointF(400, 500);
     static final Region INITIAL_MAGNIFICATION_REGION = new Region(INITIAL_MAGNIFICATION_BOUNDS);
+    static final Region OTHER_REGION_COMPAT = new Region(OTHER_MAGNIFICATION_BOUNDS_COMPAT);
     static final Region OTHER_REGION = new Region(OTHER_MAGNIFICATION_BOUNDS);
     static final int SERVICE_ID_1 = 1;
     static final int SERVICE_ID_2 = 2;
@@ -91,25 +92,17 @@
             return mMagnificationController.handleMessage(msg);
         }
     });
-    final ArgumentCaptor<MagnificationSpec> mMagnificationSpecCaptor =
-            ArgumentCaptor.forClass(MagnificationSpec.class);
     final ValueAnimator mMockValueAnimator = mock(ValueAnimator.class);
     MagnificationController.SettingsBridge mMockSettingsBridge;
 
-
     MagnificationController mMagnificationController;
     ValueAnimator.AnimatorUpdateListener mTargetAnimationListener;
 
-    @BeforeClass
-    public static void oneTimeInitialization() {
-        if (Looper.myLooper() == null) {
-            Looper.prepare();
-        }
-    }
-
     @Before
     public void setUp() {
-        when(mMockContext.getMainLooper()).thenReturn(Looper.myLooper());
+        Looper looper = InstrumentationRegistry.getContext().getMainLooper();
+        // Pretending ID of the Thread associated with looper as main thread ID in controller
+        when(mMockContext.getMainLooper()).thenReturn(looper);
         Resources mockResources = mock(Resources.class);
         when(mMockContext.getResources()).thenReturn(mockResources);
         when(mockResources.getInteger(R.integer.config_longAnimTime))
@@ -136,6 +129,12 @@
         Mockito.reset(mMockValueAnimator); // Ignore other initialization
     }
 
+    @After
+    public void tearDown() {
+        mMessageCapturingHandler.removeAllMessages();
+    }
+
+
     @Test
     public void testRegister_WindowManagerAndContextRegisterListeners() {
         mMagnificationController.register();
@@ -202,6 +201,7 @@
         final PointF offsets = computeOffsets(INITIAL_MAGNIFICATION_BOUNDS, center, scale);
         assertTrue(mMagnificationController
                 .setScale(scale, center.x, center.y, false, SERVICE_ID_1));
+        mMessageCapturingHandler.sendAllMessages();
 
         final MagnificationSpec expectedSpec = getMagnificationSpec(scale, offsets);
         verify(mMockWindowManager).setMagnificationSpec(argThat(closeTo(expectedSpec)));
@@ -219,6 +219,7 @@
         PointF pivotPoint = INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER;
         assertTrue(mMagnificationController
                 .setScale(scale, pivotPoint.x, pivotPoint.y, true, SERVICE_ID_1));
+        mMessageCapturingHandler.sendAllMessages();
 
         // New center should be halfway between original center and pivot
         PointF newCenter = new PointF((pivotPoint.x + INITIAL_MAGNIFICATION_BOUNDS.centerX()) / 2,
@@ -264,6 +265,7 @@
         PointF newCenter = INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER;
         assertTrue(mMagnificationController
                 .setCenter(newCenter.x, newCenter.y, false, SERVICE_ID_1));
+        mMessageCapturingHandler.sendAllMessages();
         PointF expectedOffsets = computeOffsets(INITIAL_MAGNIFICATION_BOUNDS, newCenter, scale);
         MagnificationSpec expectedSpec = getMagnificationSpec(scale, expectedOffsets);
 
@@ -284,6 +286,7 @@
 
         assertTrue(mMagnificationController.setScaleAndCenter(scale, newCenter.x, newCenter.y,
                 true, SERVICE_ID_1));
+        mMessageCapturingHandler.sendAllMessages();
 
         assertEquals(newCenter.x, mMagnificationController.getCenterX(), 0.5);
         assertEquals(newCenter.y, mMagnificationController.getCenterY(), 0.5);
@@ -325,6 +328,7 @@
         assertTrue(mMagnificationController.setScaleAndCenter(
                 MagnificationController.MAX_SCALE + 1.0f,
                 newCenter.x, newCenter.y, false, SERVICE_ID_1));
+        mMessageCapturingHandler.sendAllMessages();
 
         assertEquals(newCenter.x, mMagnificationController.getCenterX(), 0.5);
         assertEquals(newCenter.y, mMagnificationController.getCenterY(), 0.5);
@@ -335,6 +339,7 @@
         assertTrue(mMagnificationController.setScaleAndCenter(0.5f,
                 INITIAL_MAGNIFICATION_BOUNDS_CENTER.x, INITIAL_MAGNIFICATION_BOUNDS_CENTER.y,
                 false, SERVICE_ID_1));
+        mMessageCapturingHandler.sendAllMessages();
 
         assertEquals(INITIAL_MAGNIFICATION_BOUNDS_CENTER.x,
                 mMagnificationController.getCenterX(), 0.5);
@@ -351,6 +356,7 @@
         // Off the edge to the top and left
         assertTrue(mMagnificationController.setScaleAndCenter(
                 scale, -100f, -200f, false, SERVICE_ID_1));
+        mMessageCapturingHandler.sendAllMessages();
 
         PointF newCenter = INITIAL_BOUNDS_UPPER_LEFT_2X_CENTER;
         PointF newOffsets = computeOffsets(INITIAL_MAGNIFICATION_BOUNDS, newCenter, scale);
@@ -364,6 +370,7 @@
         assertTrue(mMagnificationController.setScaleAndCenter(scale,
                 INITIAL_MAGNIFICATION_BOUNDS.right + 1, INITIAL_MAGNIFICATION_BOUNDS.bottom + 1,
                 false, SERVICE_ID_1));
+        mMessageCapturingHandler.sendAllMessages();
         newCenter = INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER;
         newOffsets = computeOffsets(INITIAL_MAGNIFICATION_BOUNDS, newCenter, scale);
         assertEquals(newCenter.x, mMagnificationController.getCenterX(), 0.5);
@@ -391,12 +398,14 @@
         // First zoom in
         assertTrue(mMagnificationController
                 .setScaleAndCenter(scale, startCenter.x, startCenter.y, false, SERVICE_ID_1));
+        mMessageCapturingHandler.sendAllMessages();
         Mockito.reset(mMockWindowManager);
 
         PointF newCenter = INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER;
         PointF newOffsets = computeOffsets(INITIAL_MAGNIFICATION_BOUNDS, newCenter, scale);
         mMagnificationController.offsetMagnifiedRegion(
                 startOffsets.x - newOffsets.x, startOffsets.y - newOffsets.y, SERVICE_ID_1);
+        mMessageCapturingHandler.sendAllMessages();
 
         MagnificationSpec expectedSpec = getMagnificationSpec(scale, newOffsets);
         verify(mMockWindowManager).setMagnificationSpec(argThat(closeTo(expectedSpec)));
@@ -490,6 +499,7 @@
     public void testResetIfNeeded_doesWhatItSays() {
         mMagnificationController.register();
         zoomIn2xToMiddle();
+        mMessageCapturingHandler.sendAllMessages();
         reset(mMockAms);
         assertTrue(mMagnificationController.resetIfNeeded(false));
         verify(mMockAms).notifyMagnificationChanged(
@@ -507,6 +517,7 @@
                 broadcastReceiverCaptor.capture(), (IntentFilter) anyObject());
         BroadcastReceiver br = broadcastReceiverCaptor.getValue();
         zoomIn2xToMiddle();
+        mMessageCapturingHandler.sendAllMessages();
         br.onReceive(mMockContext, null);
         mMessageCapturingHandler.sendAllMessages();
         assertFalse(mMagnificationController.isMagnifying());
@@ -517,6 +528,7 @@
         mMagnificationController.register();
         MagnificationCallbacks callbacks = getMagnificationCallbacks();
         zoomIn2xToMiddle();
+        mMessageCapturingHandler.sendAllMessages();
         callbacks.onUserContextChanged();
         mMessageCapturingHandler.sendAllMessages();
         assertFalse(mMagnificationController.isMagnifying());
@@ -539,10 +551,11 @@
         // Going from a small region to a large one leads to no issues
         mMagnificationController.register();
         zoomIn2xToMiddle();
+        mMessageCapturingHandler.sendAllMessages();
         MagnificationSpec startSpec = getCurrentMagnificationSpec();
         MagnificationCallbacks callbacks = getMagnificationCallbacks();
         Mockito.reset(mMockWindowManager);
-        callbacks.onMagnificationRegionChanged(OTHER_REGION);
+        callbacks.onMagnificationRegionChanged(OTHER_REGION_COMPAT);
         mMessageCapturingHandler.sendAllMessages();
         assertThat(getCurrentMagnificationSpec(), closeTo(startSpec));
         verifyNoMoreInteractions(mMockWindowManager);
@@ -553,11 +566,12 @@
         mMagnificationController.register();
         PointF startCenter = INITIAL_MAGNIFICATION_BOUNDS_CENTER;
         float scale = 2.0f;
+        // setting animate parameter to true is differ from zoomIn2xToMiddle()
         mMagnificationController.setScale(scale, startCenter.x, startCenter.y, true, SERVICE_ID_1);
         MagnificationSpec startSpec = getCurrentMagnificationSpec();
         MagnificationCallbacks callbacks = getMagnificationCallbacks();
         Mockito.reset(mMockWindowManager);
-        callbacks.onMagnificationRegionChanged(OTHER_REGION);
+        callbacks.onMagnificationRegionChanged(OTHER_REGION_COMPAT);
         mMessageCapturingHandler.sendAllMessages();
         assertThat(getCurrentMagnificationSpec(), closeTo(startSpec));
         verifyNoMoreInteractions(mMockWindowManager);
@@ -573,6 +587,7 @@
         PointF startCenter = OTHER_BOUNDS_LOWER_RIGHT_2X_CENTER;
         float scale = 2.0f;
         mMagnificationController.setScale(scale, startCenter.x, startCenter.y, false, SERVICE_ID_1);
+        mMessageCapturingHandler.sendAllMessages();
         MagnificationSpec startSpec = getCurrentMagnificationSpec();
         verify(mMockWindowManager).setMagnificationSpec(argThat(closeTo(startSpec)));
         Mockito.reset(mMockWindowManager);
@@ -597,8 +612,9 @@
         PointF startCenter = OTHER_BOUNDS_LOWER_RIGHT_2X_CENTER;
         float scale = 2.0f;
         mMagnificationController.setScale(scale, startCenter.x, startCenter.y, true, SERVICE_ID_1);
+        mMessageCapturingHandler.sendAllMessages();
         MagnificationSpec startSpec = getCurrentMagnificationSpec();
-        when (mMockValueAnimator.isRunning()).thenReturn(true);
+        when(mMockValueAnimator.isRunning()).thenReturn(true);
 
         callbacks.onMagnificationRegionChanged(INITIAL_MAGNIFICATION_REGION);
         mMessageCapturingHandler.sendAllMessages();
@@ -616,6 +632,7 @@
     public void testRequestRectOnScreen_rectAlreadyOnScreen_doesNothing() {
         mMagnificationController.register();
         zoomIn2xToMiddle();
+        mMessageCapturingHandler.sendAllMessages();
         MagnificationSpec startSpec = getCurrentMagnificationSpec();
         MagnificationCallbacks callbacks = getMagnificationCallbacks();
         Mockito.reset(mMockWindowManager);
@@ -631,6 +648,7 @@
     public void testRequestRectOnScreen_rectCanFitOnScreen_pansToGetRectOnScreen() {
         mMagnificationController.register();
         zoomIn2xToMiddle();
+        mMessageCapturingHandler.sendAllMessages();
         MagnificationCallbacks callbacks = getMagnificationCallbacks();
         Mockito.reset(mMockWindowManager);
         callbacks.onRectangleOnScreenRequested(0, 0, 1, 1);
@@ -644,6 +662,7 @@
     public void testRequestRectOnScreen_garbageInput_doesNothing() {
         mMagnificationController.register();
         zoomIn2xToMiddle();
+        mMessageCapturingHandler.sendAllMessages();
         MagnificationSpec startSpec = getCurrentMagnificationSpec();
         MagnificationCallbacks callbacks = getMagnificationCallbacks();
         Mockito.reset(mMockWindowManager);
@@ -653,12 +672,12 @@
         verifyNoMoreInteractions(mMockWindowManager);
     }
 
-
     @Test
     public void testRequestRectOnScreen_rectTooWide_pansToGetStartOnScreenBasedOnLocale() {
         Locale.setDefault(new Locale("en", "us"));
         mMagnificationController.register();
         zoomIn2xToMiddle();
+        mMessageCapturingHandler.sendAllMessages();
         MagnificationCallbacks callbacks = getMagnificationCallbacks();
         MagnificationSpec startSpec = getCurrentMagnificationSpec();
         Mockito.reset(mMockWindowManager);
@@ -685,6 +704,7 @@
     public void testRequestRectOnScreen_rectTooTall_pansMinimumToGetTopOnScreen() {
         mMagnificationController.register();
         zoomIn2xToMiddle();
+        mMessageCapturingHandler.sendAllMessages();
         MagnificationCallbacks callbacks = getMagnificationCallbacks();
         MagnificationSpec startSpec = getCurrentMagnificationSpec();
         Mockito.reset(mMockWindowManager);
@@ -708,6 +728,7 @@
 
         assertTrue(mMagnificationController.setScaleAndCenter(scale, firstCenter.x, firstCenter.y,
                 true, SERVICE_ID_1));
+        mMessageCapturingHandler.sendAllMessages();
 
         assertEquals(firstCenter.x, mMagnificationController.getCenterX(), 0.5);
         assertEquals(firstCenter.y, mMagnificationController.getCenterY(), 0.5);
@@ -736,6 +757,7 @@
                 scale, computeOffsets(INITIAL_MAGNIFICATION_BOUNDS, newCenter, scale));
         assertTrue(mMagnificationController.setCenter(
                 newCenter.x, newCenter.y, true, SERVICE_ID_1));
+        mMessageCapturingHandler.sendAllMessages();
 
         // Animation should have been restarted
         verify(mMockValueAnimator, times(2)).start();
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/MessageCapturingHandler.java b/services/tests/servicestests/src/com/android/server/accessibility/MessageCapturingHandler.java
index e3ee47f..e2b517f 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/MessageCapturingHandler.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/MessageCapturingHandler.java
@@ -16,11 +16,13 @@
 
 package com.android.server.accessibility;
 
-import android.app.Notification;
 import android.os.Handler;
+import android.os.Looper;
 import android.os.Message;
 import android.util.Pair;
 
+import androidx.test.InstrumentationRegistry;
+
 import java.util.ArrayList;
 import java.util.List;
 
@@ -34,13 +36,22 @@
     Handler.Callback mCallback;
 
     public MessageCapturingHandler(Handler.Callback callback) {
+        this(InstrumentationRegistry.getContext().getMainLooper(), callback);
+    }
+
+    public MessageCapturingHandler(Looper looper, Callback callback) {
+        super(looper);
         mCallback = callback;
     }
 
+    /**
+     * Holding messages in queue, but never dispatching.
+     * @see #removeAllMessages()
+     */
     @Override
     public boolean sendMessageAtTime(Message message, long uptimeMillis) {
         timedMessages.add(new Pair<>(Message.obtain(message), uptimeMillis));
-        return super.sendMessageAtTime(message, uptimeMillis);
+        return super.sendMessageAtTime(message, Long.MAX_VALUE);
     }
 
     public void setCallback(Handler.Callback callback) {
@@ -67,6 +78,22 @@
         removeStaleMessages();
     }
 
+    /**
+     * Clear messages sent from this handler in queue.
+     * <p>
+     * If main looper is used, this method should be called in tear down function
+     * to ensure messages isolation between test cases.
+     * </p>
+     */
+    public void removeAllMessages() {
+        if (hasMessages()) {
+            for (int i = 0; i < timedMessages.size(); i++) {
+                Message message = timedMessages.get(i).first;
+                removeMessages(message.what, message.obj);
+            }
+        }
+    }
+
     public boolean hasMessages() {
         removeStaleMessages();
         return !timedMessages.isEmpty();
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/MotionEventInjectorTest.java b/services/tests/servicestests/src/com/android/server/accessibility/MotionEventInjectorTest.java
index 5f0fa87..2cba9d0 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/MotionEventInjectorTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/MotionEventInjectorTest.java
@@ -43,7 +43,6 @@
 import android.accessibilityservice.IAccessibilityServiceClient;
 import android.graphics.Point;
 import android.os.Handler;
-import android.os.Looper;
 import android.os.Message;
 import android.os.RemoteException;
 import android.util.Log;
@@ -57,8 +56,8 @@
 import org.hamcrest.Description;
 import org.hamcrest.Matcher;
 import org.hamcrest.TypeSafeMatcher;
+import org.junit.After;
 import org.junit.Before;
-import org.junit.BeforeClass;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
@@ -127,13 +126,6 @@
     Matcher<MotionEvent> mIsClickDown;
     Matcher<MotionEvent> mIsClickUp;
 
-    @BeforeClass
-    public static void oneTimeInitialization() {
-        if (Looper.myLooper() == null) {
-            Looper.prepare();
-        }
-    }
-
     @Before
     public void setUp() {
         mMessageCapturingHandler = new MessageCapturingHandler(new Handler.Callback() {
@@ -172,6 +164,12 @@
                 hasTimeFromDown(CLICK_DURATION));
     }
 
+    @After
+    public void tearDown() {
+        mMessageCapturingHandler.removeAllMessages();
+    }
+
+
     @Test
     public void testInjectEvents_shouldEmergeInOrderWithCorrectTiming() throws RemoteException {
         EventStreamTransformation next = attachMockNext(mMotionEventInjector);
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/TouchExplorerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/TouchExplorerTest.java
index c47885f..2645461 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/TouchExplorerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/TouchExplorerTest.java
@@ -16,12 +16,14 @@
 
 package com.android.server.accessibility;
 
-import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
 
 import android.content.Context;
 import android.graphics.PointF;
 import android.os.SystemClock;
+import android.testing.DexmakerShareClassLoaderRule;
 import android.util.DebugUtils;
 import android.view.InputDevice;
 import android.view.MotionEvent;
@@ -30,6 +32,7 @@
 import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
@@ -66,6 +69,11 @@
     private TouchExplorer mTouchExplorer;
     private long mLastDownTime = Integer.MIN_VALUE;
 
+    // mock package-private AccessibilityGestureDetector class
+    @Rule
+    public final DexmakerShareClassLoaderRule mDexmakerShareClassLoaderRule =
+            new DexmakerShareClassLoaderRule();
+
     /**
      * {@link TouchExplorer#sendDownForAllNotInjectedPointers} injecting events with the same object
      * is resulting {@link ArgumentCaptor} to capture events with last state. Before implementation
@@ -93,8 +101,9 @@
     public void setUp() {
         Context context = InstrumentationRegistry.getContext();
         AccessibilityManagerService ams = new AccessibilityManagerService(context);
+        AccessibilityGestureDetector detector = mock(AccessibilityGestureDetector.class);
         mCaptor = new EventCaptor();
-        mTouchExplorer = new TouchExplorer(context, ams);
+        mTouchExplorer = new TouchExplorer(context, ams, detector);
         mTouchExplorer.setNext(mCaptor);
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/UiAutomationManagerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/UiAutomationManagerTest.java
index 8853db2..8e09d60 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/UiAutomationManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/UiAutomationManagerTest.java
@@ -32,13 +32,12 @@
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
 import android.os.IBinder;
-import android.os.Looper;
 import android.view.accessibility.AccessibilityEvent;
 
 import com.android.server.wm.WindowManagerInternal;
 
+import org.junit.After;
 import org.junit.Before;
-import org.junit.BeforeClass;
 import org.junit.Test;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
@@ -66,13 +65,6 @@
     @Mock IAccessibilityServiceClient mMockAccessibilityServiceClient;
     @Mock IBinder mMockServiceAsBinder;
 
-    @BeforeClass
-    public static void oneTimeInitialization() {
-        if (Looper.myLooper() == null) {
-            Looper.prepare();
-        }
-    }
-
     @Before
     public void setup() {
         MockitoAnnotations.initMocks(this);
@@ -88,6 +80,12 @@
         mMessageCapturingHandler = new MessageCapturingHandler(null);
     }
 
+    @After
+    public void tearDown() {
+        mMessageCapturingHandler.removeAllMessages();
+    }
+
+
     @Test
     public void isRunning_returnsTrueOnlyWhenRunning() {
         assertFalse(mUiAutomationManager.isUiAutomationRunningLocked());
diff --git a/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodSubtypeSwitchingControllerTest.java b/services/tests/servicestests/src/com/android/server/inputmethod/InputMethodSubtypeSwitchingControllerTest.java
similarity index 97%
rename from core/tests/coretests/src/com/android/internal/inputmethod/InputMethodSubtypeSwitchingControllerTest.java
rename to services/tests/servicestests/src/com/android/server/inputmethod/InputMethodSubtypeSwitchingControllerTest.java
index 8a83518..910d433 100644
--- a/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodSubtypeSwitchingControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/inputmethod/InputMethodSubtypeSwitchingControllerTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.internal.inputmethod;
+package com.android.server.inputmethod;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -23,15 +23,15 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.view.inputmethod.InputMethodInfo;
 import android.view.inputmethod.InputMethodSubtype;
 import android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder;
 
-import com.android.internal.inputmethod.InputMethodSubtypeSwitchingController.ControllerImpl;
-import com.android.internal.inputmethod.InputMethodSubtypeSwitchingController.ImeSubtypeListItem;
-import com.android.internal.inputmethod.InputMethodUtils;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.server.inputmethod.InputMethodSubtypeSwitchingController.ControllerImpl;
+import com.android.server.inputmethod.InputMethodSubtypeSwitchingController.ImeSubtypeListItem;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodUtilsTest.java b/services/tests/servicestests/src/com/android/server/inputmethod/InputMethodUtilsTest.java
similarity index 90%
rename from core/tests/coretests/src/com/android/internal/inputmethod/InputMethodUtilsTest.java
rename to services/tests/servicestests/src/com/android/server/inputmethod/InputMethodUtilsTest.java
index 3064afa..4d0278f 100644
--- a/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodUtilsTest.java
+++ b/services/tests/servicestests/src/com/android/server/inputmethod/InputMethodUtilsTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.internal.inputmethod;
+package com.android.server.inputmethod;
 
 import static android.view.inputmethod.InputMethodManager.CONTROL_WINDOW_IS_TEXT_EDITOR;
 import static android.view.inputmethod.InputMethodManager.CONTROL_WINDOW_VIEW_HAS_FOCUS;
@@ -37,13 +37,14 @@
 import android.os.Build;
 import android.os.LocaleList;
 import android.os.Parcel;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.view.inputmethod.InputMethodInfo;
 import android.view.inputmethod.InputMethodSubtype;
 import android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -71,15 +72,11 @@
     private static final Locale LOCALE_FR = new Locale("fr");
     private static final Locale LOCALE_FR_CA = new Locale("fr", "CA");
     private static final Locale LOCALE_HI = new Locale("hi");
-    private static final Locale LOCALE_JA = new Locale("ja");
     private static final Locale LOCALE_JA_JP = new Locale("ja", "JP");
     private static final Locale LOCALE_ZH_CN = new Locale("zh", "CN");
     private static final Locale LOCALE_ZH_TW = new Locale("zh", "TW");
     private static final Locale LOCALE_IN = new Locale("in");
     private static final Locale LOCALE_ID = new Locale("id");
-    private static final Locale LOCALE_TH = new Locale("ht");
-    private static final Locale LOCALE_TH_TH = new Locale("ht", "TH");
-    private static final Locale LOCALE_TH_TH_TH = new Locale("ht", "TH", "TH");
     private static final String SUBTYPE_MODE_KEYBOARD = "keyboard";
     private static final String SUBTYPE_MODE_VOICE = "voice";
     private static final String SUBTYPE_MODE_HANDWRITING = "handwriting";
@@ -1087,122 +1084,6 @@
     }
 
     @Test
-    public void testGetSuitableLocalesForSpellChecker() throws Exception {
-        {
-            final ArrayList<Locale> locales =
-                    InputMethodUtils.getSuitableLocalesForSpellChecker(LOCALE_EN_US);
-            assertEquals(3, locales.size());
-            assertEquals(LOCALE_EN_US, locales.get(0));
-            assertEquals(LOCALE_EN_GB, locales.get(1));
-            assertEquals(LOCALE_EN, locales.get(2));
-        }
-
-        {
-            final ArrayList<Locale> locales =
-                    InputMethodUtils.getSuitableLocalesForSpellChecker(LOCALE_EN_GB);
-            assertEquals(3, locales.size());
-            assertEquals(LOCALE_EN_GB, locales.get(0));
-            assertEquals(LOCALE_EN_US, locales.get(1));
-            assertEquals(LOCALE_EN, locales.get(2));
-        }
-
-        {
-            final ArrayList<Locale> locales =
-                    InputMethodUtils.getSuitableLocalesForSpellChecker(LOCALE_EN);
-            assertEquals(3, locales.size());
-            assertEquals(LOCALE_EN, locales.get(0));
-            assertEquals(LOCALE_EN_US, locales.get(1));
-            assertEquals(LOCALE_EN_GB, locales.get(2));
-        }
-
-        {
-            final ArrayList<Locale> locales =
-                    InputMethodUtils.getSuitableLocalesForSpellChecker(LOCALE_EN_IN);
-            assertEquals(4, locales.size());
-            assertEquals(LOCALE_EN_IN, locales.get(0));
-            assertEquals(LOCALE_EN_US, locales.get(1));
-            assertEquals(LOCALE_EN_GB, locales.get(2));
-            assertEquals(LOCALE_EN, locales.get(3));
-        }
-
-        {
-            final ArrayList<Locale> locales =
-                    InputMethodUtils.getSuitableLocalesForSpellChecker(LOCALE_JA_JP);
-            assertEquals(5, locales.size());
-            assertEquals(LOCALE_JA_JP, locales.get(0));
-            assertEquals(LOCALE_JA, locales.get(1));
-            assertEquals(LOCALE_EN_US, locales.get(2));
-            assertEquals(LOCALE_EN_GB, locales.get(3));
-            assertEquals(Locale.ENGLISH, locales.get(4));
-        }
-
-        // Test 3-letter language code.
-        {
-            final ArrayList<Locale> locales =
-                    InputMethodUtils.getSuitableLocalesForSpellChecker(LOCALE_FIL_PH);
-            assertEquals(5, locales.size());
-            assertEquals(LOCALE_FIL_PH, locales.get(0));
-            assertEquals(LOCALE_FIL, locales.get(1));
-            assertEquals(LOCALE_EN_US, locales.get(2));
-            assertEquals(LOCALE_EN_GB, locales.get(3));
-            assertEquals(Locale.ENGLISH, locales.get(4));
-        }
-
-        // Test variant.
-        {
-            final ArrayList<Locale> locales =
-                    InputMethodUtils.getSuitableLocalesForSpellChecker(LOCALE_TH_TH_TH);
-            assertEquals(6, locales.size());
-            assertEquals(LOCALE_TH_TH_TH, locales.get(0));
-            assertEquals(LOCALE_TH_TH, locales.get(1));
-            assertEquals(LOCALE_TH, locales.get(2));
-            assertEquals(LOCALE_EN_US, locales.get(3));
-            assertEquals(LOCALE_EN_GB, locales.get(4));
-            assertEquals(Locale.ENGLISH, locales.get(5));
-        }
-
-        // Test Locale extension.
-        {
-            final Locale localeWithoutVariant = LOCALE_JA_JP;
-            final Locale localeWithVariant = new Locale.Builder()
-                    .setLocale(LOCALE_JA_JP)
-                    .setExtension('x', "android")
-                    .build();
-            assertFalse(localeWithoutVariant.equals(localeWithVariant));
-
-            final ArrayList<Locale> locales =
-                    InputMethodUtils.getSuitableLocalesForSpellChecker(localeWithVariant);
-            assertEquals(5, locales.size());
-            assertEquals(LOCALE_JA_JP, locales.get(0));
-            assertEquals(LOCALE_JA, locales.get(1));
-            assertEquals(LOCALE_EN_US, locales.get(2));
-            assertEquals(LOCALE_EN_GB, locales.get(3));
-            assertEquals(Locale.ENGLISH, locales.get(4));
-        }
-    }
-
-    @Test
-    public void testConstructLocaleFromString() throws Exception {
-        assertEquals(new Locale("en"), InputMethodUtils.constructLocaleFromString("en"));
-        assertEquals(new Locale("en", "US"), InputMethodUtils.constructLocaleFromString("en_US"));
-        assertEquals(new Locale("en", "US", "POSIX"),
-                InputMethodUtils.constructLocaleFromString("en_US_POSIX"));
-
-        // Special rewrite rule for "tl" for versions of Android earlier than Lollipop that did not
-        // support three letter language codes, and used "tl" (Tagalog) as the language string for
-        // "fil" (Filipino).
-        assertEquals(new Locale("fil"), InputMethodUtils.constructLocaleFromString("tl"));
-        assertEquals(new Locale("fil", "PH"), InputMethodUtils.constructLocaleFromString("tl_PH"));
-        assertEquals(new Locale("fil", "PH", "POSIX"),
-                InputMethodUtils.constructLocaleFromString("tl_PH_POSIX"));
-
-        // So far rejecting an invalid/unexpected locale string is out of the scope of this method.
-        assertEquals(new Locale("a"), InputMethodUtils.constructLocaleFromString("a"));
-        assertEquals(new Locale("a b c"), InputMethodUtils.constructLocaleFromString("a b c"));
-        assertEquals(new Locale("en-US"), InputMethodUtils.constructLocaleFromString("en-US"));
-    }
-
-    @Test
     public void testIsSoftInputModeStateVisibleAllowed() {
         // On pre-P devices, SOFT_INPUT_STATE_VISIBLE/SOFT_INPUT_STATE_ALWAYS_VISIBLE are always
         // allowed, regardless of the focused view state.
diff --git a/core/tests/coretests/src/com/android/internal/inputmethod/LocaleUtilsTest.java b/services/tests/servicestests/src/com/android/server/inputmethod/LocaleUtilsTest.java
similarity index 98%
rename from core/tests/coretests/src/com/android/internal/inputmethod/LocaleUtilsTest.java
rename to services/tests/servicestests/src/com/android/server/inputmethod/LocaleUtilsTest.java
index 549511a..3fc0e4f 100644
--- a/core/tests/coretests/src/com/android/internal/inputmethod/LocaleUtilsTest.java
+++ b/services/tests/servicestests/src/com/android/server/inputmethod/LocaleUtilsTest.java
@@ -14,13 +14,14 @@
  * limitations under the License.
  */
 
-package com.android.internal.inputmethod;
+package com.android.server.inputmethod;
 
 import static org.junit.Assert.assertEquals;
 
 import android.os.LocaleList;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
index ee41c0b..c3c0788 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
@@ -716,9 +716,9 @@
         assertNotSame(origPkgSetting.mPermissionsState, testPkgSetting.mPermissionsState);
         assertThat(origPkgSetting.mPermissionsState, is(testPkgSetting.mPermissionsState));
         assertThat(origPkgSetting.name, is(testPkgSetting.name));
-        // oldCodePaths is _not_ copied
-        // assertNotSame(origPkgSetting.oldCodePaths, testPkgSetting.oldCodePaths);
-        // assertThat(origPkgSetting.oldCodePaths, is(not(testPkgSetting.oldCodePaths)));
+        // mOldCodePaths is _not_ copied
+        // assertNotSame(origPkgSetting.mOldCodePaths, testPkgSetting.mOldCodePaths);
+        // assertThat(origPkgSetting.mOldCodePaths, is(not(testPkgSetting.mOldCodePaths)));
         assertSame(origPkgSetting.parentPackageName, testPkgSetting.parentPackageName);
         assertThat(origPkgSetting.parentPackageName, is(testPkgSetting.parentPackageName));
         assertSame(origPkgSetting.pkg, testPkgSetting.pkg);
diff --git a/core/tests/coretests/src/com/android/internal/textservice/LazyIntToIntMapTest.java b/services/tests/servicestests/src/com/android/server/textservices/LazyIntToIntMapTest.java
similarity index 95%
rename from core/tests/coretests/src/com/android/internal/textservice/LazyIntToIntMapTest.java
rename to services/tests/servicestests/src/com/android/server/textservices/LazyIntToIntMapTest.java
index 3518527..f80afb2 100644
--- a/core/tests/coretests/src/com/android/internal/textservice/LazyIntToIntMapTest.java
+++ b/services/tests/servicestests/src/com/android/server/textservices/LazyIntToIntMapTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.internal.textservice;
+package com.android.server.textservices;
 
 import static org.junit.Assert.assertEquals;
 import static org.mockito.ArgumentMatchers.anyInt;
@@ -25,8 +25,8 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/services/tests/servicestests/src/com/android/server/textservices/LocaleUtilsTest.java b/services/tests/servicestests/src/com/android/server/textservices/LocaleUtilsTest.java
new file mode 100644
index 0000000..3766d24
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/textservices/LocaleUtilsTest.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.textservices;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.Locale;
+
+public class LocaleUtilsTest {
+    private static final Locale LOCALE_EN = new Locale("en");
+    private static final Locale LOCALE_EN_US = new Locale("en", "US");
+    private static final Locale LOCALE_EN_GB = new Locale("en", "GB");
+    private static final Locale LOCALE_EN_IN = new Locale("en", "IN");
+    private static final Locale LOCALE_FIL = new Locale("fil");
+    private static final Locale LOCALE_FIL_PH = new Locale("fil", "PH");
+    private static final Locale LOCALE_JA = new Locale("ja");
+    private static final Locale LOCALE_JA_JP = new Locale("ja", "JP");
+    private static final Locale LOCALE_TH = new Locale("ht");
+    private static final Locale LOCALE_TH_TH = new Locale("ht", "TH");
+    private static final Locale LOCALE_TH_TH_TH = new Locale("ht", "TH", "TH");
+
+    @Test
+    public void testGetSuitableLocalesForSpellChecker() throws Exception {
+        {
+            final ArrayList<Locale> locales =
+                    LocaleUtils.getSuitableLocalesForSpellChecker(LOCALE_EN_US);
+            assertEquals(3, locales.size());
+            assertEquals(LOCALE_EN_US, locales.get(0));
+            assertEquals(LOCALE_EN_GB, locales.get(1));
+            assertEquals(LOCALE_EN, locales.get(2));
+        }
+
+        {
+            final ArrayList<Locale> locales =
+                    LocaleUtils.getSuitableLocalesForSpellChecker(LOCALE_EN_GB);
+            assertEquals(3, locales.size());
+            assertEquals(LOCALE_EN_GB, locales.get(0));
+            assertEquals(LOCALE_EN_US, locales.get(1));
+            assertEquals(LOCALE_EN, locales.get(2));
+        }
+
+        {
+            final ArrayList<Locale> locales =
+                    LocaleUtils.getSuitableLocalesForSpellChecker(LOCALE_EN);
+            assertEquals(3, locales.size());
+            assertEquals(LOCALE_EN, locales.get(0));
+            assertEquals(LOCALE_EN_US, locales.get(1));
+            assertEquals(LOCALE_EN_GB, locales.get(2));
+        }
+
+        {
+            final ArrayList<Locale> locales =
+                    LocaleUtils.getSuitableLocalesForSpellChecker(LOCALE_EN_IN);
+            assertEquals(4, locales.size());
+            assertEquals(LOCALE_EN_IN, locales.get(0));
+            assertEquals(LOCALE_EN_US, locales.get(1));
+            assertEquals(LOCALE_EN_GB, locales.get(2));
+            assertEquals(LOCALE_EN, locales.get(3));
+        }
+
+        {
+            final ArrayList<Locale> locales =
+                    LocaleUtils.getSuitableLocalesForSpellChecker(LOCALE_JA_JP);
+            assertEquals(5, locales.size());
+            assertEquals(LOCALE_JA_JP, locales.get(0));
+            assertEquals(LOCALE_JA, locales.get(1));
+            assertEquals(LOCALE_EN_US, locales.get(2));
+            assertEquals(LOCALE_EN_GB, locales.get(3));
+            assertEquals(Locale.ENGLISH, locales.get(4));
+        }
+
+        // Test 3-letter language code.
+        {
+            final ArrayList<Locale> locales =
+                    LocaleUtils.getSuitableLocalesForSpellChecker(LOCALE_FIL_PH);
+            assertEquals(5, locales.size());
+            assertEquals(LOCALE_FIL_PH, locales.get(0));
+            assertEquals(LOCALE_FIL, locales.get(1));
+            assertEquals(LOCALE_EN_US, locales.get(2));
+            assertEquals(LOCALE_EN_GB, locales.get(3));
+            assertEquals(Locale.ENGLISH, locales.get(4));
+        }
+
+        // Test variant.
+        {
+            final ArrayList<Locale> locales =
+                    LocaleUtils.getSuitableLocalesForSpellChecker(LOCALE_TH_TH_TH);
+            assertEquals(6, locales.size());
+            assertEquals(LOCALE_TH_TH_TH, locales.get(0));
+            assertEquals(LOCALE_TH_TH, locales.get(1));
+            assertEquals(LOCALE_TH, locales.get(2));
+            assertEquals(LOCALE_EN_US, locales.get(3));
+            assertEquals(LOCALE_EN_GB, locales.get(4));
+            assertEquals(Locale.ENGLISH, locales.get(5));
+        }
+
+        // Test Locale extension.
+        {
+            final Locale localeWithoutVariant = LOCALE_JA_JP;
+            final Locale localeWithVariant = new Locale.Builder()
+                    .setLocale(LOCALE_JA_JP)
+                    .setExtension('x', "android")
+                    .build();
+            assertFalse(localeWithoutVariant.equals(localeWithVariant));
+
+            final ArrayList<Locale> locales =
+                    LocaleUtils.getSuitableLocalesForSpellChecker(localeWithVariant);
+            assertEquals(5, locales.size());
+            assertEquals(LOCALE_JA_JP, locales.get(0));
+            assertEquals(LOCALE_JA, locales.get(1));
+            assertEquals(LOCALE_EN_US, locales.get(2));
+            assertEquals(LOCALE_EN_GB, locales.get(3));
+            assertEquals(Locale.ENGLISH, locales.get(4));
+        }
+    }
+}
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/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index a1b3b98..4344285 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -519,8 +519,9 @@
         NotificationChannel channel = new NotificationChannel("id", "name",
                 IMPORTANCE_HIGH);
         NotificationRecord r = generateNotificationRecord(channel);
-        assertTrue(mService.isBlocked(r, mUsageStats));
-        verify(mUsageStats, times(1)).registerSuspendedByAdmin(eq(r));
+
+        // isBlocked is only used for user blocking, not app suspension
+        assertFalse(mService.isBlocked(r, mUsageStats));
     }
 
     @Test
@@ -3453,4 +3454,46 @@
             // 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/usb/java/com/android/server/usb/UsbHostManager.java b/services/usb/java/com/android/server/usb/UsbHostManager.java
index 589bcdc..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);
@@ -513,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/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/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
index 1ff5fc6..ce63ff9 100755
--- a/startop/scripts/app_startup/run_app_with_prefetch
+++ b/startop/scripts/app_startup/run_app_with_prefetch
@@ -92,8 +92,7 @@
         shift
         ;;
       --compiler-filter)
-        # ignore any '--compiler-filter xyz' settings.
-        # FIXME: app_startup_runner.py should not be passing this flag.
+        compiler_filter="$2"
         shift
         ;;
       *)
@@ -194,9 +193,6 @@
 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"
@@ -286,6 +282,47 @@
   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 "=========================================="
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/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/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/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 8ebfec4..b01d419 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -41,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;
@@ -191,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;
 
     /**
@@ -1610,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();
     }
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 2ac0afe..fa24796 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;
@@ -702,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";
 
@@ -1499,23 +1500,24 @@
                 Rlog.d(TAG, "getCellLocation returning null because telephony is null");
                 return null;
             }
+
             Bundle bundle = telephony.getCellLocation(mContext.getOpPackageName());
-            if (bundle.isEmpty()) {
-                Rlog.d(TAG, "getCellLocation returning null because bundle is empty");
+            if (bundle == null || bundle.isEmpty()) {
+                Rlog.d(TAG, "getCellLocation returning null because CellLocation is unavailable");
                 return null;
             }
+
             CellLocation cl = CellLocation.newFromBundle(bundle);
-            if (cl.isEmpty()) {
-                Rlog.d(TAG, "getCellLocation returning null because CellLocation is empty");
+            if (cl == null || cl.isEmpty()) {
+                Rlog.d(TAG, "getCellLocation returning null because CellLocation is empty or"
+                        + " phone type doesn't match CellLocation type");
                 return null;
             }
+
             return cl;
         } catch (RemoteException ex) {
             Rlog.d(TAG, "getCellLocation returning null due to RemoteException " + ex);
             return null;
-        } catch (NullPointerException ex) {
-            Rlog.d(TAG, "getCellLocation returning null due to NullPointerException " + ex);
-            return null;
         }
     }
 
@@ -1690,7 +1692,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);
diff --git a/tests/SystemMemoryTest/host/src/com/android/tests/sysmem/host/Cujs.java b/tests/SystemMemoryTest/host/src/com/android/tests/sysmem/host/Cujs.java
index 579d972..1b63874 100644
--- a/tests/SystemMemoryTest/host/src/com/android/tests/sysmem/host/Cujs.java
+++ b/tests/SystemMemoryTest/host/src/com/android/tests/sysmem/host/Cujs.java
@@ -11,7 +11,7 @@
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
  */
 
 package com.android.tests.sysmem.host;
@@ -24,10 +24,10 @@
  * host.
  */
 public class Cujs {
-    private ITestDevice device;
+    private ITestDevice mDevice;
 
     public Cujs(ITestDevice device) {
-        this.device = device;
+        this.mDevice = device;
     }
 
     /**
@@ -38,6 +38,6 @@
         // TODO: Consider exercising the system in other interesting ways as
         // well.
         String command = "am instrument -w com.android.tests.sysmem.device/.Cujs";
-        device.executeShellCommand(command);
+        mDevice.executeShellCommand(command);
     }
 }
diff --git a/tests/SystemMemoryTest/host/src/com/android/tests/sysmem/host/MemoryTest.java b/tests/SystemMemoryTest/host/src/com/android/tests/sysmem/host/MemoryTest.java
index bbec065..cfd598d 100644
--- a/tests/SystemMemoryTest/host/src/com/android/tests/sysmem/host/MemoryTest.java
+++ b/tests/SystemMemoryTest/host/src/com/android/tests/sysmem/host/MemoryTest.java
@@ -11,7 +11,7 @@
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
  */
 
 package com.android.tests.sysmem.host;
@@ -22,46 +22,54 @@
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner.TestLogData;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner.TestMetrics;
 import com.android.tradefed.testtype.IDeviceTest;
-import java.io.IOException;
+
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.io.IOException;
+
+/**
+ * Runs a system memory test.
+ */
 @RunWith(DeviceJUnit4ClassRunner.class)
 public class MemoryTest implements IDeviceTest {
 
     @Rule public TestMetrics testMetrics = new TestMetrics();
     @Rule public TestLogData testLogs = new TestLogData();
 
-    private ITestDevice testDevice;
-    private int iterations = 0;     // Number of times cujs have been run.
-    private Metrics metrics;
-    private Cujs cujs;
+    private ITestDevice mTestDevice;
+    private int mIterations = 0;     // Number of times cujs have been run.
+    private Metrics mMetrics;
+    private Cujs mCujs;
 
     @Override
     public void setDevice(ITestDevice device) {
-        testDevice = device;
-        metrics = new Metrics(device, testMetrics, testLogs);
-        cujs = new Cujs(device);
+        mTestDevice = device;
+        mMetrics = new Metrics(device, testMetrics, testLogs);
+        mCujs = new Cujs(device);
     }
 
     @Override
     public ITestDevice getDevice() {
-        return testDevice;
+        return mTestDevice;
     }
 
     // Invoke a single iteration of running the cujs.
     private void runCujs() throws DeviceNotAvailableException {
-        cujs.run();
-        iterations++;
+        mCujs.run();
+        mIterations++;
     }
 
     // Sample desired memory.
     private void sample()
             throws DeviceNotAvailableException, IOException, Metrics.MetricsException {
-        metrics.sample(String.format("%03d", iterations));
+        mMetrics.sample(String.format("%03d", mIterations));
     }
 
+    /**
+     * Runs the memory tests.
+     */
     @Test
     public void run() throws Exception {
         sample();   // Sample before running cujs
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 616983e..70bc22c 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
@@ -11,7 +11,7 @@
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
  */
 
 package com.android.tests.sysmem.host;
@@ -22,6 +22,7 @@
 import com.android.tradefed.result.LogDataType;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner.TestLogData;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner.TestMetrics;
+
 import java.io.File;
 import java.io.IOException;
 import java.io.PrintStream;
@@ -33,15 +34,15 @@
  */
 class Metrics {
 
-    private ITestDevice device;
-    private TestMetrics metrics;
-    private TestLogData logs;
+    private ITestDevice mDevice;
+    private TestMetrics mMetrics;
+    private TestLogData mLogs;
 
     /**
      * Exception thrown in case of error sampling metrics.
      */
     public static class MetricsException extends Exception {
-        public MetricsException(String msg) {
+        MetricsException(String msg) {
             super(msg);
         }
 
@@ -59,22 +60,22 @@
      * @param metrics where to log the high level metrics when taking a sample
      * @param logs where to log detailed breakdowns when taking a sample
      */
-    public Metrics(ITestDevice device, TestMetrics metrics, TestLogData logs) {
-        this.device = device;
-        this.metrics = metrics;
-        this.logs = logs;
+    Metrics(ITestDevice device, TestMetrics metrics, TestLogData logs) {
+        this.mDevice = device;
+        this.mMetrics = metrics;
+        this.mLogs = logs;
     }
 
     /**
      * 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);
-      }
+        File file = File.createTempFile(label, "txt");
+        PrintStream ps = new PrintStream(file);
+        ps.print(text);
+        try (FileInputStreamSource dataStream = new FileInputStreamSource(file)) {
+            mLogs.addTestLog(label, LogDataType.TEXT, dataStream);
+        }
     }
 
     /**
@@ -82,11 +83,11 @@
      */
     private int getPidForProcess(String name)
             throws DeviceNotAvailableException, IOException, MetricsException {
-        String psout = device.executeShellCommand("ps -A -o PID,CMD");
+        String psout = mDevice.executeShellCommand("ps -A -o PID,CMD");
         Scanner sc = new Scanner(psout);
         try {
             // ps output is of the form:
-            //  PID CMD            
+            //  PID CMD
             //    1 init
             //    2 kthreadd
             //    ...
@@ -117,20 +118,22 @@
      */
     void sample(String label) throws DeviceNotAvailableException, IOException, MetricsException {
         // adb root access is required to get showmap
-        device.enableAdbRoot();
+        mDevice.enableAdbRoot();
 
         int pid = getPidForProcess("system_server");
 
         // Read showmap for system server and add it as a test log
-        String showmap = device.executeShellCommand("showmap " + pid);
+        String showmap = mDevice.executeShellCommand("showmap " + pid);
         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:
+        // CHECKSTYLE:OFF Generated code
         // virtual                     shared   shared  private  private
         //    size      RSS      PSS    clean    dirty    clean    dirty     swap  swapPSS   # object
         //-------- -------- -------- -------- -------- -------- -------- -------- -------- ---- ------------------------------
         //  928480   113016    24860    87348     7916     3632    14120     1968     1968 1900 TOTAL
+        // CHECKSTYLE:ON Generated code
         try {
             int pos = showmap.lastIndexOf("----");
             Scanner sc = new Scanner(showmap.substring(pos));
@@ -139,16 +142,16 @@
             long rss = sc.nextLong();
             long pss = sc.nextLong();
 
-            metrics.addTestMetric(String.format("%s.system_server.vss", label), Long.toString(vss));
-            metrics.addTestMetric(String.format("%s.system_server.rss", label), Long.toString(rss));
-            metrics.addTestMetric(String.format("%s.system_server.pss", label), Long.toString(pss));
+            mMetrics.addTestMetric(label + ".system_server.vss", Long.toString(vss));
+            mMetrics.addTestMetric(label + ".system_server.rss", Long.toString(rss));
+            mMetrics.addTestMetric(label + ".system_server.pss", Long.toString(pss));
         } catch (InputMismatchException e) {
             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);
+        String debuggerd = mDevice.executeShellCommand("debuggerd -j " + pid);
         logText(label + ".system_server.debuggerd", debuggerd);
 
         // TODO: Experiment with other additional metrics.
diff --git a/tools/aapt2/StringPool_test.cpp b/tools/aapt2/StringPool_test.cpp
index 0778564..9a7238b 100644
--- a/tools/aapt2/StringPool_test.cpp
+++ b/tools/aapt2/StringPool_test.cpp
@@ -303,7 +303,7 @@
   }
 }
 
-TEST(StringPoolTest, FlattenModifiedUTF8) {
+TEST(StringPoolTest, ModifiedUTF8) {
   using namespace android;  // For NO_ERROR on Windows.
   StdErrDiagnostics diag;
   StringPool pool;
@@ -315,12 +315,24 @@
   StringPool::FlattenUtf8(&buffer, pool, &diag);
   std::unique_ptr<uint8_t[]> data = util::Copy(buffer);
 
-  // Check that the 4 byte utf-8 codepoint is encoded using 2 3 byte surrogate pairs
+  // Check that the codepoints are encoded using two three-byte surrogate pairs
   ResStringPool test;
   ASSERT_EQ(test.setTo(data.get(), buffer.size()), NO_ERROR);
-  EXPECT_THAT(util::GetString(test, 0), Eq("\xED\xA0\x81\xED\xB0\x80"));
-  EXPECT_THAT(util::GetString(test, 1), Eq("foo \xED\xA0\x81\xED\xB0\xB7 bar"));
-  EXPECT_THAT(util::GetString(test, 2), Eq("\xED\xA0\x81\xED\xB0\x80\xED\xA0\x81\xED\xB0\xB7"));
+  size_t len;
+  const char* str = test.string8At(0, &len);
+  ASSERT_THAT(str, NotNull());
+  EXPECT_THAT(std::string(str, len), Eq("\xED\xA0\x81\xED\xB0\x80"));
+  str = test.string8At(1, &len);
+  ASSERT_THAT(str, NotNull());
+  EXPECT_THAT(std::string(str, len), Eq("foo \xED\xA0\x81\xED\xB0\xB7 bar"));
+  str = test.string8At(2, &len);
+  ASSERT_THAT(str, NotNull());
+  EXPECT_THAT(std::string(str, len), Eq("\xED\xA0\x81\xED\xB0\x80\xED\xA0\x81\xED\xB0\xB7"));
+
+  // Check that retrieving the strings returns the original UTF-8 character bytes
+  EXPECT_THAT(util::GetString(test, 0), Eq("\xF0\x90\x90\x80"));
+  EXPECT_THAT(util::GetString(test, 1), Eq("foo \xF0\x90\x90\xB7 bar"));
+  EXPECT_THAT(util::GetString(test, 2), Eq("\xF0\x90\x90\x80\xF0\x90\x90\xB7"));
 }
 
 TEST(StringPoolTest, MaxEncodingLength) {
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/Util.cpp b/tools/aapt2/util/Util.cpp
index 9bef54e5..59b7fff 100644
--- a/tools/aapt2/util/Util.cpp
+++ b/tools/aapt2/util/Util.cpp
@@ -322,11 +322,11 @@
   output.reserve(modified_size);
   for (size_t i = 0; i < size; i++) {
     if (((uint8_t) utf8[i] >> 4) == 0xF) {
-      auto codepoint = (char32_t) utf32_from_utf8_at(utf8.data(), size, i, nullptr);
+      int32_t codepoint = utf32_from_utf8_at(utf8.data(), size, i, nullptr);
 
       // Calculate the high and low surrogates as UTF-16 would
-      char32_t high = ((codepoint - 0x10000) / 0x400) + 0xD800;
-      char32_t low = ((codepoint - 0x10000) % 0x400) + 0xDC00;
+      int32_t high = ((codepoint - 0x10000) / 0x400) + 0xD800;
+      int32_t low = ((codepoint - 0x10000) % 0x400) + 0xDC00;
 
       // Encode each surrogate in UTF-8
       output.push_back((char) (0xE4 | ((high >> 12) & 0xF)));
@@ -344,6 +344,60 @@
   return output;
 }
 
+std::string ModifiedUtf8ToUtf8(const std::string& modified_utf8) {
+  // The UTF-8 representation will have a byte length less than or equal to the Modified UTF-8
+  // representation.
+  std::string output;
+  output.reserve(modified_utf8.size());
+
+  size_t index = 0;
+  const size_t modified_size = modified_utf8.size();
+  while (index < modified_size) {
+    size_t next_index;
+    int32_t high_surrogate = utf32_from_utf8_at(modified_utf8.data(), modified_size, index,
+                                                &next_index);
+    if (high_surrogate < 0) {
+      return {};
+    }
+
+    // Check that the first codepoint is within the high surrogate range
+    if (high_surrogate >= 0xD800 && high_surrogate <= 0xDB7F) {
+      int32_t low_surrogate = utf32_from_utf8_at(modified_utf8.data(), modified_size, next_index,
+                                                 &next_index);
+      if (low_surrogate < 0) {
+        return {};
+      }
+
+      // Check that the second codepoint is within the low surrogate range
+      if (low_surrogate >= 0xDC00 && low_surrogate <= 0xDFFF) {
+        const char32_t codepoint = (char32_t) (((high_surrogate - 0xD800) * 0x400)
+            + (low_surrogate - 0xDC00) + 0x10000);
+
+        // The decoded codepoint should represent a 4 byte, UTF-8 character
+        const size_t utf8_length = (size_t) utf32_to_utf8_length(&codepoint, 1);
+        if (utf8_length != 4) {
+          return {};
+        }
+
+        // Encode the UTF-8 representation of the codepoint into the string
+        char* start = &output[output.size()];
+        output.resize(output.size() + utf8_length);
+        utf32_to_utf8((char32_t*) &codepoint, 1, start, utf8_length + 1);
+
+        index = next_index;
+        continue;
+      }
+    }
+
+    // Append non-surrogate pairs to the output string
+    for (size_t i = index; i < next_index; i++) {
+      output.push_back(modified_utf8[i]);
+    }
+    index = next_index;
+  }
+  return output;
+}
+
 std::u16string Utf8ToUtf16(const StringPiece& utf8) {
   ssize_t utf16_length = utf8_to_utf16_length(
       reinterpret_cast<const uint8_t*>(utf8.data()), utf8.length());
@@ -469,7 +523,7 @@
   size_t len;
   const char* str = pool.string8At(idx, &len);
   if (str != nullptr) {
-    return std::string(str, len);
+    return ModifiedUtf8ToUtf8(std::string(str, len));
   }
   return Utf16ToUtf8(GetString16(pool, idx));
 }
diff --git a/tools/aapt2/util/Util.h b/tools/aapt2/util/Util.h
index 36b7333..c6e8e6e 100644
--- a/tools/aapt2/util/Util.h
+++ b/tools/aapt2/util/Util.h
@@ -199,6 +199,7 @@
 
 // Converts a UTF8 string into Modified UTF8
 std::string Utf8ToModifiedUtf8(const std::string& utf8);
+std::string ModifiedUtf8ToUtf8(const std::string& modified_utf8);
 
 // Converts a UTF8 string to a UTF16 string.
 std::u16string Utf8ToUtf16(const android::StringPiece& utf8);
diff --git a/tools/apilint/apilint.py b/tools/apilint/apilint.py
index 018e9c9..934847f 100644
--- a/tools/apilint/apilint.py
+++ b/tools/apilint/apilint.py
@@ -697,8 +697,8 @@
         "android.provider",
         ["android.content","android.graphics.drawable"],
         "android.database",
-        "android.graphics",
         "android.text",
+        "android.graphics",
         "android.os",
         "android.util"
     ]
diff --git a/tools/hiddenapi/sort_api.sh b/tools/hiddenapi/sort_api.sh
index bdcc807..76a2f2d 100755
--- a/tools/hiddenapi/sort_api.sh
+++ b/tools/hiddenapi/sort_api.sh
@@ -12,8 +12,8 @@
 # Sort
 IFS=$'\n'
 # Stash away comments
-C=( $(grep -E '^#' <<< "${A[*]}") )
-A=( $(grep -v -E '^#' <<< "${A[*]}") )
+C=( $(grep -E '^#' <<< "${A[*]}" || :) )
+A=( $(grep -v -E '^#' <<< "${A[*]}" || :) )
 # Sort entries
 A=( $(LC_COLLATE=C sort -f <<< "${A[*]}") )
 A=( $(uniq <<< "${A[*]}") )
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;
     }