Merge "Don't get application info for the system" into nyc-dev
diff --git a/api/current.txt b/api/current.txt
index fbbb2e3..53738dc 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -9498,9 +9498,10 @@
   public class LauncherApps {
     method public java.util.List<android.content.pm.LauncherActivityInfo> getActivityList(java.lang.String, android.os.UserHandle);
     method public android.content.pm.ApplicationInfo getApplicationInfo(java.lang.String, int, android.os.UserHandle);
-    method public android.os.ParcelFileDescriptor getShortcutIconFd(android.content.pm.ShortcutInfo, android.os.UserHandle);
-    method public int getShortcutIconResId(android.content.pm.ShortcutInfo, android.os.UserHandle);
-    method public java.util.List<android.content.pm.ShortcutInfo> getShortcutInfo(java.lang.String, java.util.List<java.lang.String>, android.os.UserHandle);
+    method public android.os.ParcelFileDescriptor getShortcutIconFd(android.content.pm.ShortcutInfo);
+    method public android.os.ParcelFileDescriptor getShortcutIconFd(java.lang.String, java.lang.String, android.os.UserHandle);
+    method public int getShortcutIconResId(android.content.pm.ShortcutInfo);
+    method public int getShortcutIconResId(java.lang.String, java.lang.String, android.os.UserHandle);
     method public java.util.List<android.content.pm.ShortcutInfo> getShortcuts(android.content.pm.LauncherApps.ShortcutQuery, android.os.UserHandle);
     method public boolean hasShortcutHostPermission();
     method public boolean isActivityEnabled(android.content.ComponentName, android.os.UserHandle);
@@ -9512,6 +9513,7 @@
     method public void startAppDetailsActivity(android.content.ComponentName, android.os.UserHandle, android.graphics.Rect, android.os.Bundle);
     method public void startMainActivity(android.content.ComponentName, android.os.UserHandle, android.graphics.Rect, android.os.Bundle);
     method public boolean startShortcut(java.lang.String, java.lang.String, android.graphics.Rect, android.os.Bundle, android.os.UserHandle);
+    method public boolean startShortcut(android.content.pm.ShortcutInfo, android.graphics.Rect, android.os.Bundle);
     method public void unregisterCallback(android.content.pm.LauncherApps.Callback);
   }
 
@@ -9533,6 +9535,7 @@
     method public void setChangedSince(long);
     method public void setPackage(java.lang.String);
     method public void setQueryFlags(int);
+    method public void setShortcutIds(java.util.List<java.lang.String>);
     field public static final int FLAG_GET_DYNAMIC = 1; // 0x1
     field public static final int FLAG_GET_KEY_FIELDS_ONLY = 4; // 0x4
     field public static final int FLAG_GET_PINNED = 2; // 0x2
@@ -10046,6 +10049,7 @@
     method public java.lang.String getPackageName();
     method public java.lang.String getText();
     method public java.lang.String getTitle();
+    method public android.os.UserHandle getUserHandle();
     method public int getWeight();
     method public boolean hasIconFile();
     method public boolean hasIconResource();
diff --git a/api/system-current.txt b/api/system-current.txt
index d91f5d1..ea83257 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -9836,9 +9836,10 @@
   public class LauncherApps {
     method public java.util.List<android.content.pm.LauncherActivityInfo> getActivityList(java.lang.String, android.os.UserHandle);
     method public android.content.pm.ApplicationInfo getApplicationInfo(java.lang.String, int, android.os.UserHandle);
-    method public android.os.ParcelFileDescriptor getShortcutIconFd(android.content.pm.ShortcutInfo, android.os.UserHandle);
-    method public int getShortcutIconResId(android.content.pm.ShortcutInfo, android.os.UserHandle);
-    method public java.util.List<android.content.pm.ShortcutInfo> getShortcutInfo(java.lang.String, java.util.List<java.lang.String>, android.os.UserHandle);
+    method public android.os.ParcelFileDescriptor getShortcutIconFd(android.content.pm.ShortcutInfo);
+    method public android.os.ParcelFileDescriptor getShortcutIconFd(java.lang.String, java.lang.String, android.os.UserHandle);
+    method public int getShortcutIconResId(android.content.pm.ShortcutInfo);
+    method public int getShortcutIconResId(java.lang.String, java.lang.String, android.os.UserHandle);
     method public java.util.List<android.content.pm.ShortcutInfo> getShortcuts(android.content.pm.LauncherApps.ShortcutQuery, android.os.UserHandle);
     method public boolean hasShortcutHostPermission();
     method public boolean isActivityEnabled(android.content.ComponentName, android.os.UserHandle);
@@ -9850,6 +9851,7 @@
     method public void startAppDetailsActivity(android.content.ComponentName, android.os.UserHandle, android.graphics.Rect, android.os.Bundle);
     method public void startMainActivity(android.content.ComponentName, android.os.UserHandle, android.graphics.Rect, android.os.Bundle);
     method public boolean startShortcut(java.lang.String, java.lang.String, android.graphics.Rect, android.os.Bundle, android.os.UserHandle);
+    method public boolean startShortcut(android.content.pm.ShortcutInfo, android.graphics.Rect, android.os.Bundle);
     method public void unregisterCallback(android.content.pm.LauncherApps.Callback);
   }
 
@@ -9871,6 +9873,7 @@
     method public void setChangedSince(long);
     method public void setPackage(java.lang.String);
     method public void setQueryFlags(int);
+    method public void setShortcutIds(java.util.List<java.lang.String>);
     field public static final int FLAG_GET_DYNAMIC = 1; // 0x1
     field public static final int FLAG_GET_KEY_FIELDS_ONLY = 4; // 0x4
     field public static final int FLAG_GET_PINNED = 2; // 0x2
@@ -10446,6 +10449,7 @@
     method public java.lang.String getPackageName();
     method public java.lang.String getText();
     method public java.lang.String getTitle();
+    method public android.os.UserHandle getUserHandle();
     method public int getWeight();
     method public boolean hasIconFile();
     method public boolean hasIconResource();
@@ -15491,6 +15495,7 @@
 
   public class NanoApp {
     ctor public NanoApp();
+    ctor public NanoApp(int, byte[]);
     method public int describeContents();
     method public byte[] getAppBinary();
     method public int getAppId();
diff --git a/api/test-current.txt b/api/test-current.txt
index bad9733..caf3231 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -9507,9 +9507,10 @@
   public class LauncherApps {
     method public java.util.List<android.content.pm.LauncherActivityInfo> getActivityList(java.lang.String, android.os.UserHandle);
     method public android.content.pm.ApplicationInfo getApplicationInfo(java.lang.String, int, android.os.UserHandle);
-    method public android.os.ParcelFileDescriptor getShortcutIconFd(android.content.pm.ShortcutInfo, android.os.UserHandle);
-    method public int getShortcutIconResId(android.content.pm.ShortcutInfo, android.os.UserHandle);
-    method public java.util.List<android.content.pm.ShortcutInfo> getShortcutInfo(java.lang.String, java.util.List<java.lang.String>, android.os.UserHandle);
+    method public android.os.ParcelFileDescriptor getShortcutIconFd(android.content.pm.ShortcutInfo);
+    method public android.os.ParcelFileDescriptor getShortcutIconFd(java.lang.String, java.lang.String, android.os.UserHandle);
+    method public int getShortcutIconResId(android.content.pm.ShortcutInfo);
+    method public int getShortcutIconResId(java.lang.String, java.lang.String, android.os.UserHandle);
     method public java.util.List<android.content.pm.ShortcutInfo> getShortcuts(android.content.pm.LauncherApps.ShortcutQuery, android.os.UserHandle);
     method public boolean hasShortcutHostPermission();
     method public boolean isActivityEnabled(android.content.ComponentName, android.os.UserHandle);
@@ -9521,6 +9522,7 @@
     method public void startAppDetailsActivity(android.content.ComponentName, android.os.UserHandle, android.graphics.Rect, android.os.Bundle);
     method public void startMainActivity(android.content.ComponentName, android.os.UserHandle, android.graphics.Rect, android.os.Bundle);
     method public boolean startShortcut(java.lang.String, java.lang.String, android.graphics.Rect, android.os.Bundle, android.os.UserHandle);
+    method public boolean startShortcut(android.content.pm.ShortcutInfo, android.graphics.Rect, android.os.Bundle);
     method public void unregisterCallback(android.content.pm.LauncherApps.Callback);
   }
 
@@ -9542,6 +9544,7 @@
     method public void setChangedSince(long);
     method public void setPackage(java.lang.String);
     method public void setQueryFlags(int);
+    method public void setShortcutIds(java.util.List<java.lang.String>);
     field public static final int FLAG_GET_DYNAMIC = 1; // 0x1
     field public static final int FLAG_GET_KEY_FIELDS_ONLY = 4; // 0x4
     field public static final int FLAG_GET_PINNED = 2; // 0x2
@@ -10056,6 +10059,7 @@
     method public java.lang.String getPackageName();
     method public java.lang.String getText();
     method public java.lang.String getTitle();
+    method public android.os.UserHandle getUserHandle();
     method public int getWeight();
     method public boolean hasIconFile();
     method public boolean hasIconResource();
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 3f9629c8..96757bb 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -2216,7 +2216,9 @@
      *             that uses {@link DeviceAdminInfo#USES_POLICY_RESET_PASSWORD}
      */
     public boolean resetPassword(String password, int flags) {
-        throwIfParentInstance("resetPassword");
+        if (mParentInstance) {
+            throw new SecurityException("Reset password does not work across profiles.");
+        }
         if (mService != null) {
             try {
                 return mService.resetPassword(password, flags);
@@ -2353,7 +2355,6 @@
      *             that uses {@link DeviceAdminInfo#USES_POLICY_WIPE_DATA}
      */
     public void wipeData(int flags) {
-        throwIfParentInstance("wipeData");
         if (mService != null) {
             try {
                 mService.wipeData(flags);
@@ -2387,7 +2388,6 @@
      */
     public ComponentName setGlobalProxy(@NonNull ComponentName admin, Proxy proxySpec,
             List<String> exclusionList ) {
-        throwIfParentInstance("setGlobalProxy");
         if (proxySpec == null) {
             throw new NullPointerException();
         }
@@ -2453,7 +2453,6 @@
      */
     public void setRecommendedGlobalProxy(@NonNull ComponentName admin, @Nullable ProxyInfo
             proxyInfo) {
-        throwIfParentInstance("setRecommendedGlobalProxy");
         if (mService != null) {
             try {
                 mService.setRecommendedGlobalProxy(admin, proxyInfo);
@@ -2604,7 +2603,6 @@
      *             {@link DeviceAdminInfo#USES_ENCRYPTED_STORAGE}
      */
     public int setStorageEncryption(@NonNull ComponentName admin, boolean encrypt) {
-        throwIfParentInstance("setStorageEncryption");
         if (mService != null) {
             try {
                 return mService.setStorageEncryption(admin, encrypt);
@@ -2625,7 +2623,6 @@
      * @return true if the admin(s) are requesting encryption, false if not.
      */
     public boolean getStorageEncryption(@Nullable ComponentName admin) {
-        throwIfParentInstance("getStorageEncryption");
         if (mService != null) {
             try {
                 return mService.getStorageEncryption(admin, myUserId());
@@ -2721,7 +2718,6 @@
      *         owner.
      */
     public boolean installCaCert(@Nullable ComponentName admin, byte[] certBuffer) {
-        throwIfParentInstance("installCaCert");
         if (mService != null) {
             try {
                 return mService.installCaCert(admin, certBuffer);
@@ -2742,7 +2738,6 @@
      *         owner.
      */
     public void uninstallCaCert(@Nullable ComponentName admin, byte[] certBuffer) {
-        throwIfParentInstance("uninstallCaCert");
         if (mService != null) {
             try {
                 final String alias = getCaCertAlias(certBuffer);
@@ -2768,7 +2763,6 @@
      */
     public List<byte[]> getInstalledCaCerts(@Nullable ComponentName admin) {
         List<byte[]> certs = new ArrayList<byte[]>();
-        throwIfParentInstance("getInstalledCaCerts");
         if (mService != null) {
             try {
                 mService.enforceCanManageCaCerts(admin);
@@ -2797,7 +2791,6 @@
      *         owner.
      */
     public void uninstallAllUserCaCerts(@Nullable ComponentName admin) {
-        throwIfParentInstance("uninstallAllUserCaCerts");
         if (mService != null) {
             try {
                 mService.uninstallCaCerts(admin, new TrustedCertificateStore().userAliases()
@@ -2818,7 +2811,6 @@
      *         owner.
      */
     public boolean hasCaCertInstalled(@Nullable ComponentName admin, byte[] certBuffer) {
-        throwIfParentInstance("hasCaCertInstalled");
         if (mService != null) {
             try {
                 mService.enforceCanManageCaCerts(admin);
@@ -2887,7 +2879,6 @@
      */
     public boolean installKeyPair(@Nullable ComponentName admin, @NonNull PrivateKey privKey,
             @NonNull Certificate[] certs, @NonNull String alias, boolean requestAccess) {
-        throwIfParentInstance("installKeyPair");
         try {
             final byte[] pemCert = Credentials.convertToPem(certs[0]);
             byte[] pemChain = null;
@@ -2920,7 +2911,6 @@
      *         owner.
      */
     public boolean removeKeyPair(@Nullable ComponentName admin, @NonNull String alias) {
-        throwIfParentInstance("removeKeyPair");
         try {
             return mService.removeKeyPair(admin, alias);
         } catch (RemoteException e) {
@@ -2961,7 +2951,6 @@
      */
     public void setCertInstallerPackage(@NonNull ComponentName admin, @Nullable String
             installerPackage) throws SecurityException {
-        throwIfParentInstance("setCertInstallerPackage");
         if (mService != null) {
             try {
                 mService.setCertInstallerPackage(admin, installerPackage);
@@ -2981,7 +2970,6 @@
      * @throws SecurityException if {@code admin} is not a device or a profile owner.
      */
     public String getCertInstallerPackage(@NonNull ComponentName admin) throws SecurityException {
-        throwIfParentInstance("getCertInstallerPackage");
         if (mService != null) {
             try {
                 return mService.getCertInstallerPackage(admin);
@@ -3012,7 +3000,6 @@
      */
     public void setAlwaysOnVpnPackage(@NonNull ComponentName admin, @Nullable String vpnPackage)
             throws NameNotFoundException, UnsupportedOperationException {
-        throwIfParentInstance("setAlwaysOnVpnPackage");
         if (mService != null) {
             try {
                 if (!mService.setAlwaysOnVpnPackage(admin, vpnPackage)) {
@@ -3034,7 +3021,6 @@
      * @throws SecurityException if {@code admin} is not a device or a profile owner.
      */
     public String getAlwaysOnVpnPackage(@NonNull ComponentName admin) {
-        throwIfParentInstance("getAlwaysOnVpnPackage");
         if (mService != null) {
             try {
                 return mService.getAlwaysOnVpnPackage(admin);
@@ -3062,7 +3048,6 @@
      *             {@link DeviceAdminInfo#USES_POLICY_DISABLE_CAMERA}.
      */
     public void setCameraDisabled(@NonNull ComponentName admin, boolean disabled) {
-        throwIfParentInstance("setCameraDisabled");
         if (mService != null) {
             try {
                 mService.setCameraDisabled(admin, disabled);
@@ -3079,7 +3064,6 @@
      * have disabled the camera
      */
     public boolean getCameraDisabled(@Nullable ComponentName admin) {
-        throwIfParentInstance("getCameraDisabled");
         return getCameraDisabled(admin, myUserId());
     }
 
@@ -3109,7 +3093,6 @@
      *             than the one managed by the device owner.
      */
     public boolean requestBugreport(@NonNull ComponentName admin) {
-        throwIfParentInstance("requestBugreport");
         if (mService != null) {
             try {
                 return mService.requestBugreport(admin);
@@ -3148,7 +3131,6 @@
      * @throws SecurityException if {@code admin} is not a device or profile owner.
      */
     public void setScreenCaptureDisabled(@NonNull ComponentName admin, boolean disabled) {
-        throwIfParentInstance("setScreenCaptureDisabled");
         if (mService != null) {
             try {
                 mService.setScreenCaptureDisabled(admin, disabled);
@@ -3165,7 +3147,6 @@
      * have disabled screen capture.
      */
     public boolean getScreenCaptureDisabled(@Nullable ComponentName admin) {
-        throwIfParentInstance("getScreenCaptureDisabled");
         return getScreenCaptureDisabled(admin, myUserId());
     }
 
@@ -3195,7 +3176,6 @@
      * @throws SecurityException if {@code admin} is not a device owner.
      */
     public void setAutoTimeRequired(@NonNull ComponentName admin, boolean required) {
-        throwIfParentInstance("setAutoTimeRequired");
         if (mService != null) {
             try {
                 mService.setAutoTimeRequired(admin, required);
@@ -3209,7 +3189,6 @@
      * @return true if auto time is required.
      */
     public boolean getAutoTimeRequired() {
-        throwIfParentInstance("getAutoTimeRequired");
         if (mService != null) {
             try {
                 return mService.getAutoTimeRequired();
@@ -3236,7 +3215,6 @@
      */
     public void setForceEphemeralUsers(
             @NonNull ComponentName admin, boolean forceEphemeralUsers) {
-        throwIfParentInstance("setForceEphemeralUsers");
         if (mService != null) {
             try {
                 mService.setForceEphemeralUsers(admin, forceEphemeralUsers);
@@ -3252,7 +3230,6 @@
      * @hide
      */
     public boolean getForceEphemeralUsers(@NonNull ComponentName admin) {
-        throwIfParentInstance("getForceEphemeralUsers");
         if (mService != null) {
             try {
                 return mService.getForceEphemeralUsers(admin);
@@ -3540,7 +3517,6 @@
      * @return whether or not the package is registered as the device owner app.
      */
     public boolean isDeviceOwnerApp(String packageName) {
-        throwIfParentInstance("isDeviceOwnerApp");
         return isDeviceOwnerAppOnCallingUser(packageName);
     }
 
@@ -3638,7 +3614,6 @@
      *             does not own the current device owner component.
      */
     public void clearDeviceOwnerApp(String packageName) {
-        throwIfParentInstance("clearDeviceOwnerApp");
         if (mService != null) {
             try {
                 mService.clearDeviceOwner(packageName);
@@ -3756,7 +3731,6 @@
      * @throws SecurityException if {@code admin} is not an active profile owner.
      */
     public void clearProfileOwner(@NonNull ComponentName admin) {
-        throwIfParentInstance("clearProfileOwner");
         if (mService != null) {
             try {
                 mService.clearProfileOwner(admin);
@@ -3830,7 +3804,6 @@
      * @throws SecurityException if {@code admin} is not a device owner.
      */
     public void setDeviceOwnerLockScreenInfo(@NonNull ComponentName admin, CharSequence info) {
-        throwIfParentInstance("setDeviceOwnerLockScreenInfo");
         if (mService != null) {
             try {
                 mService.setDeviceOwnerLockScreenInfo(admin, info);
@@ -3844,7 +3817,6 @@
      * @return The device owner information. If it is not set returns {@code null}.
      */
     public CharSequence getDeviceOwnerLockScreenInfo() {
-        throwIfParentInstance("getDeviceOwnerLockScreenInfo");
         if (mService != null) {
             try {
                 return mService.getDeviceOwnerLockScreenInfo();
@@ -3876,7 +3848,6 @@
      */
     public String[] setPackagesSuspended(@NonNull ComponentName admin, String[] packageNames,
             boolean suspended) {
-        throwIfParentInstance("setPackagesSuspended");
         if (mService != null) {
             try {
                 return mService.setPackagesSuspended(admin, packageNames, suspended);
@@ -3899,7 +3870,6 @@
      */
     public boolean isPackageSuspended(@NonNull ComponentName admin, String packageName)
             throws NameNotFoundException {
-        throwIfParentInstance("isPackageSuspended");
         if (mService != null) {
             try {
                 return mService.isPackageSuspended(admin, packageName);
@@ -3921,7 +3891,6 @@
      * @throws SecurityException if {@code admin} is not a profile owner.
      */
     public void setProfileEnabled(@NonNull ComponentName admin) {
-        throwIfParentInstance("setProfileEnabled");
         if (mService != null) {
             try {
                 mService.setProfileEnabled(admin);
@@ -3943,7 +3912,6 @@
      * @throws SecurityException if {@code admin} is not a device or profile owner.
      */
     public void setProfileName(@NonNull ComponentName admin, String profileName) {
-        throwIfParentInstance("setProfileName");
         if (mService != null) {
             try {
                 mService.setProfileName(admin, profileName);
@@ -3962,7 +3930,6 @@
      * @return Whether or not the package is registered as the profile owner.
      */
     public boolean isProfileOwnerApp(String packageName) {
-        throwIfParentInstance("isProfileOwnerApp");
         if (mService != null) {
             try {
                 ComponentName profileOwner = mService.getProfileOwner(myUserId());
@@ -4057,7 +4024,6 @@
      */
     public void addPersistentPreferredActivity(@NonNull ComponentName admin, IntentFilter filter,
             @NonNull ComponentName activity) {
-        throwIfParentInstance("addPersistentPreferredActivity");
         if (mService != null) {
             try {
                 mService.addPersistentPreferredActivity(admin, filter, activity);
@@ -4080,7 +4046,6 @@
      */
     public void clearPackagePersistentPreferredActivities(@NonNull ComponentName admin,
             String packageName) {
-        throwIfParentInstance("clearPackagePersistentPreferredActivities");
         if (mService != null) {
             try {
                 mService.clearPackagePersistentPreferredActivities(admin, packageName);
@@ -4109,7 +4074,6 @@
      */
     public void setApplicationRestrictionsManagingPackage(@NonNull ComponentName admin,
             @Nullable String packageName) throws NameNotFoundException {
-        throwIfParentInstance("setApplicationRestrictionsManagingPackage");
         if (mService != null) {
             try {
                 if (!mService.setApplicationRestrictionsManagingPackage(admin, packageName)) {
@@ -4131,7 +4095,6 @@
      * @throws SecurityException if {@code admin} is not a device or profile owner.
      */
     public String getApplicationRestrictionsManagingPackage(@NonNull ComponentName admin) {
-        throwIfParentInstance("getApplicationRestrictionsManagingPackage");
         if (mService != null) {
             try {
                 return mService.getApplicationRestrictionsManagingPackage(admin);
@@ -4151,7 +4114,6 @@
      * that method.
      */
     public boolean isCallerApplicationRestrictionsManagingPackage() {
-        throwIfParentInstance("isCallerApplicationRestrictionsManagingPackage");
         if (mService != null) {
             try {
                 return mService.isCallerApplicationRestrictionsManagingPackage();
@@ -4197,7 +4159,6 @@
      */
     public void setApplicationRestrictions(@Nullable ComponentName admin, String packageName,
             Bundle settings) {
-        throwIfParentInstance("setApplicationRestrictions");
         if (mService != null) {
             try {
                 mService.setApplicationRestrictions(admin, packageName, settings);
@@ -4296,7 +4257,6 @@
      * @throws SecurityException if {@code admin} is not a device or profile owner.
      */
     public void setCrossProfileCallerIdDisabled(@NonNull ComponentName admin, boolean disabled) {
-        throwIfParentInstance("setCrossProfileCallerIdDisabled");
         if (mService != null) {
             try {
                 mService.setCrossProfileCallerIdDisabled(admin, disabled);
@@ -4317,7 +4277,6 @@
      * @throws SecurityException if {@code admin} is not a device or profile owner.
      */
     public boolean getCrossProfileCallerIdDisabled(@NonNull ComponentName admin) {
-        throwIfParentInstance("getCrossProfileCallerIdDisabled");
         if (mService != null) {
             try {
                 return mService.getCrossProfileCallerIdDisabled(admin);
@@ -4358,7 +4317,6 @@
      */
     public void setCrossProfileContactsSearchDisabled(@NonNull ComponentName admin,
             boolean disabled) {
-        throwIfParentInstance("setCrossProfileContactsSearchDisabled");
         if (mService != null) {
             try {
                 mService.setCrossProfileContactsSearchDisabled(admin, disabled);
@@ -4379,7 +4337,6 @@
      * @throws SecurityException if {@code admin} is not a device or profile owner.
      */
     public boolean getCrossProfileContactsSearchDisabled(@NonNull ComponentName admin) {
-        throwIfParentInstance("getCrossProfileContactsSearchDisabled");
         if (mService != null) {
             try {
                 return mService.getCrossProfileContactsSearchDisabled(admin);
@@ -4450,7 +4407,6 @@
      * @throws SecurityException if {@code admin} is not a device or profile owner.
      */
     public void setBluetoothContactSharingDisabled(@NonNull ComponentName admin, boolean disabled) {
-        throwIfParentInstance("setBluetoothContactSharingDisabled");
         if (mService != null) {
             try {
                 mService.setBluetoothContactSharingDisabled(admin, disabled);
@@ -4473,7 +4429,6 @@
      * @throws SecurityException if {@code admin} is not a device or profile owner.
      */
     public boolean getBluetoothContactSharingDisabled(@NonNull ComponentName admin) {
-        throwIfParentInstance("getBluetoothContactSharingDisabled");
         if (mService != null) {
             try {
                 return mService.getBluetoothContactSharingDisabled(admin);
@@ -4517,7 +4472,6 @@
      * @throws SecurityException if {@code admin} is not a device or profile owner.
      */
     public void addCrossProfileIntentFilter(@NonNull ComponentName admin, IntentFilter filter, int flags) {
-        throwIfParentInstance("addCrossProfileIntentFilter");
         if (mService != null) {
             try {
                 mService.addCrossProfileIntentFilter(admin, filter, flags);
@@ -4536,7 +4490,6 @@
      * @throws SecurityException if {@code admin} is not a device or profile owner.
      */
     public void clearCrossProfileIntentFilters(@NonNull ComponentName admin) {
-        throwIfParentInstance("clearCrossProfileIntentFilters");
         if (mService != null) {
             try {
                 mService.clearCrossProfileIntentFilters(admin);
@@ -4566,7 +4519,6 @@
      */
     public boolean setPermittedAccessibilityServices(@NonNull ComponentName admin,
             List<String> packageNames) {
-        throwIfParentInstance("setPermittedAccessibilityServices");
         if (mService != null) {
             try {
                 return mService.setPermittedAccessibilityServices(admin, packageNames);
@@ -4588,7 +4540,6 @@
      * @throws SecurityException if {@code admin} is not a device or profile owner.
      */
     public List<String> getPermittedAccessibilityServices(@NonNull ComponentName admin) {
-        throwIfParentInstance("getPermittedAccessibilityServices");
         if (mService != null) {
             try {
                 return mService.getPermittedAccessibilityServices(admin);
@@ -4666,7 +4617,6 @@
      * @throws SecurityException if {@code admin} is not a device or profile owner.
      */
     public boolean setPermittedInputMethods(@NonNull ComponentName admin, List<String> packageNames) {
-        throwIfParentInstance("setPermittedInputMethods");
         if (mService != null) {
             try {
                 return mService.setPermittedInputMethods(admin, packageNames);
@@ -4689,7 +4639,6 @@
      * @throws SecurityException if {@code admin} is not a device or profile owner.
      */
     public List<String> getPermittedInputMethods(@NonNull ComponentName admin) {
-        throwIfParentInstance("getPermittedInputMethods");
         if (mService != null) {
             try {
                 return mService.getPermittedInputMethods(admin);
@@ -4885,7 +4834,6 @@
     public UserHandle createAndManageUser(@NonNull ComponentName admin, @NonNull String name,
             @NonNull ComponentName profileOwner, @Nullable PersistableBundle adminExtras,
             int flags) {
-        throwIfParentInstance("createAndManageUser");
         try {
             return mService.createAndManageUser(admin, name, profileOwner, adminExtras, flags);
         } catch (RemoteException re) {
@@ -4903,7 +4851,6 @@
      * @throws SecurityException if {@code admin} is not a device owner.
      */
     public boolean removeUser(@NonNull ComponentName admin, UserHandle userHandle) {
-        throwIfParentInstance("removeUser");
         try {
             return mService.removeUser(admin, userHandle);
         } catch (RemoteException re) {
@@ -4921,7 +4868,6 @@
      * @see Intent#ACTION_USER_FOREGROUND
      */
     public boolean switchUser(@NonNull ComponentName admin, @Nullable UserHandle userHandle) {
-        throwIfParentInstance("switchUser");
         try {
             return mService.switchUser(admin, userHandle);
         } catch (RemoteException re) {
@@ -4947,7 +4893,6 @@
      * @see {@link #setApplicationRestrictionsManagingPackage}
      */
     public Bundle getApplicationRestrictions(@Nullable ComponentName admin, String packageName) {
-        throwIfParentInstance("getApplicationRestrictions");
         if (mService != null) {
             try {
                 return mService.getApplicationRestrictions(admin, packageName);
@@ -4970,7 +4915,6 @@
      * @throws SecurityException if {@code admin} is not a device or profile owner.
      */
     public void addUserRestriction(@NonNull ComponentName admin, String key) {
-        throwIfParentInstance("addUserRestriction");
         if (mService != null) {
             try {
                 mService.setUserRestriction(admin, key, true);
@@ -4992,7 +4936,6 @@
      * @throws SecurityException if {@code admin} is not a device or profile owner.
      */
     public void clearUserRestriction(@NonNull ComponentName admin, String key) {
-        throwIfParentInstance("clearUserRestriction");
         if (mService != null) {
             try {
                 mService.setUserRestriction(admin, key, false);
@@ -5014,7 +4957,6 @@
      * @throws SecurityException if {@code admin} is not a device or profile owner.
      */
     public Bundle getUserRestrictions(@NonNull ComponentName admin) {
-        throwIfParentInstance("getUserRestrictions");
         Bundle ret = null;
         if (mService != null) {
             try {
@@ -5059,7 +5001,6 @@
      */
     public boolean setApplicationHidden(@NonNull ComponentName admin, String packageName,
             boolean hidden) {
-        throwIfParentInstance("setApplicationHidden");
         if (mService != null) {
             try {
                 return mService.setApplicationHidden(admin, packageName, hidden);
@@ -5079,7 +5020,6 @@
      * @throws SecurityException if {@code admin} is not a device or profile owner.
      */
     public boolean isApplicationHidden(@NonNull ComponentName admin, String packageName) {
-        throwIfParentInstance("isApplicationHidden");
         if (mService != null) {
             try {
                 return mService.isApplicationHidden(admin, packageName);
@@ -5099,7 +5039,6 @@
      * @throws SecurityException if {@code admin} is not a device or profile owner.
      */
     public void enableSystemApp(@NonNull ComponentName admin, String packageName) {
-        throwIfParentInstance("enableSystemApp");
         if (mService != null) {
             try {
                 mService.enableSystemApp(admin, packageName);
@@ -5120,7 +5059,6 @@
      * @throws SecurityException if {@code admin} is not a device or profile owner.
      */
     public int enableSystemApp(@NonNull ComponentName admin, Intent intent) {
-        throwIfParentInstance("enableSystemApp");
         if (mService != null) {
             try {
                 return mService.enableSystemAppWithIntent(admin, intent);
@@ -5153,7 +5091,6 @@
      */
     public void setAccountManagementDisabled(@NonNull ComponentName admin, String accountType,
             boolean disabled) {
-        throwIfParentInstance("setAccountManagementDisabled");
         if (mService != null) {
             try {
                 mService.setAccountManagementDisabled(admin, accountType, disabled);
@@ -5174,7 +5111,6 @@
      * @see #setAccountManagementDisabled
      */
     public String[] getAccountTypesWithManagementDisabled() {
-        throwIfParentInstance("getAccountTypesWithManagementDisabled");
         return getAccountTypesWithManagementDisabledAsUser(myUserId());
     }
 
@@ -5212,7 +5148,6 @@
      */
     public void setLockTaskPackages(@NonNull ComponentName admin, String[] packages)
             throws SecurityException {
-        throwIfParentInstance("setLockTaskPackages");
         if (mService != null) {
             try {
                 mService.setLockTaskPackages(admin, packages);
@@ -5229,7 +5164,6 @@
      * @hide
      */
     public String[] getLockTaskPackages(@NonNull ComponentName admin) {
-        throwIfParentInstance("getLockTaskPackages");
         if (mService != null) {
             try {
                 return mService.getLockTaskPackages(admin);
@@ -5246,7 +5180,6 @@
      * @param pkg The package to check
      */
     public boolean isLockTaskPermitted(String pkg) {
-        throwIfParentInstance("isLockTaskPermitted");
         if (mService != null) {
             try {
                 return mService.isLockTaskPermitted(pkg);
@@ -5295,7 +5228,6 @@
      * @throws SecurityException if {@code admin} is not a device owner.
      */
     public void setGlobalSetting(@NonNull ComponentName admin, String setting, String value) {
-        throwIfParentInstance("setGlobalSetting");
         if (mService != null) {
             try {
                 mService.setGlobalSetting(admin, setting, value);
@@ -5328,7 +5260,6 @@
      * @throws SecurityException if {@code admin} is not a device or profile owner.
      */
     public void setSecureSetting(@NonNull ComponentName admin, String setting, String value) {
-        throwIfParentInstance("setSecureSetting");
         if (mService != null) {
             try {
                 mService.setSecureSetting(admin, setting, value);
@@ -5352,7 +5283,6 @@
      */
     public void setRestrictionsProvider(@NonNull ComponentName admin,
             @Nullable ComponentName provider) {
-        throwIfParentInstance("setRestrictionsProvider");
         if (mService != null) {
             try {
                 mService.setRestrictionsProvider(admin, provider);
@@ -5370,7 +5300,6 @@
      * @throws SecurityException if {@code admin} is not a device or profile owner.
      */
     public void setMasterVolumeMuted(@NonNull ComponentName admin, boolean on) {
-        throwIfParentInstance("setMasterVolumeMuted");
         if (mService != null) {
             try {
                 mService.setMasterVolumeMuted(admin, on);
@@ -5388,7 +5317,6 @@
      * @throws SecurityException if {@code admin} is not a device or profile owner.
      */
     public boolean isMasterVolumeMuted(@NonNull ComponentName admin) {
-        throwIfParentInstance("isMasterVolumeMuted");
         if (mService != null) {
             try {
                 return mService.isMasterVolumeMuted(admin);
@@ -5409,7 +5337,6 @@
      */
     public void setUninstallBlocked(@NonNull ComponentName admin, String packageName,
             boolean uninstallBlocked) {
-        throwIfParentInstance("setUninstallBlocked");
         if (mService != null) {
             try {
                 mService.setUninstallBlocked(admin, packageName, uninstallBlocked);
@@ -5435,7 +5362,6 @@
      * @throws SecurityException if {@code admin} is not a device or profile owner.
      */
     public boolean isUninstallBlocked(@Nullable ComponentName admin, String packageName) {
-        throwIfParentInstance("isUninstallBlocked");
         if (mService != null) {
             try {
                 return mService.isUninstallBlocked(admin, packageName);
@@ -5463,7 +5389,6 @@
      * @see #getCrossProfileWidgetProviders(android.content.ComponentName)
      */
     public boolean addCrossProfileWidgetProvider(@NonNull ComponentName admin, String packageName) {
-        throwIfParentInstance("addCrossProfileWidgetProvider");
         if (mService != null) {
             try {
                 return mService.addCrossProfileWidgetProvider(admin, packageName);
@@ -5491,7 +5416,6 @@
      */
     public boolean removeCrossProfileWidgetProvider(
             @NonNull ComponentName admin, String packageName) {
-        throwIfParentInstance("removeCrossProfileWidgetProvider");
         if (mService != null) {
             try {
                 return mService.removeCrossProfileWidgetProvider(admin, packageName);
@@ -5513,7 +5437,6 @@
      * @throws SecurityException if {@code admin} is not a profile owner.
      */
     public List<String> getCrossProfileWidgetProviders(@NonNull ComponentName admin) {
-        throwIfParentInstance("getCrossProfileWidgetProviders");
         if (mService != null) {
             try {
                 List<String> providers = mService.getCrossProfileWidgetProviders(admin);
@@ -5535,7 +5458,6 @@
      * @throws SecurityException if {@code admin} is not a device or profile owner.
      */
     public void setUserIcon(@NonNull ComponentName admin, Bitmap icon) {
-        throwIfParentInstance("setUserIcon");
         try {
             mService.setUserIcon(admin, icon);
         } catch (RemoteException re) {
@@ -5555,7 +5477,6 @@
      * @see SystemUpdatePolicy
      */
     public void setSystemUpdatePolicy(@NonNull ComponentName admin, SystemUpdatePolicy policy) {
-        throwIfParentInstance("setSystemUpdatePolicy");
         if (mService != null) {
             try {
                 mService.setSystemUpdatePolicy(admin, policy);
@@ -5571,7 +5492,6 @@
      * @return The current policy object, or {@code null} if no policy is set.
      */
     public SystemUpdatePolicy getSystemUpdatePolicy() {
-        throwIfParentInstance("getSystemUpdatePolicy");
         if (mService != null) {
             try {
                 return mService.getSystemUpdatePolicy();
@@ -5597,7 +5517,6 @@
      * @throws SecurityException if {@code admin} is not a device owner.
      */
     public boolean setKeyguardDisabled(@NonNull ComponentName admin, boolean disabled) {
-        throwIfParentInstance("setKeyguardDisabled");
         try {
             return mService.setKeyguardDisabled(admin, disabled);
         } catch (RemoteException re) {
@@ -5616,7 +5535,6 @@
      * @throws SecurityException if {@code admin} is not a device owner.
      */
     public boolean setStatusBarDisabled(@NonNull ComponentName admin, boolean disabled) {
-        throwIfParentInstance("setStatusBarDisabled");
         try {
             return mService.setStatusBarDisabled(admin, disabled);
         } catch (RemoteException re) {
@@ -5662,7 +5580,6 @@
      * @see #setPermissionGrantState
      */
     public void setPermissionPolicy(@NonNull ComponentName admin, int policy) {
-        throwIfParentInstance("setPermissionPolicy");
         try {
             mService.setPermissionPolicy(admin, policy);
         } catch (RemoteException re) {
@@ -5677,7 +5594,6 @@
      * @return the current policy for future permission requests.
      */
     public int getPermissionPolicy(ComponentName admin) {
-        throwIfParentInstance("getPermissionPolicy");
         try {
             return mService.getPermissionPolicy(admin);
         } catch (RemoteException re) {
@@ -5714,7 +5630,6 @@
      */
     public boolean setPermissionGrantState(@NonNull ComponentName admin, String packageName,
             String permission, int grantState) {
-        throwIfParentInstance("setPermissionGrantState");
         try {
             return mService.setPermissionGrantState(admin, packageName, permission, grantState);
         } catch (RemoteException re) {
@@ -5743,7 +5658,6 @@
      */
     public int getPermissionGrantState(@NonNull ComponentName admin, String packageName,
             String permission) {
-        throwIfParentInstance("getPermissionGrantState");
         try {
             return mService.getPermissionGrantState(admin, packageName, permission);
         } catch (RemoteException re) {
@@ -5759,7 +5673,6 @@
      * @throws IllegalArgumentException if the supplied action is not valid.
      */
     public boolean isProvisioningAllowed(String action) {
-        throwIfParentInstance("isProvisioningAllowed");
         try {
             return mService.isProvisioningAllowed(action);
         } catch (RemoteException re) {
@@ -5775,7 +5688,6 @@
      * @return if this user is a managed profile of another user.
      */
     public boolean isManagedProfile(@NonNull ComponentName admin) {
-        throwIfParentInstance("isManagedProfile");
         try {
             return mService.isManagedProfile(admin);
         } catch (RemoteException re) {
@@ -5809,7 +5721,6 @@
      * @throws SecurityException if {@code admin} is not a device owner.
      */
     public String getWifiMacAddress(@NonNull ComponentName admin) {
-        throwIfParentInstance("getWifiMacAddress");
         try {
             return mService.getWifiMacAddress(admin);
         } catch (RemoteException re) {
@@ -5826,7 +5737,6 @@
      * @see TelephonyManager#CALL_STATE_IDLE
      */
     public void reboot(@NonNull ComponentName admin) {
-        throwIfParentInstance("reboot");
         try {
             mService.reboot(admin);
         } catch (RemoteException re) {
@@ -5853,7 +5763,6 @@
      */
     public void setShortSupportMessage(@NonNull ComponentName admin,
             @Nullable String message) {
-        throwIfParentInstance("setShortSupportMessage");
         if (mService != null) {
             try {
                 mService.setShortSupportMessage(admin, message);
@@ -5872,7 +5781,6 @@
      * @throws SecurityException if {@code admin} is not an active administrator.
      */
     public String getShortSupportMessage(@NonNull ComponentName admin) {
-        throwIfParentInstance("getShortSupportMessage");
         if (mService != null) {
             try {
                 return mService.getShortSupportMessage(admin);
@@ -5899,7 +5807,6 @@
      */
     public void setLongSupportMessage(@NonNull ComponentName admin,
             @Nullable String message) {
-        throwIfParentInstance("setLongSupportMessage");
         if (mService != null) {
             try {
                 mService.setLongSupportMessage(admin, message);
@@ -5918,7 +5825,6 @@
      * @throws SecurityException if {@code admin} is not an active administrator.
      */
     public String getLongSupportMessage(@NonNull ComponentName admin) {
-        throwIfParentInstance("getLongSupportMessage");
         if (mService != null) {
             try {
                 return mService.getLongSupportMessage(admin);
@@ -6015,7 +5921,6 @@
      * @throws SecurityException if {@code admin} is not a profile owner.
      */
     public DevicePolicyManager getParentProfileInstance(@NonNull ComponentName admin) {
-        throwIfParentInstance("getParentProfileInstance");
         try {
             if (!mService.isManagedProfile(admin)) {
                 throw new SecurityException("The current user does not have a parent profile.");
@@ -6042,7 +5947,6 @@
      * @see #retrieveSecurityLogs
      */
     public void setSecurityLoggingEnabled(@NonNull ComponentName admin, boolean enabled) {
-        throwIfParentInstance("setSecurityLoggingEnabled");
         try {
             mService.setSecurityLoggingEnabled(admin, enabled);
         } catch (RemoteException re) {
@@ -6061,7 +5965,6 @@
      * @throws SecurityException if {@code admin} is not a device owner.
      */
     public boolean isSecurityLoggingEnabled(@NonNull ComponentName admin) {
-        throwIfParentInstance("isSecurityLoggingEnabled");
         try {
             return mService.isSecurityLoggingEnabled(admin);
         } catch (RemoteException re) {
@@ -6085,7 +5988,6 @@
      * @throws SecurityException if {@code admin} is not a device owner.
      */
     public List<SecurityEvent> retrieveSecurityLogs(@NonNull ComponentName admin) {
-        throwIfParentInstance("retrieveSecurityLogs");
         try {
             ParceledListSlice<SecurityEvent> list = mService.retrieveSecurityLogs(admin);
             if (list != null) {
@@ -6131,7 +6033,6 @@
      * @throws SecurityException if {@code admin} is not a device owner.
      */
     public List<SecurityEvent> retrievePreRebootSecurityLogs(@NonNull ComponentName admin) {
-        throwIfParentInstance("retrievePreRebootSecurityLogs");
         try {
             ParceledListSlice<SecurityEvent> list = mService.retrievePreRebootSecurityLogs(admin);
             return list.getList();
@@ -6153,7 +6054,6 @@
      * @throws SecurityException if {@code admin} is not a profile owner.
      */
     public void setOrganizationColor(@NonNull ComponentName admin, int color) {
-        throwIfParentInstance("setOrganizationColor");
         try {
             mService.setOrganizationColor(admin, color);
         } catch (RemoteException re) {
@@ -6189,7 +6089,6 @@
      * @throws SecurityException if {@code admin} is not a profile owner.
      */
     public int getOrganizationColor(@NonNull ComponentName admin) {
-        throwIfParentInstance("getOrganizationColor");
         try {
             return mService.getOrganizationColor(admin);
         } catch (RemoteException re) {
@@ -6225,7 +6124,6 @@
      * @throws SecurityException if {@code admin} is not a profile owner.
      */
     public void setOrganizationName(@NonNull ComponentName admin, @Nullable String title) {
-        throwIfParentInstance("setOrganizationName");
         try {
             mService.setOrganizationName(admin, title);
         } catch (RemoteException re) {
@@ -6242,7 +6140,6 @@
      * @throws SecurityException if {@code admin} is not a profile owner.
      */
     public String getOrganizationName(@NonNull ComponentName admin) {
-        throwIfParentInstance("getOrganizationName");
         try {
             return mService.getOrganizationName(admin);
         } catch (RemoteException re) {
@@ -6368,10 +6265,4 @@
             throw re.rethrowFromSystemServer();
         }
     }
-
-    private void throwIfParentInstance(String functionName) {
-        if (mParentInstance) {
-            throw new SecurityException(functionName + " cannot be called on the parent instance");
-        }
-    }
 }
diff --git a/core/java/android/content/pm/ILauncherApps.aidl b/core/java/android/content/pm/ILauncherApps.aidl
index 6b3d4f1..46321a4 100644
--- a/core/java/android/content/pm/ILauncherApps.aidl
+++ b/core/java/android/content/pm/ILauncherApps.aidl
@@ -47,17 +47,16 @@
     ApplicationInfo getApplicationInfo(String packageName, int flags, in UserHandle user);
 
     ParceledListSlice getShortcuts(String callingPackage, long changedSince, String packageName,
-            in ComponentName componentName, int flags, in UserHandle user);
-    ParceledListSlice getShortcutInfo(String callingPackage, String packageName, in List<String> ids,
-            in UserHandle user);
+            in List shortcutIds, in ComponentName componentName, int flags, in UserHandle user);
     void pinShortcuts(String callingPackage, String packageName, in List<String> shortcutIds,
             in UserHandle user);
     boolean startShortcut(String callingPackage, String packageName, String id,
-            in Rect sourceBounds, in Bundle startActivityOptions, in UserHandle user);
+            in Rect sourceBounds, in Bundle startActivityOptions, int userId);
 
-    int getShortcutIconResId(String callingPackage, in ShortcutInfo shortcut, in UserHandle user);
-    ParcelFileDescriptor getShortcutIconFd(String callingPackage, in ShortcutInfo shortcut,
-            in UserHandle user);
+    int getShortcutIconResId(String callingPackage, String packageName, String id,
+            int userId);
+    ParcelFileDescriptor getShortcutIconFd(String callingPackage, String packageName, String id,
+            int userId);
 
     boolean hasShortcutHostPermission(String callingPackage);
 }
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index d865f345..abe1aaf 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -205,6 +205,9 @@
         String mPackage;
 
         @Nullable
+        List<String> mShortcutIds;
+
+        @Nullable
         ComponentName mActivity;
 
         @QueryFlags
@@ -229,6 +232,14 @@
         }
 
         /**
+         * If non-null, return only the specified shortcuts by ID.  When setting this field,
+         * a packange name must also be set with {@link #setPackage}.
+         */
+        public void setShortcutIds(@Nullable List<String> shortcutIds) {
+            mShortcutIds = shortcutIds;
+        }
+
+        /**
          * If non-null, returns only shortcuts associated with the activity.
          */
         public void setActivity(@Nullable ComponentName activity) {
@@ -429,7 +440,8 @@
             @NonNull UserHandle user) {
         try {
             return mService.getShortcuts(mContext.getPackageName(),
-                    query.mChangedSince, query.mPackage, query.mActivity, query.mQueryFlags, user)
+                    query.mChangedSince, query.mPackage, query.mShortcutIds, query.mActivity,
+                    query.mQueryFlags, user)
                     .getList();
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
@@ -437,29 +449,18 @@
     }
 
     /**
-     * Returns {@link ShortcutInfo}s with the given IDs from a package.
-     *
-     * <p>Callers must be allowed to access the shortcut information, as defined in {@link
-     * #hasShortcutHostPermission()}.
-     *
-     * @param packageName The target package.
-     * @param ids IDs of the shortcuts to retrieve.
-     * @param user The UserHandle of the profile.
-     *
-     * @return list of {@link ShortcutInfo} associated with the package.
+     * @hide // No longer used.  Use getShortcuts() instead.  Kept for unit tests.
      */
     @Nullable
     public List<ShortcutInfo> getShortcutInfo(@NonNull String packageName,
             @NonNull List<String> ids, @NonNull UserHandle user) {
-        try {
-            return mService.getShortcutInfo(mContext.getPackageName(), packageName, ids, user)
-                    .getList();
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
+        final ShortcutQuery q = new ShortcutQuery();
+        q.setPackage(packageName);
+        q.setShortcutIds(ids);
+        q.setQueryFlags(ShortcutQuery.FLAG_GET_DYNAMIC | ShortcutQuery.FLAG_GET_PINNED);
+        return getShortcuts(q, user);
     }
 
-
     /**
      * Pin shortcuts on a package.
      *
@@ -490,11 +491,33 @@
      * #hasShortcutHostPermission()}.
      *
      * @param shortcut The target shortcut.
+     */
+    public int getShortcutIconResId(@NonNull ShortcutInfo shortcut) {
+        return getShortcutIconResId(shortcut.getPackageName(), shortcut.getId(),
+                shortcut.getUserId());
+    }
+
+    /**
+     * Return the icon resource ID, if {@code shortcut} has one
+     * (i.e. when {@link ShortcutInfo#hasIconResource()} returns {@code true}).
+     *
+     * <p>Callers must be allowed to access the shortcut information, as defined in {@link
+     * #hasShortcutHostPermission()}.
+     *
+     * @param packageName The target package name.
+     * @param shortcutId The ID of the shortcut to lad rom.
      * @param user The UserHandle of the profile.
      */
-    public int getShortcutIconResId(@NonNull ShortcutInfo shortcut, @NonNull UserHandle user) {
+    public int getShortcutIconResId(@NonNull String packageName, @NonNull String shortcutId,
+            @NonNull UserHandle user) {
+        return getShortcutIconResId(packageName, shortcutId, user.getIdentifier());
+    }
+
+    private int getShortcutIconResId(@NonNull String packageName, @NonNull String shortcutId,
+            int userId) {
         try {
-            return mService.getShortcutIconResId(mContext.getPackageName(), shortcut, user);
+            return mService.getShortcutIconResId(mContext.getPackageName(),
+                    packageName, shortcutId, userId);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -508,12 +531,34 @@
      * #hasShortcutHostPermission()}.
      *
      * @param shortcut The target shortcut.
+     */
+    public ParcelFileDescriptor getShortcutIconFd(
+            @NonNull ShortcutInfo shortcut) {
+        return getShortcutIconFd(shortcut.getPackageName(), shortcut.getId(),
+                shortcut.getUserId());
+    }
+
+    /**
+     * Return the icon as {@link ParcelFileDescriptor}, when it's stored as a file
+     * (i.e. when {@link ShortcutInfo#hasIconFile()} returns {@code true}).
+     *
+     * <p>Callers must be allowed to access the shortcut information, as defined in {@link
+     * #hasShortcutHostPermission()}.
+     *
+     * @param packageName The target package name.
+     * @param shortcutId The ID of the shortcut to lad rom.
      * @param user The UserHandle of the profile.
      */
     public ParcelFileDescriptor getShortcutIconFd(
-            @NonNull ShortcutInfo shortcut, @NonNull UserHandle user) {
+            @NonNull String packageName, @NonNull String shortcutId, @NonNull UserHandle user) {
+        return getShortcutIconFd(packageName, shortcutId, user.getIdentifier());
+    }
+
+    private ParcelFileDescriptor getShortcutIconFd(
+            @NonNull String packageName, @NonNull String shortcutId, int userId) {
         try {
-            return mService.getShortcutIconFd(mContext.getPackageName(), shortcut, user);
+            return mService.getShortcutIconFd(mContext.getPackageName(),
+                    packageName, shortcutId, userId);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -536,9 +581,35 @@
     public boolean startShortcut(@NonNull String packageName, @NonNull String shortcutId,
             @Nullable Rect sourceBounds, @Nullable Bundle startActivityOptions,
             @NonNull UserHandle user) {
+        return startShortcut(packageName, shortcutId, sourceBounds, startActivityOptions,
+                user.getIdentifier());
+    }
+
+    /**
+     * Launches a shortcut.
+     *
+     * <p>Callers must be allowed to access the shortcut information, as defined in {@link
+     * #hasShortcutHostPermission()}.
+     *
+     * @param shortcut The target shortcut.
+     * @param sourceBounds The Rect containing the source bounds of the clicked icon.
+     * @param startActivityOptions Options to pass to startActivity.
+     * @return {@code false} when the shortcut is no longer valid (e.g. the creator application
+     *   has been uninstalled). {@code true} when the shortcut is still valid.
+     */
+    public boolean startShortcut(@NonNull ShortcutInfo shortcut,
+            @Nullable Rect sourceBounds, @Nullable Bundle startActivityOptions) {
+        return startShortcut(shortcut.getPackageName(), shortcut.getId(),
+                sourceBounds, startActivityOptions,
+                shortcut.getUserId());
+    }
+
+    private boolean startShortcut(@NonNull String packageName, @NonNull String shortcutId,
+            @Nullable Rect sourceBounds, @Nullable Bundle startActivityOptions,
+            int userId) {
         try {
             return mService.startShortcut(mContext.getPackageName(), packageName, shortcutId,
-                    sourceBounds, startActivityOptions, user);
+                    sourceBounds, startActivityOptions, userId);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
diff --git a/core/java/android/content/pm/ShortcutInfo.java b/core/java/android/content/pm/ShortcutInfo.java
index 1812575a..7a807c4 100644
--- a/core/java/android/content/pm/ShortcutInfo.java
+++ b/core/java/android/content/pm/ShortcutInfo.java
@@ -18,6 +18,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UserIdInt;
 import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -153,7 +154,11 @@
     @Nullable
     private String mBitmapPath;
 
+    private final int mUserId;
+
     private ShortcutInfo(Builder b) {
+        mUserId = b.mContext.getUserId();
+
         mId = Preconditions.checkStringNotEmpty(b.mId, "Shortcut ID must be provided");
 
         // Note we can't do other null checks here because SM.updateShortcuts() takes partial
@@ -191,6 +196,7 @@
      * Copy constructor.
      */
     private ShortcutInfo(ShortcutInfo source, @CloneFlags int cloneFlags) {
+        mUserId = source.mUserId;
         mId = source.mId;
         mPackageName = source.mPackageName;
         mFlags = source.mFlags;
@@ -238,6 +244,7 @@
      * @hide
      */
     public void copyNonNullFieldsFrom(ShortcutInfo source) {
+        Preconditions.checkState(mUserId == source.mUserId, "Owner User ID must match");
         Preconditions.checkState(mId.equals(source.mId), "ID must match");
         Preconditions.checkState(mPackageName.equals(source.mPackageName),
                 "Package name must match");
@@ -362,8 +369,8 @@
          *
          * <p>For performance reasons, icons will <b>NOT</b> be available on instances
          * returned by {@link ShortcutManager} or {@link LauncherApps}.  Launcher applications
-         * need to use {@link LauncherApps#getShortcutIconFd(ShortcutInfo, UserHandle)}
-         * and {@link LauncherApps#getShortcutIconResId(ShortcutInfo, UserHandle)}.
+         * need to use {@link LauncherApps#getShortcutIconFd(ShortcutInfo)}
+         * and {@link LauncherApps#getShortcutIconResId(ShortcutInfo)}.
          */
         @NonNull
         public Builder setIcon(Icon icon) {
@@ -544,6 +551,18 @@
         return mExtras;
     }
 
+    /** @hide */
+    public int getUserId() {
+        return mUserId;
+    }
+
+    /**
+     * {@link UserHandle} on which the publisher created shortcuts.
+     */
+    public UserHandle getUserHandle() {
+        return UserHandle.of(mUserId);
+    }
+
     /**
      * Last time when any of the fields was updated.
      */
@@ -590,7 +609,7 @@
     /**
      * Return whether a shortcut's icon is a resource in the owning package.
      *
-     * @see LauncherApps#getShortcutIconResId(ShortcutInfo, UserHandle)
+     * @see LauncherApps#getShortcutIconResId(ShortcutInfo)
      */
     public boolean hasIconResource() {
         return hasFlags(FLAG_HAS_ICON_RES);
@@ -599,7 +618,7 @@
     /**
      * Return whether a shortcut's icon is stored as a file.
      *
-     * @see LauncherApps#getShortcutIconFd(ShortcutInfo, UserHandle)
+     * @see LauncherApps#getShortcutIconFd(ShortcutInfo)
      */
     public boolean hasIconFile() {
         return hasFlags(FLAG_HAS_ICON_FILE);
@@ -661,6 +680,7 @@
     private ShortcutInfo(Parcel source) {
         final ClassLoader cl = getClass().getClassLoader();
 
+        mUserId = source.readInt();
         mId = source.readString();
         mPackageName = source.readString();
         mActivityComponent = source.readParcelable(cl);
@@ -679,6 +699,7 @@
 
     @Override
     public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(mUserId);
         dest.writeString(mId);
         dest.writeString(mPackageName);
         dest.writeParcelable(mActivityComponent, flags);
@@ -784,11 +805,13 @@
     }
 
     /** @hide */
-    public ShortcutInfo(String id, String packageName, ComponentName activityComponent,
+    public ShortcutInfo(
+            @UserIdInt int userId, String id, String packageName, ComponentName activityComponent,
             Icon icon, String title, String text, Intent intent,
             PersistableBundle intentPersistableExtras,
             int weight, PersistableBundle extras, long lastChangedTimestamp,
             int flags, int iconResId, String bitmapPath) {
+        mUserId = userId;
         mId = id;
         mPackageName = packageName;
         mActivityComponent = activityComponent;
diff --git a/core/java/android/content/pm/ShortcutServiceInternal.java b/core/java/android/content/pm/ShortcutServiceInternal.java
index d57f2e6e..dc3d317 100644
--- a/core/java/android/content/pm/ShortcutServiceInternal.java
+++ b/core/java/android/content/pm/ShortcutServiceInternal.java
@@ -42,15 +42,10 @@
     public abstract List<ShortcutInfo>
             getShortcuts(int launcherUserId,
             @NonNull String callingPackage, long changedSince,
-            @Nullable String packageName, @Nullable ComponentName componentName,
-            @ShortcutQuery.QueryFlags int flags,
+            @Nullable String packageName, @Nullable List<String> shortcutIds,
+            @Nullable ComponentName componentName, @ShortcutQuery.QueryFlags int flags,
             int userId);
 
-    public abstract List<ShortcutInfo>
-            getShortcutInfo(int launcherUserId, @NonNull String callingPackage,
-            @NonNull String packageName, @Nullable List<String> ids, int userId);
-
-
     public abstract boolean
             isPinnedByCaller(int launcherUserId, @NonNull String callingPackage,
             @NonNull String packageName, @NonNull String id, int userId);
@@ -65,11 +60,11 @@
     public abstract void addListener(@NonNull ShortcutChangeListener listener);
 
     public abstract int getShortcutIconResId(int launcherUserId, @NonNull String callingPackage,
-            @NonNull ShortcutInfo shortcut, int userId);
+            @NonNull String packageName, @NonNull String shortcutId, int userId);
 
     public abstract ParcelFileDescriptor getShortcutIconFd(int launcherUserId,
             @NonNull String callingPackage,
-            @NonNull ShortcutInfo shortcut, int userId);
+            @NonNull String packageName, @NonNull String shortcutId, int userId);
 
     public abstract boolean hasShortcutHostPermission(int launcherUserId,
             @NonNull String callingPackage);
diff --git a/core/java/android/hardware/location/NanoApp.java b/core/java/android/hardware/location/NanoApp.java
index c8f3439..8d50be6 100644
--- a/core/java/android/hardware/location/NanoApp.java
+++ b/core/java/android/hardware/location/NanoApp.java
@@ -18,6 +18,7 @@
 import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.util.Log;
 
 /** A class describing nano apps.
  * A nano app is a piece of executable code that can be
@@ -31,10 +32,15 @@
  */
 @SystemApi
 public class NanoApp {
+    private final String TAG = "NanoApp";
+
+    private final String UNKNOWN = "Unknown";
+
     private String mPublisher;
     private String mName;
 
     private int mAppId;
+    private boolean mAppIdSet;
     private int mAppVersion;
 
     private int mNeededReadMemBytes;
@@ -45,7 +51,48 @@
     private int[] mOutputEvents;
     private byte[] mAppBinary;
 
+    /**
+     * If this version of the constructor is used, the methods
+     * {@link #setAppBinary(byte[])} and {@link #setAppId(int)} must be called
+     * prior to passing this object to any managers.
+     *
+     * @see #NanoApp(int, byte[])
+     */
     public NanoApp() {
+        this(0, null);
+        mAppIdSet = false;
+    }
+
+    /**
+     * Initialize a NanoApp with the given id and binary.
+     *
+     * While this sets defaults for other fields, users will want to provide
+     * other values for those fields in most cases.
+     *
+     * @see #setPublisher(String)
+     * @see #setName(String)
+     * @see #setAppVersion(int)
+     * @see #setNeededReadMemBytes(int)
+     * @see #setNeededWriteMemBytes(int)
+     * @see #setNeededExecMemBytes(int)
+     * @see #setNeededSensors(int[])
+     * @see #setOutputEvents(int[])
+     */
+    public NanoApp(int appId, byte[] appBinary) {
+        mPublisher = UNKNOWN;
+        mName = UNKNOWN;
+
+        mAppId = appId;
+        mAppIdSet = true;
+        mAppVersion = 0;
+
+        mNeededReadMemBytes = 0;
+        mNeededWriteMemBytes = 0;
+        mNeededExecMemBytes = 0;
+
+        mNeededSensors = new int[0];
+        mOutputEvents = new int[0];
+        mAppBinary = appBinary;
     }
 
     /**
@@ -73,6 +120,7 @@
      */
     public void setAppId(int appId) {
         mAppId = appId;
+        mAppIdSet = true;
     }
 
     /**
@@ -256,6 +304,13 @@
     }
 
     public void writeToParcel(Parcel out, int flags) {
+        if (mAppBinary == null) {
+            throw new IllegalStateException("Must set non-null AppBinary for nanoapp " + mName);
+        }
+        if (!mAppIdSet) {
+            throw new IllegalStateException("Must set AppId for nanoapp " + mName);
+        }
+
         out.writeString(mPublisher);
         out.writeString(mName);
         out.writeInt(mAppId);
diff --git a/core/java/android/hardware/soundtrigger/KeyphraseEnrollmentInfo.java b/core/java/android/hardware/soundtrigger/KeyphraseEnrollmentInfo.java
index cc018e9..458c584 100644
--- a/core/java/android/hardware/soundtrigger/KeyphraseEnrollmentInfo.java
+++ b/core/java/android/hardware/soundtrigger/KeyphraseEnrollmentInfo.java
@@ -35,9 +35,11 @@
 import org.xmlpull.v1.XmlPullParserException;
 
 import java.io.IOException;
-import java.util.Arrays;
+import java.util.HashMap;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Locale;
+import java.util.Map;
 
 /**
  * Enrollment information about the different available keyphrases.
@@ -82,8 +84,16 @@
     public static final String EXTRA_VOICE_KEYPHRASE_LOCALE =
             "com.android.intent.extra.VOICE_KEYPHRASE_LOCALE";
 
-    private KeyphraseMetadata[] mKeyphrases;
-    private String mEnrollmentPackage;
+    /**
+     * List of available keyphrases.
+     */
+    final private KeyphraseMetadata[] mKeyphrases;
+
+    /**
+     * Map between KeyphraseMetadata and the package name of the enrollment app that provides it.
+     */
+    final private Map<KeyphraseMetadata, String> mKeyphrasePackageMap;
+
     private String mParseError;
 
     public KeyphraseEnrollmentInfo(PackageManager pm) {
@@ -94,15 +104,17 @@
                 new Intent(ACTION_MANAGE_VOICE_KEYPHRASES), PackageManager.MATCH_DEFAULT_ONLY);
         if (ris == null || ris.isEmpty()) {
             // No application capable of enrolling for voice keyphrases is present.
-            mParseError = "No enrollment application found";
+            mParseError = "No enrollment applications found";
+            mKeyphrasePackageMap = null;
+            mKeyphrases = null;
             return;
         }
 
-        boolean found = false;
-        ApplicationInfo ai = null;
+        List<String> parseErrors = new LinkedList<String>();
+        mKeyphrasePackageMap = new HashMap<KeyphraseMetadata, String>();
         for (ResolveInfo ri : ris) {
             try {
-                ai = pm.getApplicationInfo(
+                ApplicationInfo ai = pm.getApplicationInfo(
                         ri.activityInfo.packageName, PackageManager.GET_META_DATA);
                 if ((ai.privateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) == 0) {
                     // The application isn't privileged (/system/priv-app).
@@ -116,27 +128,45 @@
                     Slog.w(TAG, ai.packageName + " does not require MANAGE_VOICE_KEYPHRASES");
                     continue;
                 }
-                mEnrollmentPackage = ai.packageName;
-                found = true;
-                break;
+
+                mKeyphrasePackageMap.put(
+                        getKeyphraseMetadataFromApplicationInfo(pm, ai, parseErrors),
+                        ai.packageName);
             } catch (PackageManager.NameNotFoundException e) {
-                Slog.w(TAG, "error parsing voice enrollment meta-data", e);
+                String error = "error parsing voice enrollment meta-data for "
+                        + ri.activityInfo.packageName;
+                parseErrors.add(error + ": " + e);
+                Slog.w(TAG, error, e);
             }
         }
 
-        if (!found) {
+        if (mKeyphrasePackageMap.isEmpty()) {
+            String error = "No suitable enrollment application found";
+            parseErrors.add(error);
+            Slog.w(TAG, error);
             mKeyphrases = null;
-            mParseError = "No suitable enrollment application found";
-            return;
+        } else {
+            mKeyphrases = mKeyphrasePackageMap.keySet().toArray(
+                    new KeyphraseMetadata[mKeyphrasePackageMap.size()]);
         }
 
+        if (!parseErrors.isEmpty()) {
+            mParseError = TextUtils.join("\n", parseErrors);
+        }
+    }
+
+    private KeyphraseMetadata getKeyphraseMetadataFromApplicationInfo(PackageManager pm,
+            ApplicationInfo ai, List<String> parseErrors) {
         XmlResourceParser parser = null;
+        String packageName = ai.packageName;
+        KeyphraseMetadata keyphraseMetadata = null;
         try {
             parser = ai.loadXmlMetaData(pm, VOICE_KEYPHRASE_META_DATA);
             if (parser == null) {
-                mParseError = "No " + VOICE_KEYPHRASE_META_DATA + " meta-data for "
-                        + ai.packageName;
-                return;
+                String error = "No " + VOICE_KEYPHRASE_META_DATA + " meta-data for " + packageName;
+                parseErrors.add(error);
+                Slog.w(TAG, error);
+                return null;
             }
 
             Resources res = pm.getResourcesForApplication(ai);
@@ -149,48 +179,55 @@
 
             String nodeName = parser.getName();
             if (!"voice-enrollment-application".equals(nodeName)) {
-                mParseError = "Meta-data does not start with voice-enrollment-application tag";
-                return;
+                String error = "Meta-data does not start with voice-enrollment-application tag for "
+                        + packageName;
+                parseErrors.add(error);
+                Slog.w(TAG, error);
+                return null;
             }
 
             TypedArray array = res.obtainAttributes(attrs,
                     com.android.internal.R.styleable.VoiceEnrollmentApplication);
-            initializeKeyphrasesFromTypedArray(array);
+            keyphraseMetadata = getKeyphraseFromTypedArray(array, packageName, parseErrors);
             array.recycle();
         } catch (XmlPullParserException e) {
-            mParseError = "Error parsing keyphrase enrollment meta-data: " + e;
-            Slog.w(TAG, "error parsing keyphrase enrollment meta-data", e);
-            return;
+            String error = "Error parsing keyphrase enrollment meta-data for " + packageName;
+            parseErrors.add(error + ": " + e);
+            Slog.w(TAG, error, e);
         } catch (IOException e) {
-            mParseError = "Error parsing keyphrase enrollment meta-data: " + e;
-            Slog.w(TAG, "error parsing keyphrase enrollment meta-data", e);
-            return;
+            String error = "Error parsing keyphrase enrollment meta-data for " + packageName;
+            parseErrors.add(error + ": " + e);
+            Slog.w(TAG, error, e);
         } catch (PackageManager.NameNotFoundException e) {
-            mParseError = "Error parsing keyphrase enrollment meta-data: " + e;
-            Slog.w(TAG, "error parsing keyphrase enrollment meta-data", e);
-            return;
+            String error = "Error parsing keyphrase enrollment meta-data for " + packageName;
+            parseErrors.add(error + ": " + e);
+            Slog.w(TAG, error, e);
         } finally {
             if (parser != null) parser.close();
         }
+        return keyphraseMetadata;
     }
 
-    private void initializeKeyphrasesFromTypedArray(TypedArray array) {
+    private KeyphraseMetadata getKeyphraseFromTypedArray(TypedArray array, String packageName,
+            List<String> parseErrors) {
         // Get the keyphrase ID.
         int searchKeyphraseId = array.getInt(
                 com.android.internal.R.styleable.VoiceEnrollmentApplication_searchKeyphraseId, -1);
         if (searchKeyphraseId <= 0) {
-            mParseError = "No valid searchKeyphraseId specified in meta-data";
-            Slog.w(TAG, mParseError);
-            return;
+            String error = "No valid searchKeyphraseId specified in meta-data for " + packageName;
+            parseErrors.add(error);
+            Slog.w(TAG, error);
+            return null;
         }
 
         // Get the keyphrase text.
         String searchKeyphrase = array.getString(
                 com.android.internal.R.styleable.VoiceEnrollmentApplication_searchKeyphrase);
         if (searchKeyphrase == null) {
-            mParseError = "No valid searchKeyphrase specified in meta-data";
-            Slog.w(TAG, mParseError);
-            return;
+            String error = "No valid searchKeyphrase specified in meta-data for " + packageName;
+            parseErrors.add(error);
+            Slog.w(TAG, error);
+            return null;
         }
 
         // Get the supported locales.
@@ -198,9 +235,11 @@
                 com.android.internal.R.styleable
                         .VoiceEnrollmentApplication_searchKeyphraseSupportedLocales);
         if (searchKeyphraseSupportedLocales == null) {
-            mParseError = "No valid searchKeyphraseSupportedLocales specified in meta-data";
-            Slog.w(TAG, mParseError);
-            return;
+            String error = "No valid searchKeyphraseSupportedLocales specified in meta-data for "
+                    + packageName;
+            parseErrors.add(error);
+            Slog.w(TAG, error);
+            return null;
         }
         ArraySet<Locale> locales = new ArraySet<>();
         // Try adding locales if the locale string is non-empty.
@@ -214,9 +253,11 @@
                 // We catch a generic exception here because we don't want the system service
                 // to be affected by a malformed metadata because invalid locales were specified
                 // by the system application.
-                mParseError = "Error reading searchKeyphraseSupportedLocales from meta-data";
-                Slog.w(TAG, mParseError, ex);
-                return;
+                String error = "Error reading searchKeyphraseSupportedLocales from meta-data for "
+                        + packageName;
+                parseErrors.add(error);
+                Slog.w(TAG, error);
+                return null;
             }
         }
 
@@ -224,13 +265,13 @@
         int recognitionModes = array.getInt(com.android.internal.R.styleable
                 .VoiceEnrollmentApplication_searchKeyphraseRecognitionFlags, -1);
         if (recognitionModes < 0) {
-            mParseError = "No valid searchKeyphraseRecognitionFlags specified in meta-data";
-            Slog.w(TAG, mParseError);
-            return;
+            String error = "No valid searchKeyphraseRecognitionFlags specified in meta-data for "
+                    + packageName;
+            parseErrors.add(error);
+            Slog.w(TAG, error);
+            return null;
         }
-        mKeyphrases = new KeyphraseMetadata[1];
-        mKeyphrases[0] = new KeyphraseMetadata(searchKeyphraseId, searchKeyphrase, locales,
-                recognitionModes);
+        return new KeyphraseMetadata(searchKeyphraseId, searchKeyphrase, locales, recognitionModes);
     }
 
     public String getParseError() {
@@ -259,14 +300,15 @@
      *         given keyphrase/locale combination isn't possible.
      */
     public Intent getManageKeyphraseIntent(int action, String keyphrase, Locale locale) {
-        if (mEnrollmentPackage == null || mEnrollmentPackage.isEmpty()) {
+        if (mKeyphrasePackageMap == null || mKeyphrasePackageMap.isEmpty()) {
             Slog.w(TAG, "No enrollment application exists");
             return null;
         }
 
-        if (getKeyphraseMetadata(keyphrase, locale) != null) {
+        KeyphraseMetadata keyphraseMetadata = getKeyphraseMetadata(keyphrase, locale);
+        if (keyphraseMetadata != null) {
             Intent intent = new Intent(ACTION_MANAGE_VOICE_KEYPHRASES)
-                    .setPackage(mEnrollmentPackage)
+                    .setPackage(mKeyphrasePackageMap.get(keyphraseMetadata))
                     .putExtra(EXTRA_VOICE_KEYPHRASE_HINT_TEXT, keyphrase)
                     .putExtra(EXTRA_VOICE_KEYPHRASE_LOCALE, locale.toLanguageTag())
                     .putExtra(EXTRA_VOICE_KEYPHRASE_ACTION, action);
@@ -298,14 +340,13 @@
                 return keyphraseMetadata;
             }
         }
-        Slog.w(TAG, "Enrollment application doesn't support the given keyphrase/locale");
+        Slog.w(TAG, "No Enrollment application supports the given keyphrase/locale");
         return null;
     }
 
     @Override
     public String toString() {
-        return "KeyphraseEnrollmentInfo [Keyphrases=" + Arrays.toString(mKeyphrases)
-                + ", EnrollmentPackage=" + mEnrollmentPackage + ", ParseError=" + mParseError
-                + "]";
+        return "KeyphraseEnrollmentInfo [Keyphrases=" + mKeyphrasePackageMap.toString()
+                + ", ParseError=" + mParseError + "]";
     }
 }
diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl
index c38bf3c..67d3959 100644
--- a/core/java/android/os/IUserManager.aidl
+++ b/core/java/android/os/IUserManager.aidl
@@ -45,6 +45,7 @@
     UserInfo getPrimaryUser();
     List<UserInfo> getUsers(boolean excludeDying);
     List<UserInfo> getProfiles(int userHandle, boolean enabledOnly);
+    int[] getProfileIds(int userId, boolean enabledOnly);
     boolean canAddMoreManagedProfiles(int userHandle, boolean allowedToRemoveOne);
     UserInfo getProfileParent(int userHandle);
     boolean isSameProfileGroup(int userHandle, int otherUserHandle);
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 707d5f5..d5b3b35 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -1590,18 +1590,46 @@
      * @return A non-empty list of UserHandles associated with the calling user.
      */
     public List<UserHandle> getUserProfiles() {
-        ArrayList<UserHandle> profiles = new ArrayList<UserHandle>();
-        List<UserInfo> users;
+        int[] userIds = getProfileIds(UserHandle.myUserId(), true /* enabledOnly */);
+        List<UserHandle> result = new ArrayList<>(userIds.length);
+        for (int userId : userIds) {
+            result.add(UserHandle.of(userId));
+        }
+        return result;
+    }
+
+    /**
+     * Returns a list of ids for profiles associated with the specified user including the user
+     * itself.
+     *
+     * @param userId      id of the user to return profiles for
+     * @param enabledOnly whether return only {@link UserInfo#isEnabled() enabled} profiles
+     * @return A non-empty list of ids of profiles associated with the specified user.
+     *
+     * @hide
+     */
+    public int[] getProfileIds(@UserIdInt int userId, boolean enabledOnly) {
         try {
-            users = mService.getProfiles(UserHandle.myUserId(), true /* enabledOnly */);
+            return mService.getProfileIds(userId, enabledOnly);
         } catch (RemoteException re) {
             throw re.rethrowFromSystemServer();
         }
-        for (UserInfo info : users) {
-            UserHandle userHandle = new UserHandle(info.id);
-            profiles.add(userHandle);
-        }
-        return profiles;
+    }
+
+    /**
+     * @see #getProfileIds(int, boolean)
+     * @hide
+     */
+    public int[] getProfileIdsWithDisabled(@UserIdInt int userId) {
+        return getProfileIds(userId, false /* enabledOnly */);
+    }
+
+    /**
+     * @see #getProfileIds(int, boolean)
+     * @hide
+     */
+    public int[] getEnabledProfileIds(@UserIdInt int userId) {
+        return getProfileIds(userId, true /* enabledOnly */);
     }
 
     /**
diff --git a/core/java/android/view/inputmethod/InputMethodSubtype.java b/core/java/android/view/inputmethod/InputMethodSubtype.java
index a42f4d9..dc433b1 100644
--- a/core/java/android/view/inputmethod/InputMethodSubtype.java
+++ b/core/java/android/view/inputmethod/InputMethodSubtype.java
@@ -68,6 +68,7 @@
     // TODO: remove this
     private static final String EXTRA_KEY_UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME =
             "UntranslatableReplacementStringInSubtypeName";
+    private static final int SUBTYPE_ID_NONE = 0;
 
     private final boolean mIsAuxiliary;
     private final boolean mOverridesImplicitlyEnabledSubtype;
@@ -157,13 +158,13 @@
          * track of enabled subtypes by ID. When the IME package gets upgraded, enabled IDs will
          * stay enabled even if other attributes are different. If the ID is unspecified or 0,
          * Arrays.hashCode(new Object[] {locale, mode, extraValue,
-         * isAuxiliary, overridesImplicitlyEnabledSubtype}) will be used instead.
+         * isAuxiliary, overridesImplicitlyEnabledSubtype, isAsciiCapable}) will be used instead.
          */
         public InputMethodSubtypeBuilder setSubtypeId(int subtypeId) {
             mSubtypeId = subtypeId;
             return this;
         }
-        private int mSubtypeId = 0;
+        private int mSubtypeId = SUBTYPE_ID_NONE;
 
         /**
          * @param subtypeLocale is the locale supported by this subtype.
@@ -268,7 +269,7 @@
      * subtypes by ID. When the IME package gets upgraded, enabled IDs will stay enabled even if
      * other attributes are different. If the ID is unspecified or 0,
      * Arrays.hashCode(new Object[] {locale, mode, extraValue,
-     * isAuxiliary, overridesImplicitlyEnabledSubtype}) will be used instead.
+     * isAuxiliary, overridesImplicitlyEnabledSubtype, isAsciiCapable}) will be used instead.
      */
     public InputMethodSubtype(int nameId, int iconId, String locale, String mode, String extraValue,
             boolean isAuxiliary, boolean overridesImplicitlyEnabledSubtype, int id) {
@@ -293,9 +294,12 @@
         mIsAsciiCapable = builder.mIsAsciiCapable;
         // If hashCode() of this subtype is 0 and you want to specify it as an id of this subtype,
         // just specify 0 as this subtype's id. Then, this subtype's id is treated as 0.
-        mSubtypeHashCode = mSubtypeId != 0 ? mSubtypeId : hashCodeInternal(mSubtypeLocale,
-                mSubtypeMode, mSubtypeExtraValue, mIsAuxiliary, mOverridesImplicitlyEnabledSubtype,
-                mIsAsciiCapable);
+        if (mSubtypeId != SUBTYPE_ID_NONE) {
+            mSubtypeHashCode = mSubtypeId;
+        } else {
+            mSubtypeHashCode = hashCodeInternal(mSubtypeLocale, mSubtypeMode, mSubtypeExtraValue,
+                    mIsAuxiliary, mOverridesImplicitlyEnabledSubtype, mIsAsciiCapable);
+        }
     }
 
     InputMethodSubtype(Parcel source) {
@@ -501,6 +505,22 @@
         return mSubtypeHashCode;
     }
 
+    /**
+     * @hide
+     * @return {@code true} if a valid subtype ID exists.
+     */
+    public final boolean hasSubtypeId() {
+        return mSubtypeId != SUBTYPE_ID_NONE;
+    }
+
+    /**
+     * @hide
+     * @return subtype ID. {@code 0} means that not subtype ID is specified.
+     */
+    public final int getSubtypeId() {
+        return mSubtypeId;
+    }
+
     @Override
     public boolean equals(Object o) {
         if (o instanceof InputMethodSubtype) {
diff --git a/core/java/com/android/internal/widget/ResolverDrawerLayout.java b/core/java/com/android/internal/widget/ResolverDrawerLayout.java
index 25b487e..c4347f8 100644
--- a/core/java/com/android/internal/widget/ResolverDrawerLayout.java
+++ b/core/java/com/android/internal/widget/ResolverDrawerLayout.java
@@ -17,14 +17,9 @@
 
 package com.android.internal.widget;
 
-import android.annotation.NonNull;
 import android.content.Context;
 import android.content.res.TypedArray;
-import android.graphics.Canvas;
-import android.graphics.Color;
 import android.graphics.Rect;
-import android.graphics.drawable.ColorDrawable;
-import android.graphics.drawable.Drawable;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -90,10 +85,6 @@
     private final float mMinFlingVelocity;
     private final OverScroller mScroller;
     private final VelocityTracker mVelocityTracker;
-    private final Drawable mScrollIndicatorDrawable;
-    private final Drawable mFakeForeground;
-
-    private View mButtonBar;
 
     private OnDismissedListener mOnDismissedListener;
     private RunOnDismissedListener mRunOnDismissedListener;
@@ -115,8 +106,6 @@
                 }
             };
 
-    private final int[] mTempOffset = new int[2];
-
     public ResolverDrawerLayout(Context context) {
         this(context, null);
     }
@@ -138,9 +127,6 @@
                 mMaxCollapsedHeight);
         a.recycle();
 
-        mScrollIndicatorDrawable = mContext.getDrawable(R.drawable.scroll_indicator_material);
-        mFakeForeground = new ColorDrawable(Color.TRANSPARENT);
-
         mScroller = new OverScroller(context, AnimationUtils.loadInterpolator(context,
                 android.R.interpolator.decelerate_quint));
         mVelocityTracker = VelocityTracker.obtain();
@@ -152,13 +138,6 @@
         setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
     }
 
-    @Override
-    protected void onFinishInflate() {
-        super.onFinishInflate();
-
-        mButtonBar = findViewById(R.id.button_bar);
-    }
-
     public void setSmallCollapsed(boolean smallCollapsed) {
         mSmallCollapsed = smallCollapsed;
         requestLayout();
@@ -223,7 +202,8 @@
             }
             final boolean isCollapsedNew = mCollapseOffset != 0;
             if (isCollapsedOld != isCollapsedNew) {
-                onCollapsedChanged(isCollapsedNew);
+                notifyViewAccessibilityStateChangedIfNeeded(
+                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
             }
         } else {
             // Start out collapsed at first unless we restored state for otherwise
@@ -462,7 +442,8 @@
             mTopOffset += dy;
             final boolean isCollapsedNew = newPos != 0;
             if (isCollapsedOld != isCollapsedNew) {
-                onCollapsedChanged(isCollapsedNew);
+                notifyViewAccessibilityStateChangedIfNeeded(
+                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
             }
             postInvalidateOnAnimation();
             return dy;
@@ -470,14 +451,6 @@
         return 0;
     }
 
-    private void onCollapsedChanged(boolean isCollapsed) {
-        notifyViewAccessibilityStateChangedIfNeeded(
-                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
-
-        // Set a fake foreground so that we receive onDrawForeground().
-        setForeground(isCollapsed ? mFakeForeground : null);
-    }
-
     void dispatchOnDismissed() {
         if (mOnDismissedListener != null) {
             mOnDismissedListener.onDismissed();
@@ -736,23 +709,6 @@
     }
 
     @Override
-    public void onDrawForeground(Canvas canvas) {
-        if (isCollapsed() && mButtonBar != null) {
-            // Draw the scroll indicator directly above the button bar.
-            final int height = mScrollIndicatorDrawable.getIntrinsicHeight();
-            mButtonBar.getLocationInWindow(mTempOffset);
-            final int barTop = mTempOffset[1];
-            getLocationInWindow(mTempOffset);
-            final int myTop = mTempOffset[1];
-            final int top = (barTop - myTop) - height;
-            mScrollIndicatorDrawable.setBounds(0, top, getWidth(), top + height);
-            mScrollIndicatorDrawable.draw(canvas);
-        }
-
-        super.onDrawForeground(canvas);
-    }
-
-    @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         final int sourceWidth = MeasureSpec.getSize(widthMeasureSpec);
         int widthSize = sourceWidth;
diff --git a/core/res/res/layout/resolver_list.xml b/core/res/res/layout/resolver_list.xml
index fe43e1c..4b8640c 100644
--- a/core/res/res/layout/resolver_list.xml
+++ b/core/res/res/layout/resolver_list.xml
@@ -30,37 +30,33 @@
         android:layout_height="wrap_content"
         android:layout_alwaysShow="true"
         android:elevation="8dp"
-        android:background="@color/white">
-
-        <TextView
-            android:id="@+id/profile_button"
-            android:layout_width="wrap_content"
-            android:layout_height="48dp"
-            android:layout_marginEnd="8dp"
-            android:paddingStart="8dp"
-            android:paddingEnd="8dp"
-            android:visibility="gone"
-            style="?attr/borderlessButtonStyle"
-            android:textAppearance="?attr/textAppearanceButton"
-            android:textColor="@color/material_deep_teal_500"
-            android:gravity="center_vertical"
-            android:layout_alignParentTop="true"
-            android:layout_alignParentRight="true"
-            android:singleLine="true" />
-
-        <TextView
-            android:id="@+id/title"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:minHeight="56dp"
-            android:textAppearance="?attr/textAppearanceMedium"
-            android:gravity="start|center_vertical"
-            android:paddingStart="?attr/dialogPreferredPadding"
-            android:paddingEnd="?attr/dialogPreferredPadding"
-            android:paddingTop="8dp"
-            android:layout_below="@id/profile_button"
-            android:layout_alignParentLeft="true"
-            android:paddingBottom="8dp" />
+        android:background="@color/white" >
+        <TextView android:id="@+id/profile_button"
+                  android:layout_width="wrap_content"
+                  android:layout_height="48dp"
+                  android:layout_marginEnd="8dp"
+                  android:paddingStart="8dp"
+                  android:paddingEnd="8dp"
+                  android:visibility="gone"
+                  style="?attr/borderlessButtonStyle"
+                  android:textAppearance="?attr/textAppearanceButton"
+                  android:textColor="@color/material_deep_teal_500"
+                  android:gravity="center_vertical"
+                  android:layout_alignParentTop="true"
+                  android:layout_alignParentRight="true"
+                  android:singleLine="true"/>
+        <TextView android:id="@+id/title"
+                  android:layout_width="wrap_content"
+                  android:layout_height="wrap_content"
+                  android:minHeight="56dp"
+                  android:textAppearance="?attr/textAppearanceMedium"
+                  android:gravity="start|center_vertical"
+                  android:paddingStart="?attr/dialogPreferredPadding"
+                  android:paddingEnd="?attr/dialogPreferredPadding"
+                  android:paddingTop="8dp"
+                  android:layout_below="@id/profile_button"
+                  android:layout_alignParentLeft="true"
+                  android:paddingBottom="8dp" />
     </RelativeLayout>
 
     <ListView
@@ -72,23 +68,21 @@
         android:background="@color/white"
         android:elevation="8dp"
         android:nestedScrollingEnabled="true"
-        android:scrollIndicators="top|bottom"
         android:divider="@null" />
 
-    <TextView
-        android:id="@+id/empty"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:layout_alwaysShow="true"
-        android:text="@string/noApplications"
-        android:padding="32dp"
-        android:gravity="center"
-        android:visibility="gone" />
+    <TextView android:id="@+id/empty"
+              android:layout_width="match_parent"
+              android:layout_height="match_parent"
+              android:layout_alwaysShow="true"
+              android:text="@string/noApplications"
+              android:padding="32dp"
+              android:gravity="center"
+              android:visibility="gone" />
 
     <LinearLayout
         android:id="@+id/button_bar"
         android:visibility="gone"
-        style="?attr/buttonBarStyle"
+        style="?android:attr/buttonBarStyle"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_ignoreOffset="true"
@@ -103,30 +97,26 @@
         android:paddingStart="12dp"
         android:paddingEnd="12dp"
         android:elevation="8dp">
-
-        <Button
-            android:id="@+id/button_once"
-            android:layout_width="wrap_content"
-            android:layout_gravity="start"
-            android:maxLines="2"
-            style="?attr/buttonBarNegativeButtonStyle"
-            android:minHeight="@dimen/alert_dialog_button_bar_height"
-            android:layout_height="wrap_content"
-            android:enabled="false"
-            android:text="@string/activity_resolver_use_once"
-            android:onClick="onButtonClick" />
-
-        <Button
-            android:id="@+id/button_always"
-            android:layout_width="wrap_content"
-            android:layout_gravity="end"
-            android:maxLines="2"
-            android:minHeight="@dimen/alert_dialog_button_bar_height"
-            style="?attr/buttonBarPositiveButtonStyle"
-            android:layout_height="wrap_content"
-            android:enabled="false"
-            android:text="@string/activity_resolver_use_always"
-            android:onClick="onButtonClick" />
+        <Button android:id="@+id/button_once"
+                android:layout_width="wrap_content"
+                android:layout_gravity="start"
+                android:maxLines="2"
+                style="?android:attr/buttonBarNegativeButtonStyle"
+                android:minHeight="@dimen/alert_dialog_button_bar_height"
+                android:layout_height="wrap_content"
+                android:enabled="false"
+                android:text="@string/activity_resolver_use_once"
+                android:onClick="onButtonClick" />
+        <Button android:id="@+id/button_always"
+                android:layout_width="wrap_content"
+                android:layout_gravity="end"
+                android:maxLines="2"
+                android:minHeight="@dimen/alert_dialog_button_bar_height"
+                style="?android:attr/buttonBarPositiveButtonStyle"
+                android:layout_height="wrap_content"
+                android:enabled="false"
+                android:text="@string/activity_resolver_use_always"
+                android:onClick="onButtonClick" />
     </LinearLayout>
 
 </com.android.internal.widget.ResolverDrawerLayout>
diff --git a/core/res/res/layout/resolver_list_with_default.xml b/core/res/res/layout/resolver_list_with_default.xml
index ed7ef5e..31361e5 100644
--- a/core/res/res/layout/resolver_list_with_default.xml
+++ b/core/res/res/layout/resolver_list_with_default.xml
@@ -22,7 +22,8 @@
     android:layout_height="match_parent"
     android:maxWidth="@dimen/resolver_max_width"
     android:maxCollapsedHeight="144dp"
-    android:id="@id/contentPanel">
+    android:id="@id/contentPanel"
+    >
 
     <LinearLayout
         android:layout_width="match_parent"
@@ -30,75 +31,66 @@
         android:layout_alwaysShow="true"
         android:orientation="vertical"
         android:background="@color/white"
-        android:elevation="8dp">
+        android:elevation="8dp" >
 
         <LinearLayout
             android:layout_width="match_parent"
             android:layout_height="64dp"
-            android:orientation="horizontal">
+            android:orientation="horizontal" >
 
-            <ImageView
-                android:id="@+id/icon"
-                android:layout_width="24dp"
-                android:layout_height="24dp"
-                android:layout_gravity="start|top"
-                android:layout_marginStart="16dp"
-                android:layout_marginEnd="16dp"
-                android:layout_marginTop="20dp"
-                android:scaleType="fitCenter" />
-
-            <TextView
-                android:id="@+id/title"
-                android:layout_width="0dp"
-                android:layout_weight="1"
-                android:layout_height="?attr/listPreferredItemHeight"
-                android:layout_marginStart="16dp"
-                android:textAppearance="?attr/textAppearanceMedium"
-                android:gravity="start|center_vertical"
-                android:paddingEnd="16dp" />
-
-            <LinearLayout
-                android:id="@+id/profile_button"
-                android:layout_width="wrap_content"
-                android:layout_height="48dp"
-                android:layout_marginTop="4dp"
-                android:layout_marginEnd="4dp"
-                android:paddingStart="8dp"
-                android:paddingEnd="8dp"
-                android:paddingTop="4dp"
-                android:paddingBottom="4dp"
-                android:focusable="true"
-                android:visibility="gone"
-                style="?attr/borderlessButtonStyle">
-
-                <ImageView
-                    android:id="@+id/icon"
-                    android:layout_width="24dp"
-                    android:layout_height="24dp"
-                    android:layout_gravity="start|center_vertical"
-                    android:layout_marginEnd="?attr/listPreferredItemPaddingEnd"
-                    android:layout_marginTop="12dp"
-                    android:layout_marginBottom="12dp"
-                    android:scaleType="fitCenter" />
-
-                <TextView
-                    android:id="@id/text1"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:layout_gravity="start|center_vertical"
-                    android:layout_marginEnd="?attr/listPreferredItemPaddingEnd"
-                    android:textAppearance="?attr/textAppearanceButton"
-                    android:textColor="?attr/textColorPrimary"
-                    android:minLines="1"
-                    android:maxLines="1"
-                    android:ellipsize="marquee" />
+            <ImageView android:id="@+id/icon"
+                       android:layout_width="24dp"
+                       android:layout_height="24dp"
+                       android:layout_gravity="start|top"
+                       android:layout_marginStart="16dp"
+                       android:layout_marginEnd="16dp"
+                       android:layout_marginTop="20dp"
+                       android:scaleType="fitCenter" />
+            <TextView android:id="@+id/title"
+                      android:layout_width="0dp"
+                      android:layout_weight="1"
+                      android:layout_height="?android:attr/listPreferredItemHeight"
+                      android:layout_marginStart="16dp"
+                      android:textAppearance="?android:attr/textAppearanceMedium"
+                      android:gravity="start|center_vertical"
+                      android:paddingEnd="16dp" />
+            <LinearLayout android:id="@+id/profile_button"
+                          android:layout_width="wrap_content"
+                          android:layout_height="48dp"
+                          android:layout_marginTop="4dp"
+                          android:layout_marginEnd="4dp"
+                          android:paddingStart="8dp"
+                          android:paddingEnd="8dp"
+                          android:paddingTop="4dp"
+                          android:paddingBottom="4dp"
+                          android:focusable="true"
+                          android:visibility="gone"
+                          style="?attr/borderlessButtonStyle">
+                <ImageView android:id="@+id/icon"
+                           android:layout_width="24dp"
+                           android:layout_height="24dp"
+                           android:layout_gravity="start|center_vertical"
+                           android:layout_marginEnd="?attr/listPreferredItemPaddingEnd"
+                           android:layout_marginTop="12dp"
+                           android:layout_marginBottom="12dp"
+                           android:scaleType="fitCenter" />
+                <TextView android:id="@id/text1"
+                          android:layout_width="wrap_content"
+                          android:layout_height="wrap_content"
+                          android:layout_gravity="start|center_vertical"
+                          android:layout_marginEnd="?attr/listPreferredItemPaddingEnd"
+                          android:textAppearance="?attr/textAppearanceButton"
+                          android:textColor="?attr/textColorPrimary"
+                          android:minLines="1"
+                          android:maxLines="1"
+                          android:ellipsize="marquee" />
             </LinearLayout>
         </LinearLayout>
 
         <LinearLayout
             android:id="@+id/button_bar"
             android:visibility="gone"
-            style="?attr/buttonBarStyle"
+            style="?android:attr/buttonBarStyle"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:layout_alwaysShow="true"
@@ -112,36 +104,30 @@
             android:paddingEnd="12dp"
             android:background="@color/white"
             android:elevation="8dp">
-
-            <Button
-                android:id="@+id/button_once"
-                android:layout_width="wrap_content"
-                android:layout_gravity="start"
-                android:maxLines="2"
-                style="?attr/buttonBarNegativeButtonStyle"
-                android:minHeight="@dimen/alert_dialog_button_bar_height"
-                android:layout_height="wrap_content"
-                android:enabled="false"
-                android:text="@string/activity_resolver_use_once"
-                android:onClick="onButtonClick" />
-
-            <Button
-                android:id="@+id/button_always"
-                android:layout_width="wrap_content"
-                android:layout_gravity="end"
-                android:maxLines="2"
-                android:minHeight="@dimen/alert_dialog_button_bar_height"
-                style="?attr/buttonBarPositiveButtonStyle"
-                android:layout_height="wrap_content"
-                android:enabled="false"
-                android:text="@string/activity_resolver_use_always"
-                android:onClick="onButtonClick" />
+            <Button android:id="@+id/button_once"
+                    android:layout_width="wrap_content"
+                    android:layout_gravity="start"
+                    android:maxLines="2"
+                    style="?android:attr/buttonBarNegativeButtonStyle"
+                    android:minHeight="@dimen/alert_dialog_button_bar_height"
+                    android:layout_height="wrap_content"
+                    android:enabled="false"
+                    android:text="@string/activity_resolver_use_once"
+                    android:onClick="onButtonClick" />
+            <Button android:id="@+id/button_always"
+                    android:layout_width="wrap_content"
+                    android:layout_gravity="end"
+                    android:maxLines="2"
+                    android:minHeight="@dimen/alert_dialog_button_bar_height"
+                    style="?android:attr/buttonBarPositiveButtonStyle"
+                    android:layout_height="wrap_content"
+                    android:enabled="false"
+                    android:text="@string/activity_resolver_use_always"
+                    android:onClick="onButtonClick" />
         </LinearLayout>
-
-        <View
-            android:layout_width="match_parent"
-            android:layout_height="1dp"
-            android:background="?attr/dividerVertical" />
+        <View android:layout_width="match_parent"
+              android:layout_height="1dp"
+              android:background="?android:attr/dividerVertical" />
     </LinearLayout>
 
     <ListView
@@ -154,6 +140,6 @@
         android:elevation="8dp"
         android:nestedScrollingEnabled="true"
         android:divider="@null"
-        android:scrollIndicators="top|bottom" />
+        />
 
 </com.android.internal.widget.ResolverDrawerLayout>
diff --git a/core/res/res/values-h426dp-port/integers.xml b/core/res/res/values-w320dp-h426dp/integers.xml
similarity index 100%
rename from core/res/res/values-h426dp-port/integers.xml
rename to core/res/res/values-w320dp-h426dp/integers.xml
diff --git a/core/res/res/values-w426dp-land/integers.xml b/core/res/res/values-w426dp-h320dp/integers.xml
similarity index 100%
rename from core/res/res/values-w426dp-land/integers.xml
rename to core/res/res/values-w426dp-h320dp/integers.xml
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index dfa5143b..cb551e8 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -420,9 +420,6 @@
     <!-- Boolean indicating we re-try re-associating once upon disconnection and RSSI is high failure  -->
     <bool translatable="true" name="config_wifi_enable_disconnection_debounce">true</bool>
 
-    <!-- Boolean indicating autojoin will prefer 5GHz and choose 5GHz BSSIDs -->
-    <bool translatable="true" name="config_wifi_enable_5GHz_preference">true</bool>
-
     <!-- Boolean indicating whether or not to revert to default country code when cellular
          radio is unable to find any MCC information to infer wifi country code from -->
     <bool translatable="false" name="config_wifi_revert_country_code_on_cellular_loss">false</bool>
@@ -439,8 +436,6 @@
     <!-- Integer specifying the basic autojoin parameters -->
     <integer translatable="false" name="config_wifi_framework_5GHz_preference_boost_threshold">-65</integer>
     <integer translatable="false" name="config_wifi_framework_5GHz_preference_boost_factor">40</integer>
-    <integer translatable="false" name="config_wifi_framework_current_association_hysteresis_high">16</integer>
-    <integer translatable="false" name="config_wifi_framework_current_association_hysteresis_low">10</integer>
     <integer translatable="false" name="config_wifi_framework_5GHz_preference_penalty_threshold">-75</integer>
     <integer translatable="false" name="config_wifi_framework_RSSI_SCORE_OFFSET">85</integer>
     <integer translatable="false" name="config_wifi_framework_RSSI_SCORE_SLOPE">4</integer>
@@ -495,15 +490,9 @@
     <!-- Integer indicating disconnect mode short scan interval in milliseconds -->
     <integer translatable="false" name="config_wifi_disconnected_short_scan_interval">15000</integer>
 
-    <!-- Integer indicating disconnect mode long scan interval in milliseconds -->
-    <integer translatable="false" name="config_wifi_disconnected_long_scan_interval">120000</integer>
-
     <!-- Integer indicating associated partial scan short interval in milliseconds -->
     <integer translatable="false" name="config_wifi_associated_short_scan_interval">20000</integer>
 
-    <!-- Integer indicating associated partial scan long interval in milliseconds -->
-    <integer translatable="false" name="config_wifi_associated_long_scan_interval">180000</integer>
-
     <!-- Integer indicating associated full scan backoff, representing a fraction: xx/8 -->
     <integer translatable="false" name="config_wifi_framework_associated_full_scan_backoff">12</integer>
 
@@ -516,18 +505,6 @@
     <!-- Integer indicating associated full scan max num active channels -->
     <integer translatable="false" name="config_wifi_framework_associated_partial_scan_max_num_active_channels">6</integer>
 
-    <!-- Integer indicating associated full scan max num passive channels -->
-    <integer translatable="false" name="config_wifi_framework_associated_partial_scan_max_num_passive_channels">3</integer>
-
-    <!-- Integer indicating number of association errors leading to blacklisting of the network -->
-    <integer translatable="false" name="config_wifi_framework_max_connection_errors_to_blacklist">4</integer>
-
-    <!-- Integer indicating number of authentication errors leading to blacklisting of the network -->
-    <integer translatable="false" name="config_wifi_framework_max_auth_errors_to_blacklist">4</integer>
-
-    <!-- Integer indicating minimum blacklisting delay of a wofo configuration due to connectin or auth errors -->
-    <integer translatable="false" name="config_wifi_framework_network_black_list_min_time_milli">120000</integer>
-
     <!-- Integer indicating RSSI boost given to current network -->
     <integer translatable="false" name="config_wifi_framework_current_network_boost">16</integer>
 
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 8d8b832..29c6951 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -295,7 +295,6 @@
   <java-symbol type="bool" name="config_wifi_framework_enable_associated_network_selection" />
   <java-symbol type="bool" name="config_wifi_only_link_same_credential_configurations" />
   <java-symbol type="bool" name="config_wifi_enable_disconnection_debounce" />
-  <java-symbol type="bool" name="config_wifi_enable_5GHz_preference" />
   <java-symbol type="bool" name="config_wifi_revert_country_code_on_cellular_loss" />
   <java-symbol type="bool" name="config_wifi_enable_wifi_firmware_debugging" />
   <java-symbol type="integer" name="config_wifi_logger_ring_buffer_size_limit_kb" />
@@ -312,8 +311,6 @@
   <java-symbol type="integer" name="config_wifi_framework_5GHz_preference_boost_threshold" />
   <java-symbol type="integer" name="config_wifi_framework_5GHz_preference_boost_factor" />
   <java-symbol type="integer" name="config_wifi_framework_5GHz_preference_penalty_threshold" />
-  <java-symbol type="integer" name="config_wifi_framework_current_association_hysteresis_high" />
-  <java-symbol type="integer" name="config_wifi_framework_current_association_hysteresis_low" />
   <java-symbol type="integer" name="config_wifi_framework_5GHz_preference_penalty_threshold" />
   <java-symbol type="integer" name="config_wifi_framework_RSSI_SCORE_OFFSET" />
   <java-symbol type="integer" name="config_wifi_framework_RSSI_SCORE_SLOPE" />
@@ -322,14 +319,11 @@
   <java-symbol type="integer" name="config_wifi_framework_PASSPOINT_SECURITY_AWARD" />
   <java-symbol type="integer" name="config_wifi_framework_SECURITY_AWARD" />
   <java-symbol type="integer" name="config_wifi_disconnected_short_scan_interval" />
-  <java-symbol type="integer" name="config_wifi_disconnected_long_scan_interval" />
   <java-symbol type="integer" name="config_wifi_associated_short_scan_interval" />
-  <java-symbol type="integer" name="config_wifi_associated_long_scan_interval" />
   <java-symbol type="integer" name="config_wifi_framework_associated_full_scan_backoff" />
   <java-symbol type="integer" name="config_wifi_framework_associated_full_scan_max_interval" />
   <java-symbol type="integer" name="config_wifi_framework_associated_full_scan_max_total_dwell_time" />
   <java-symbol type="integer" name="config_wifi_framework_associated_partial_scan_max_num_active_channels" />
-  <java-symbol type="integer" name="config_wifi_framework_associated_partial_scan_max_num_passive_channels" />
   <java-symbol type="integer" name="config_wifi_framework_wifi_score_bad_rssi_threshold_24GHz" />
   <java-symbol type="integer" name="config_wifi_framework_wifi_score_low_rssi_threshold_24GHz" />
   <java-symbol type="integer" name="config_wifi_framework_wifi_score_good_rssi_threshold_24GHz" />
@@ -359,9 +353,6 @@
   <java-symbol type="integer" name="config_wifi_framework_associated_partial_scan_rx_packet_threshold" />
   <java-symbol type="integer" name="config_wifi_framework_network_switch_tx_packet_threshold" />
   <java-symbol type="integer" name="config_wifi_framework_network_switch_rx_packet_threshold" />
-  <java-symbol type="integer" name="config_wifi_framework_max_connection_errors_to_blacklist" />
-  <java-symbol type="integer" name="config_wifi_framework_max_auth_errors_to_blacklist" />
-  <java-symbol type="integer" name="config_wifi_framework_network_black_list_min_time_milli" />
   <java-symbol type="integer" name="config_wifi_framework_current_network_boost" />
   <java-symbol type="integer" name="config_bluetooth_max_advertisers" />
   <java-symbol type="integer" name="config_bluetooth_max_scan_filters" />
diff --git a/core/res/res/values/themes_material.xml b/core/res/res/values/themes_material.xml
index 6611eb1..2ea5c5e 100644
--- a/core/res/res/values/themes_material.xml
+++ b/core/res/res/values/themes_material.xml
@@ -890,6 +890,11 @@
         <item name="listDivider">@null</item>
 
         <item name="preferencePanelStyle">@style/PreferencePanel.Dialog</item>
+
+        <item name="windowFixedWidthMajor">@null</item>
+        <item name="windowFixedWidthMinor">@null</item>
+        <item name="windowFixedHeightMajor">@null</item>
+        <item name="windowFixedHeightMinor">@null</item>
     </style>
 
     <!-- Theme overlay that overrides window properties to display as a date picker dialog. -->
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 5621642..640399f 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -1831,14 +1831,11 @@
         private void maybeNotifyProfiles(int userId, Uri uri, String name,
                 Set<String> keysCloned) {
             if (keysCloned.contains(name)) {
-                List<UserInfo> profiles = mUserManager.getProfiles(userId);
-                int size = profiles.size();
-                for (int i = 0; i < size; i++) {
-                    UserInfo profile = profiles.get(i);
+                for (int profileId : mUserManager.getProfileIdsWithDisabled(userId)) {
                     // the notification for userId has already been sent.
-                    if (profile.id != userId) {
+                    if (profileId != userId) {
                         mHandler.obtainMessage(MyHandler.MSG_NOTIFY_URI_CHANGED,
-                                profile.id, 0, uri).sendToTarget();
+                                profileId, 0, uri).sendToTarget();
                     }
                 }
             }
diff --git a/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java b/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java
index e1e0c3b..3b53055 100644
--- a/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java
+++ b/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java
@@ -179,42 +179,37 @@
         sendBugreportStarted(1000);
         waitForScreenshotButtonEnabled(true);
 
-        final NumberFormat nf = NumberFormat.getPercentInstance();
-        nf.setMinimumFractionDigits(2);
-        nf.setMaximumFractionDigits(2);
-
-        assertProgressNotification(NAME, nf.format(0));
+        assertProgressNotification(NAME, 0f);
 
         SystemProperties.set(PROGRESS_PROPERTY, "108");
-        assertProgressNotification(NAME, nf.format(0.108));
+        assertProgressNotification(NAME, 10.80f);
 
-        SystemProperties.set(PROGRESS_PROPERTY, "500");
-        assertProgressNotification(NAME, nf.format(0.50));
+        assertProgressNotification(NAME, 50.00f);
 
         SystemProperties.set(PROGRESS_PROPERTY, "950");
-        assertProgressNotification(NAME, nf.format(0.95));
+        assertProgressNotification(NAME, 95.00f);
 
         // Make sure progress never goes back...
         SystemProperties.set(MAX_PROPERTY, "2000");
         Thread.sleep(POLLING_FREQUENCY + DateUtils.SECOND_IN_MILLIS);
-        assertProgressNotification(NAME, nf.format(0.95));
+        assertProgressNotification(NAME, 95.00f);
 
         SystemProperties.set(PROGRESS_PROPERTY, "1000");
-        assertProgressNotification(NAME, nf.format(0.95));
+        assertProgressNotification(NAME, 95.00f);
 
         // ...only forward...
         SystemProperties.set(PROGRESS_PROPERTY, "1902");
-        assertProgressNotification(NAME, nf.format(0.9510));
+        assertProgressNotification(NAME, 95.10f);
 
         SystemProperties.set(PROGRESS_PROPERTY, "1960");
-        assertProgressNotification(NAME, nf.format(0.98));
+        assertProgressNotification(NAME, 98.00f);
 
         // ...but never more than the capped value.
         SystemProperties.set(PROGRESS_PROPERTY, "2000");
-        assertProgressNotification(NAME, nf.format(0.99));
+        assertProgressNotification(NAME, 99.00f);
 
         SystemProperties.set(PROGRESS_PROPERTY, "3000");
-        assertProgressNotification(NAME, nf.format(0.99));
+        assertProgressNotification(NAME, 99.00f);
 
         Bundle extras =
                 sendBugreportFinishedAndGetSharedIntent(ID, mPlainTextPath, mScreenshotPath);
@@ -233,7 +228,7 @@
         nf.setMinimumFractionDigits(2);
         nf.setMaximumFractionDigits(2);
 
-        assertProgressNotification(NAME, nf.format(0));
+        assertProgressNotification(NAME, 00.00f);
 
         openProgressNotification(ID);
         UiObject cancelButton = mUiBot.getVisibleObject(mContext.getString(
@@ -338,7 +333,7 @@
         detailsUi.clickOk();
 
         assertPropertyValue(NAME_PROPERTY, NEW_NAME);
-        assertProgressNotification(NEW_NAME, "0.00%");
+        assertProgressNotification(NEW_NAME, 00.00f);
 
         Bundle extras = sendBugreportFinishedAndGetSharedIntent(ID, mPlainTextPath,
                 mScreenshotPath);
@@ -375,7 +370,7 @@
         detailsUi.clickOk();
 
         assertPropertyValue(NAME_PROPERTY, NEW_NAME);
-        assertProgressNotification(NEW_NAME, "0.00%");
+        assertProgressNotification(NEW_NAME, 00.00f);
 
         Bundle extras = sendBugreportFinishedAndGetSharedIntent(ID,
                 plainText? mPlainTextPath : mZipPath, mScreenshotPath);
@@ -571,13 +566,13 @@
         }
     }
 
-    private void assertProgressNotification(String name, String percent) {
+    private void assertProgressNotification(String name, float percent) {
         // TODO: it currently looks for 3 distinct objects, without taking advantage of their
         // relationship.
         openProgressNotification(ID);
         Log.v(TAG, "Looking for progress notification details: '" + name + "-" + percent + "'");
         mUiBot.getObject(name);
-        mUiBot.getObject(percent);
+        // TODO: need a way to get the ProgresBar from the "android:id/progress" UIObject...
     }
 
     private UiObject openProgressNotification(int id) {
diff --git a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
index b88846b..5d3b5ff 100644
--- a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
@@ -84,6 +84,7 @@
             android:clickable="true"
             android:focusable="true"
             android:background="?android:attr/selectableItemBackgroundBorderless"
+            android:contentDescription="@string/accessibility_quick_settings_expand"
             android:padding="12dp" />
 
     </LinearLayout>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index a33b7a3..9f41dff 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1594,4 +1594,7 @@
     <!-- Warning message when we try to dock a non-resizeble tasks and launch it in fullscreen instead. -->
     <string name="dock_non_resizeble_failed_to_dock_text">App does not support split-screen.</string>
 
+    <!-- accessibility label for button to expand quick settings [CHAR LIMIT=NONE] -->
+    <string name="accessibility_quick_settings_expand">Expand quick settings.</string>
+
 </resources>
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 66754a7..f892fd6 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -847,17 +847,16 @@
 
     private void doKeyguardLaterForChildProfilesLocked() {
         UserManager um = UserManager.get(mContext);
-        List<UserInfo> profiles = um.getEnabledProfiles(UserHandle.myUserId());
-        for (UserInfo info : profiles) {
-            if (mLockPatternUtils.isSeparateProfileChallengeEnabled(info.id)) {
-                long userTimeout = getLockTimeout(info.id);
+        for (int profileId : um.getEnabledProfileIds(UserHandle.myUserId())) {
+            if (mLockPatternUtils.isSeparateProfileChallengeEnabled(profileId)) {
+                long userTimeout = getLockTimeout(profileId);
                 if (userTimeout == 0) {
                     doKeyguardForChildProfilesLocked();
                 } else {
                     long userWhen = SystemClock.elapsedRealtime() + userTimeout;
                     Intent lockIntent = new Intent(DELAYED_LOCK_PROFILE_ACTION);
                     lockIntent.putExtra("seq", mDelayedProfileShowingSequence);
-                    lockIntent.putExtra(Intent.EXTRA_USER_ID, info.id);
+                    lockIntent.putExtra(Intent.EXTRA_USER_ID, profileId);
                     PendingIntent lockSender = PendingIntent.getBroadcast(
                             mContext, 0, lockIntent, PendingIntent.FLAG_CANCEL_CURRENT);
                     mAlarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP,
@@ -869,10 +868,9 @@
 
     private void doKeyguardForChildProfilesLocked() {
         UserManager um = UserManager.get(mContext);
-        List<UserInfo> profiles = um.getEnabledProfiles(UserHandle.myUserId());
-        for (UserInfo info : profiles) {
-            if (mLockPatternUtils.isSeparateProfileChallengeEnabled(info.id)) {
-                lockProfile(info.id);
+        for (int profileId : um.getEnabledProfileIds(UserHandle.myUserId())) {
+            if (mLockPatternUtils.isSeparateProfileChallengeEnabled(profileId)) {
+                lockProfile(profileId);
             }
         }
     }
@@ -1482,9 +1480,8 @@
                 final UserHandle currentUser = new UserHandle(KeyguardUpdateMonitor.getCurrentUser());
                 final UserManager um = (UserManager) mContext.getSystemService(
                         Context.USER_SERVICE);
-                List <UserInfo> userHandles = um.getProfiles(currentUser.getIdentifier());
-                for (UserInfo ui : userHandles) {
-                    mContext.sendBroadcastAsUser(USER_PRESENT_INTENT, ui.getUserHandle());
+                for (int profileId : um.getProfileIdsWithDisabled(currentUser.getIdentifier())) {
+                    mContext.sendBroadcastAsUser(USER_PRESENT_INTENT, UserHandle.of(profileId));
                 }
             } else {
                 mBootSendUserPresent = true;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/PageIndicator.java b/packages/SystemUI/src/com/android/systemui/qs/PageIndicator.java
index ba07bf4..5cb46ac 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/PageIndicator.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/PageIndicator.java
@@ -118,6 +118,10 @@
         }
         ImageView first = (ImageView) getChildAt(firstIndex);
         ImageView second = (ImageView) getChildAt(secondIndex);
+        if (second == null) {
+            // Weird state where number of pages must not have propagated yet.
+            return;
+        }
         // Lay the two views on top of each other.
         second.setTranslationX(first.getX() - second.getX());
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileBaseView.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileBaseView.java
index 9e40cfd..44b38f1 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTileBaseView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileBaseView.java
@@ -93,6 +93,12 @@
         }
     }
 
+    @Override
+    public boolean hasOverlappingRendering() {
+        // Avoid layers for this layout - we don't need them.
+        return false;
+    }
+
     /**
      * Update the accessibility order for this view.
      *
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java
index e494fd8..77eaa3b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java
@@ -130,6 +130,8 @@
             }
         };
         state.label = percentage;
+        state.contentDescription = mContext.getString(R.string.accessibility_quick_settings_battery,
+                percentage);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivity.java b/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivity.java
index d4922c3..177296b 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivity.java
@@ -48,6 +48,7 @@
         setContentView(R.layout.forced_resizable_activity);
         TextView tv = (TextView) findViewById(com.android.internal.R.id.message);
         tv.setText(R.string.dock_forced_resizable);
+        getWindow().setTitle(getString(R.string.dock_forced_resizable));
         getWindow().getDecorView().setOnTouchListener(this);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index e52a401..75430ff 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -3470,7 +3470,7 @@
             @Override
             public void run() {
                 mLeaveOpenOnKeyguardHide = true;
-                executeRunnableDismissingKeyguard(runnable, null, false, true);
+                executeRunnableDismissingKeyguard(runnable, null, false, false);
             }
         });
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
index ea9a5a5..2b03dfb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
@@ -125,6 +125,7 @@
         // RenderThread is doing more harm than good when touching the header (to expand quick
         // settings), so disable it for this view
         ((RippleDrawable) mSettingsButton.getBackground()).setForceSoftware(true);
+        ((RippleDrawable) mExpandIndicator.getBackground()).setForceSoftware(true);
 
         updateResources();
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
index a85fe0d..5046456 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
@@ -114,8 +114,8 @@
 
     @Override
     public String getProfileOwnerName() {
-        for (UserInfo profile : mUserManager.getProfiles(mCurrentUserId)) {
-            String name = mDevicePolicyManager.getProfileOwnerNameAsUser(profile.id);
+        for (int profileId : mUserManager.getProfileIdsWithDisabled(mCurrentUserId)) {
+            String name = mDevicePolicyManager.getProfileOwnerNameAsUser(profileId);
             if (name != null) {
                 return name;
             }
@@ -135,13 +135,13 @@
 
     @Override
     public String getProfileVpnName() {
-        for (UserInfo profile : mUserManager.getProfiles(mVpnUserId)) {
-            if (profile.id == mVpnUserId) {
+        for (int profileId : mUserManager.getProfileIdsWithDisabled(mVpnUserId)) {
+            if (profileId == mVpnUserId) {
                 continue;
             }
-            VpnConfig cfg = mCurrentVpns.get(profile.id);
+            VpnConfig cfg = mCurrentVpns.get(profileId);
             if (cfg != null) {
-                return getNameForVpnConfig(cfg, profile.getUserHandle());
+                return getNameForVpnConfig(cfg, UserHandle.of(profileId));
             }
         }
         return null;
@@ -149,8 +149,8 @@
 
     @Override
     public boolean isVpnEnabled() {
-        for (UserInfo profile : mUserManager.getProfiles(mVpnUserId)) {
-            if (mCurrentVpns.get(profile.id) != null) {
+        for (int profileId : mUserManager.getProfileIdsWithDisabled(mVpnUserId)) {
+            if (mCurrentVpns.get(profileId) != null) {
                 return true;
             }
         }
diff --git a/packages/SystemUI/src/com/android/systemui/volume/SafetyWarningDialog.java b/packages/SystemUI/src/com/android/systemui/volume/SafetyWarningDialog.java
index 04640a2..d7c4bbf 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/SafetyWarningDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/SafetyWarningDialog.java
@@ -47,6 +47,7 @@
         mAudioManager = audioManager;
 
         getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
+        setShowForAllUsers(true);
         setMessage(mContext.getString(com.android.internal.R.string.safe_media_volume_warning));
         setButton(DialogInterface.BUTTON_POSITIVE,
                 mContext.getString(com.android.internal.R.string.yes), this);
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index f93fb1b..6ca3af8 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -460,12 +460,9 @@
         }
         synchronized (mLock) {
             reloadWidgetsMaskedState(userId);
-            List<UserInfo> profiles = mUserManager.getEnabledProfiles(userId);
-            if (profiles != null) {
-                for (int i = 0; i < profiles.size(); i++) {
-                    UserInfo user  = profiles.get(i);
-                    reloadWidgetsMaskedState(user.id);
-                }
+            int[] profileIds = mUserManager.getEnabledProfileIds(userId);
+            for (int profileId : profileIds) {
+                reloadWidgetsMaskedState(profileId);
             }
         }
     }
@@ -3458,33 +3455,12 @@
         public int[] getEnabledGroupProfileIds(int userId) {
             final int parentId = getGroupParent(userId);
 
-            final List<UserInfo> profiles;
             final long identity = Binder.clearCallingIdentity();
             try {
-                profiles = mUserManager.getProfiles(parentId);
+                return mUserManager.getEnabledProfileIds(parentId);
             } finally {
                 Binder.restoreCallingIdentity(identity);
             }
-
-            int enabledProfileCount = 0;
-            final int profileCount = profiles.size();
-            for (int i = 0; i < profileCount; i++) {
-                if (profiles.get(i).isEnabled()) {
-                    enabledProfileCount++;
-                }
-            }
-
-            int enabledProfileIndex = 0;
-            final int[] profileIds = new int[enabledProfileCount];
-            for (int i = 0; i < profileCount; i++) {
-                UserInfo profile = profiles.get(i);
-                if (profile.isEnabled()) {
-                    profileIds[enabledProfileIndex] = profile.getUserHandle().getIdentifier();
-                    enabledProfileIndex++;
-                }
-            }
-
-            return profileIds;
         }
 
         public void enforceServiceExistsAndRequiresBindRemoteViewsPermission(
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index ebef21f..428e192 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -165,7 +165,7 @@
         implements PendingIntent.OnFinished {
     private static final String TAG = "ConnectivityService";
 
-    private static final boolean DBG = false;
+    private static final boolean DBG = true;
     private static final boolean VDBG = false;
 
     private static final boolean LOGD_RULES = false;
@@ -450,9 +450,8 @@
      */
     private class LegacyTypeTracker {
 
-        private static final boolean DBG = false;
+        private static final boolean DBG = true;
         private static final boolean VDBG = false;
-        private static final String TAG = "CSLegacyTypeTracker";
 
         /**
          * Array of lists, one per legacy network type (e.g., TYPE_MOBILE_MMS).
@@ -605,12 +604,6 @@
             pw.decreaseIndent();
             pw.println();
         }
-
-        // This class needs its own log method because it has a different TAG.
-        private void log(String s) {
-            Slog.d(TAG, s);
-        }
-
     }
     private LegacyTypeTracker mLegacyTypeTracker = new LegacyTypeTracker();
 
@@ -1532,7 +1525,7 @@
                 mInitialBroadcast = new Intent(intent);
             }
             intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
-            if (DBG) {
+            if (VDBG) {
                 log("sendStickyBroadcast: action=" + intent.getAction());
             }
 
@@ -1660,7 +1653,7 @@
         }
 
         if (LinkProperties.isValidMtu(mtu, newLp.hasGlobalIPv6Address()) == false) {
-            loge("Unexpected mtu value: " + mtu + ", " + iface);
+            if (mtu != 0) loge("Unexpected mtu value: " + mtu + ", " + iface);
             return;
         }
 
@@ -1671,7 +1664,7 @@
         }
 
         try {
-            if (DBG) log("Setting MTU size: " + iface + ", " + mtu);
+            if (VDBG) log("Setting MTU size: " + iface + ", " + mtu);
             mNetd.setMtu(iface, mtu);
         } catch (Exception e) {
             Slog.e(TAG, "exception in setMtu()" + e);
@@ -1707,7 +1700,7 @@
         if (tcpBufferSizes.equals(mCurrentTcpBufferSizes)) return;
 
         try {
-            if (DBG) Slog.d(TAG, "Setting tx/rx TCP buffers to " + tcpBufferSizes);
+            if (VDBG) Slog.d(TAG, "Setting tx/rx TCP buffers to " + tcpBufferSizes);
 
             final String prefix = "/sys/kernel/ipv4/tcp_";
             FileUtils.stringToFile(prefix + "rmem_min", values[0]);
@@ -2315,7 +2308,7 @@
                 if (DBG) log("Attempt to release unowned NetworkRequest " + request);
                 return;
             }
-            if (DBG) log("releasing NetworkRequest " + request);
+            if (VDBG || (DBG && nri.isRequest())) log("releasing NetworkRequest " + request);
             nri.unlinkDeathRecipient();
             mNetworkRequests.remove(request);
             mNetworkRequestInfoLogs.log("RELEASE " + nri);
@@ -2328,7 +2321,7 @@
                 for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
                     if (nai.networkRequests.get(nri.request.requestId) != null) {
                         nai.networkRequests.remove(nri.request.requestId);
-                        if (DBG) {
+                        if (VDBG) {
                             log(" Removing from current network " + nai.name() +
                                     ", leaving " + nai.networkRequests.size() +
                                     " requests.");
@@ -2439,14 +2432,14 @@
     }
 
     private void scheduleUnvalidatedPrompt(NetworkAgentInfo nai) {
-        if (DBG) log("scheduleUnvalidatedPrompt " + nai.network);
+        if (VDBG) log("scheduleUnvalidatedPrompt " + nai.network);
         mHandler.sendMessageDelayed(
                 mHandler.obtainMessage(EVENT_PROMPT_UNVALIDATED, nai.network),
                 PROMPT_UNVALIDATED_DELAY_MS);
     }
 
     private void handlePromptUnvalidated(Network network) {
-        if (DBG) log("handlePromptUnvalidated " + network);
+        if (VDBG) log("handlePromptUnvalidated " + network);
         NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
 
         // Only prompt if the network is unvalidated and was explicitly selected by the user, and if
@@ -2489,11 +2482,14 @@
                             break;
                         }
                     }
-                    if (msg.what == EVENT_EXPIRE_NET_TRANSITION_WAKELOCK) {
-                        log("Failed to find a new network - expiring NetTransition Wakelock");
-                    } else {
-                        log("NetTransition Wakelock (" + (causedBy == null ? "unknown" : causedBy) +
-                                " cleared because we found a replacement network");
+                    if (VDBG) {
+                        if (msg.what == EVENT_EXPIRE_NET_TRANSITION_WAKELOCK) {
+                            log("Failed to find a new network - expiring NetTransition Wakelock");
+                        } else {
+                            log("NetTransition Wakelock (" +
+                                    (causedBy == null ? "unknown" : causedBy) +
+                                    " cleared because we found a replacement network");
+                        }
                     }
                     break;
                 }
@@ -3347,10 +3343,6 @@
     private static enum NotificationType { SIGN_IN, NO_INTERNET; };
 
     private void setProvNotificationVisible(boolean visible, int networkType, String action) {
-        if (DBG) {
-            log("setProvNotificationVisible: E visible=" + visible + " networkType=" + networkType
-                + " action=" + action);
-        }
         Intent intent = new Intent(action);
         PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0);
         // Concatenate the range of types onto the range of NetIDs.
@@ -3377,7 +3369,7 @@
     private void setProvNotificationVisibleIntent(boolean visible, int id,
             NotificationType notifyType, int networkType, String extraInfo, PendingIntent intent,
             boolean highPriority) {
-        if (DBG) {
+        if (VDBG || (DBG && visible)) {
             log("setProvNotificationVisibleIntent " + notifyType + " visible=" + visible
                     + " networkType=" + getNetworkTypeName(networkType)
                     + " extraInfo=" + extraInfo + " highPriority=" + highPriority);
@@ -3820,8 +3812,7 @@
         Bundle thresholds = new Bundle();
         thresholds.putIntegerArrayList("thresholds", thresholdsArray);
 
-        // TODO: Switch to VDBG.
-        if (DBG) {
+        if (VDBG || (DBG && !"CONNECT".equals(reason))) {
             String detail;
             if (request != null && request.networkCapabilities.hasSignalStrength()) {
                 detail = reason + " " + request.networkCapabilities.getSignalStrength();
@@ -3986,7 +3977,7 @@
                 new NetworkCapabilities(networkCapabilities), TYPE_NONE, nextNetworkRequestId());
         NetworkRequestInfo nri = new NetworkRequestInfo(messenger, networkRequest, binder,
                 NetworkRequestType.LISTEN);
-        if (DBG) log("listenForNetwork for " + nri);
+        if (VDBG) log("listenForNetwork for " + nri);
 
         mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_LISTENER, nri));
         return networkRequest;
@@ -4004,7 +3995,7 @@
                 new NetworkCapabilities(networkCapabilities), TYPE_NONE, nextNetworkRequestId());
         NetworkRequestInfo nri = new NetworkRequestInfo(networkRequest, operation,
                 NetworkRequestType.LISTEN);
-        if (DBG) log("pendingListenForNetwork for " + nri);
+        if (VDBG) log("pendingListenForNetwork for " + nri);
 
         mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_LISTENER, nri));
     }
@@ -4209,7 +4200,7 @@
         // do this twice, adding non-nexthop routes first, then routes they are dependent on
         for (RouteInfo route : routeDiff.added) {
             if (route.hasGateway()) continue;
-            if (DBG) log("Adding Route [" + route + "] to network " + netId);
+            if (VDBG) log("Adding Route [" + route + "] to network " + netId);
             try {
                 mNetd.addRoute(netId, route);
             } catch (Exception e) {
@@ -4220,7 +4211,7 @@
         }
         for (RouteInfo route : routeDiff.added) {
             if (route.hasGateway() == false) continue;
-            if (DBG) log("Adding Route [" + route + "] to network " + netId);
+            if (VDBG) log("Adding Route [" + route + "] to network " + netId);
             try {
                 mNetd.addRoute(netId, route);
             } catch (Exception e) {
@@ -4231,7 +4222,7 @@
         }
 
         for (RouteInfo route : routeDiff.removed) {
-            if (DBG) log("Removing Route [" + route + "] from network " + netId);
+            if (VDBG) log("Removing Route [" + route + "] from network " + netId);
             try {
                 mNetd.removeRoute(netId, route);
             } catch (Exception e) {
@@ -4247,7 +4238,7 @@
         }
 
         Collection<InetAddress> dnses = newLp.getDnsServers();
-        if (DBG) log("Setting Dns servers for network " + netId + " to " + dnses);
+        if (DBG) log("Setting DNS servers for network " + netId + " to " + dnses);
         try {
             mNetd.setDnsServersForNetwork(
                     netId, NetworkUtils.makeStrings(dnses), newLp.getDomains());
@@ -4515,14 +4506,14 @@
                 }
                 if (currentNetwork == null ||
                         currentNetwork.getCurrentScore() < newNetwork.getCurrentScore()) {
-                    if (DBG) log("rematch for " + newNetwork.name());
+                    if (VDBG) log("rematch for " + newNetwork.name());
                     if (currentNetwork != null) {
-                        if (DBG) log("   accepting network in place of " + currentNetwork.name());
+                        if (VDBG) log("   accepting network in place of " + currentNetwork.name());
                         currentNetwork.networkRequests.remove(nri.request.requestId);
                         currentNetwork.networkLingered.add(nri.request);
                         affectedNetworks.add(currentNetwork);
                     } else {
-                        if (DBG) log("   accepting network in place of null");
+                        if (VDBG) log("   accepting network in place of null");
                     }
                     unlinger(newNetwork);
                     mNetworkForRequestId.put(nri.request.requestId, newNetwork);
@@ -4852,7 +4843,7 @@
     }
 
     private void updateNetworkScore(NetworkAgentInfo nai, int score) {
-        if (DBG) log("updateNetworkScore for " + nai.name() + " to " + score);
+        if (VDBG) log("updateNetworkScore for " + nai.name() + " to " + score);
         if (score < 0) {
             loge("updateNetworkScore for " + nai.name() + " got a negative score (" + score +
                     ").  Bumping score to min of 0");
@@ -4930,7 +4921,7 @@
     }
 
     protected void notifyNetworkCallbacks(NetworkAgentInfo networkAgent, int notifyType) {
-        if (DBG) log("notifyType " + notifyTypeToName(notifyType) + " for " + networkAgent.name());
+        if (VDBG) log("notifyType " + notifyTypeToName(notifyType) + " for " + networkAgent.name());
         for (int i = 0; i < networkAgent.networkRequests.size(); i++) {
             NetworkRequest nr = networkAgent.networkRequests.valueAt(i);
             NetworkRequestInfo nri = mNetworkRequests.get(nr);
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index 58e3674..22cc066 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -66,7 +66,6 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
-import android.content.pm.UserInfo;
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
@@ -1050,12 +1049,8 @@
     }
 
     void updateCurrentProfileIds() {
-        List<UserInfo> profiles = mUserManager.getProfiles(mSettings.getCurrentUserId());
-        int[] currentProfileIds = new int[profiles.size()]; // profiles will not be null
-        for (int i = 0; i < currentProfileIds.length; i++) {
-            currentProfileIds[i] = profiles.get(i).id;
-        }
-        mSettings.setCurrentProfileIds(currentProfileIds);
+        mSettings.setCurrentProfileIds(
+                mUserManager.getProfileIdsWithDisabled(mSettings.getCurrentUserId()));
     }
 
     @Override
@@ -3649,6 +3644,7 @@
         private static final String ATTR_ID = "id";
         private static final String ATTR_LABEL = "label";
         private static final String ATTR_ICON = "icon";
+        private static final String ATTR_IME_SUBTYPE_ID = "subtypeId";
         private static final String ATTR_IME_SUBTYPE_LOCALE = "imeSubtypeLocale";
         private static final String ATTR_IME_SUBTYPE_LANGUAGE_TAG = "languageTag";
         private static final String ATTR_IME_SUBTYPE_MODE = "imeSubtypeMode";
@@ -3742,6 +3738,10 @@
                     for (int i = 0; i < N; ++i) {
                         final InputMethodSubtype subtype = subtypesList.get(i);
                         out.startTag(null, NODE_SUBTYPE);
+                        if (subtype.hasSubtypeId()) {
+                            out.attribute(null, ATTR_IME_SUBTYPE_ID,
+                                    String.valueOf(subtype.getSubtypeId()));
+                        }
                         out.attribute(null, ATTR_ICON, String.valueOf(subtype.getIconResId()));
                         out.attribute(null, ATTR_LABEL, String.valueOf(subtype.getNameResId()));
                         out.attribute(null, ATTR_IME_SUBTYPE_LOCALE, subtype.getLocale());
@@ -3820,7 +3820,7 @@
                                 parser.getAttributeValue(null, ATTR_IS_AUXILIARY)));
                         final boolean isAsciiCapable = "1".equals(String.valueOf(
                                 parser.getAttributeValue(null, ATTR_IS_ASCII_CAPABLE)));
-                        final InputMethodSubtype subtype = new InputMethodSubtypeBuilder()
+                        final InputMethodSubtypeBuilder builder = new InputMethodSubtypeBuilder()
                                 .setSubtypeNameResId(label)
                                 .setSubtypeIconResId(icon)
                                 .setSubtypeLocale(imeSubtypeLocale)
@@ -3828,9 +3828,13 @@
                                 .setSubtypeMode(imeSubtypeMode)
                                 .setSubtypeExtraValue(imeSubtypeExtraValue)
                                 .setIsAuxiliary(isAuxiliary)
-                                .setIsAsciiCapable(isAsciiCapable)
-                                .build();
-                        tempSubtypesArray.add(subtype);
+                                .setIsAsciiCapable(isAsciiCapable);
+                        final String subtypeIdString =
+                                parser.getAttributeValue(null, ATTR_IME_SUBTYPE_ID);
+                        if (subtypeIdString != null) {
+                            builder.setSubtypeId(Integer.valueOf(subtypeIdString));
+                        }
+                        tempSubtypesArray.add(builder.build());
                     }
                 }
             } catch (XmlPullParserException | IOException | NumberFormatException e) {
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index 9884a70..7c48634 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -21,6 +21,7 @@
 import com.android.internal.location.ProviderProperties;
 import com.android.internal.location.ProviderRequest;
 import com.android.internal.os.BackgroundThread;
+import com.android.internal.util.ArrayUtils;
 import com.android.server.location.ActivityRecognitionProxy;
 import com.android.server.location.FlpHardwareProvider;
 import com.android.server.location.FusedProxy;
@@ -53,7 +54,6 @@
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ResolveInfo;
 import android.content.pm.Signature;
-import android.content.pm.UserInfo;
 import android.content.res.Resources;
 import android.database.ContentObserver;
 import android.hardware.location.ActivityRecognitionHardware;
@@ -359,12 +359,9 @@
      * @param currentUserId the current user, who might have an alter-ego.
      */
     void updateUserProfiles(int currentUserId) {
-        List<UserInfo> profiles = mUserManager.getProfiles(currentUserId);
+        int[] profileIds = mUserManager.getProfileIdsWithDisabled(currentUserId);
         synchronized (mLock) {
-            mCurrentUserProfiles = new int[profiles.size()];
-            for (int i = 0; i < mCurrentUserProfiles.length; i++) {
-                mCurrentUserProfiles[i] = profiles.get(i).id;
-            }
+            mCurrentUserProfiles = profileIds;
         }
     }
 
@@ -374,12 +371,7 @@
      */
     private boolean isCurrentProfile(int userId) {
         synchronized (mLock) {
-            for (int i = 0; i < mCurrentUserProfiles.length; i++) {
-                if (mCurrentUserProfiles[i] == userId) {
-                    return true;
-                }
-            }
-            return false;
+            return ArrayUtils.contains(mCurrentUserProfiles, userId);
         }
     }
 
diff --git a/services/core/java/com/android/server/TextServicesManagerService.java b/services/core/java/com/android/server/TextServicesManagerService.java
index 3eb20a0..801d6e0 100644
--- a/services/core/java/com/android/server/TextServicesManagerService.java
+++ b/services/core/java/com/android/server/TextServicesManagerService.java
@@ -43,7 +43,6 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
-import android.content.pm.UserInfo;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.IBinder;
@@ -195,12 +194,8 @@
     }
 
     void updateCurrentProfileIds() {
-        final List<UserInfo> profiles = mUserManager.getProfiles(mSettings.getCurrentUserId());
-        int[] currentProfileIds = new int[profiles.size()]; // profiles will not be null
-        for (int i = 0; i < currentProfileIds.length; i++) {
-            currentProfileIds[i] = profiles.get(i).id;
-        }
-        mSettings.setCurrentProfileIds(currentProfileIds);
+        mSettings.setCurrentProfileIds(
+                mUserManager.getProfileIdsWithDisabled(mSettings.getCurrentUserId()));
     }
 
     private class TextServicesMonitor extends PackageMonitor {
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index bea26c7..5ebb9a7 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -278,6 +278,31 @@
                 // Dispatch unlocked to system services
                 mHandler.sendMessage(mHandler.obtainMessage(SYSTEM_USER_UNLOCK_MSG, userId, 0));
 
+                // Dispatch unlocked to external apps
+                final Intent unlockedIntent = new Intent(Intent.ACTION_USER_UNLOCKED);
+                unlockedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
+                unlockedIntent.addFlags(
+                        Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND);
+                mService.broadcastIntentLocked(null, null, unlockedIntent, null, null, 0, null,
+                        null, null, AppOpsManager.OP_NONE, null, false, false, MY_PID, SYSTEM_UID,
+                        userId);
+
+                if (getUserInfo(userId).isManagedProfile()) {
+                    UserInfo parent = getUserManager().getProfileParent(userId);
+                    if (parent != null) {
+                        final Intent profileUnlockedIntent = new Intent(
+                                Intent.ACTION_MANAGED_PROFILE_UNLOCKED);
+                        profileUnlockedIntent.putExtra(Intent.EXTRA_USER, UserHandle.of(userId));
+                        profileUnlockedIntent.addFlags(
+                                Intent.FLAG_RECEIVER_REGISTERED_ONLY
+                                | Intent.FLAG_RECEIVER_FOREGROUND);
+                        mService.broadcastIntentLocked(null, null, profileUnlockedIntent,
+                                null, null, 0, null, null, null, AppOpsManager.OP_NONE,
+                                null, false, false, MY_PID, SYSTEM_UID,
+                                parent.id);
+                    }
+                }
+
                 // Send PRE_BOOT broadcasts if fingerprint changed
                 final UserInfo info = getUserInfo(userId);
                 if (!Objects.equals(info.lastLoggedInFingerprint, Build.FINGERPRINT)) {
@@ -320,31 +345,6 @@
                 // Remember that we logged in
                 mUserManager.onUserLoggedIn(userId);
 
-                // Dispatch unlocked to external apps
-                final Intent unlockedIntent = new Intent(Intent.ACTION_USER_UNLOCKED);
-                unlockedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
-                unlockedIntent.addFlags(
-                        Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND);
-                mService.broadcastIntentLocked(null, null, unlockedIntent, null, null, 0, null,
-                        null, null, AppOpsManager.OP_NONE, null, false, false, MY_PID, SYSTEM_UID,
-                        userId);
-
-                if (getUserInfo(userId).isManagedProfile()) {
-                    UserInfo parent = getUserManager().getProfileParent(userId);
-                    if (parent != null) {
-                        final Intent profileUnlockedIntent = new Intent(
-                                Intent.ACTION_MANAGED_PROFILE_UNLOCKED);
-                        profileUnlockedIntent.putExtra(Intent.EXTRA_USER, UserHandle.of(userId));
-                        profileUnlockedIntent.addFlags(
-                                Intent.FLAG_RECEIVER_REGISTERED_ONLY
-                                | Intent.FLAG_RECEIVER_FOREGROUND);
-                        mService.broadcastIntentLocked(null, null, profileUnlockedIntent,
-                                null, null, 0, null, null, null, AppOpsManager.OP_NONE,
-                                null, false, false, MY_PID, SYSTEM_UID,
-                                parent.id);
-                    }
-                }
-
                 final Intent bootIntent = new Intent(Intent.ACTION_BOOT_COMPLETED, null);
                 bootIntent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
                 bootIntent.addFlags(Intent.FLAG_RECEIVER_NO_ABORT
@@ -893,8 +893,9 @@
     boolean unlockUserCleared(final int userId, byte[] token, byte[] secret,
             ProgressReporter progress) {
         synchronized (mService) {
-            // Bail if already running unlocked
+            // Bail if already running unlocked, or if not running at all
             final UserState uss = mStartedUsers.get(userId);
+            if (uss == null) return false;
             switch (uss.state) {
                 case STATE_RUNNING_UNLOCKING:
                 case STATE_RUNNING_UNLOCKED:
diff --git a/services/core/java/com/android/server/camera/CameraService.java b/services/core/java/com/android/server/camera/CameraService.java
index cd8eb4e..7d9adf2 100644
--- a/services/core/java/com/android/server/camera/CameraService.java
+++ b/services/core/java/com/android/server/camera/CameraService.java
@@ -15,32 +15,28 @@
  */
 package com.android.server.camera;
 
-import android.app.ActivityManager;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.content.pm.UserInfo;
 import android.hardware.ICameraService;
 import android.hardware.ICameraServiceProxy;
 import android.nfc.INfcAdapter;
+import android.os.Binder;
 import android.os.Handler;
 import android.os.IBinder;
-import android.os.Binder;
 import android.os.Message;
 import android.os.Process;
 import android.os.RemoteException;
-import android.os.UserManager;
 import android.os.SystemProperties;
-import android.util.Slog;
+import android.os.UserManager;
 import android.util.ArraySet;
+import android.util.Slog;
 
 import com.android.server.ServiceThread;
 import com.android.server.SystemService;
 
 import java.util.Collection;
-import java.util.HashSet;
-import java.util.List;
 import java.util.Set;
 
 /**
@@ -225,11 +221,11 @@
     }
 
     private Set<Integer> getEnabledUserHandles(int currentUserHandle) {
-        List<UserInfo> userProfiles = mUserManager.getEnabledProfiles(currentUserHandle);
-        Set<Integer> handles = new HashSet<>(userProfiles.size());
+        int[] userProfiles = mUserManager.getEnabledProfileIds(currentUserHandle);
+        Set<Integer> handles = new ArraySet<>(userProfiles.length);
 
-        for (UserInfo i : userProfiles) {
-            handles.add(i.id);
+        for (int id : userProfiles) {
+            handles.add(id);
         }
 
         return handles;
diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java
index 3d8bf51..e3f3849 100644
--- a/services/core/java/com/android/server/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java
@@ -541,10 +541,8 @@
         UserManager um = UserManager.get(mContext);
 
         // Allow current user or profiles of the current user...
-        List<UserInfo> profiles = um.getEnabledProfiles(userId);
-        final int n = profiles.size();
-        for (int i = 0; i < n; i++) {
-            if (profiles.get(i).id == userId) {
+        for (int profileId : um.getEnabledProfileIds(userId)) {
+            if (profileId == userId) {
                 return true;
             }
         }
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index a89a422..f29970c 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -176,10 +176,7 @@
         mRankingTimeMs = calculateRankingTimeMs(previous.getRankingTimeMs());
         mCreationTimeMs = previous.mCreationTimeMs;
         mVisibleSinceMs = previous.mVisibleSinceMs;
-        mUserImportance = previous.mUserImportance;
-        mImportance = previous.mImportance;
-        mImportanceExplanation = previous.mImportanceExplanation;
-        // Don't copy mGlobalSortKey, recompute it.
+        // Don't copy importance information or mGlobalSortKey, recompute them.
     }
 
     public Notification getNotification() { return sbn.getNotification(); }
diff --git a/services/core/java/com/android/server/pm/BackgroundDexOptService.java b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
index da9cd8b..f6255af 100644
--- a/services/core/java/com/android/server/pm/BackgroundDexOptService.java
+++ b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
@@ -89,6 +89,15 @@
         }
     }
 
+    public static void notifyPackageChanged(String packageName) {
+        // The idle maintanance job skips packages which previously failed to
+        // compile. The given package has changed and may successfully compile
+        // now. Remove it from the list of known failing packages.
+        synchronized (sFailedPackageNames) {
+            sFailedPackageNames.remove(packageName);
+        }
+    }
+
     // Returns the current battery level as a 0-100 integer.
     private int getBatteryLevel() {
         IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
@@ -170,7 +179,9 @@
                     }
                     // Conservatively add package to the list of failing ones in case performDexOpt
                     // never returns.
-                    sFailedPackageNames.add(pkg);
+                    synchronized (sFailedPackageNames) {
+                        sFailedPackageNames.add(pkg);
+                    }
                     // Optimize package if needed. Note that there can be no race between
                     // concurrent jobs because PackageDexOptimizer.performDexOpt is synchronized.
                     if (pm.performDexOpt(pkg,
@@ -179,7 +190,9 @@
                             PackageManagerService.REASON_BACKGROUND_DEXOPT,
                             /* force */ false)) {
                         // Dexopt succeeded, remove package from the list of failing ones.
-                        sFailedPackageNames.remove(pkg);
+                        synchronized (sFailedPackageNames) {
+                            sFailedPackageNames.remove(pkg);
+                        }
                     }
                 }
                 // Ran to completion, so we abandon our timeslice and do not reschedule.
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index 4c18e15..79d9c86 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -213,8 +213,11 @@
          * Checks if the caller is in the same group as the userToCheck.
          */
         private void ensureInUserProfiles(UserHandle userToCheck, String message) {
+            ensureInUserProfiles(userToCheck.getIdentifier(), message);
+        }
+
+        private void ensureInUserProfiles(int targetUserId, String message) {
             final int callingUserId = injectCallingUserId();
-            final int targetUserId = userToCheck.getIdentifier();
 
             if (targetUserId == callingUserId) return;
 
@@ -253,9 +256,13 @@
          * Checks if the user is enabled.
          */
         private boolean isUserEnabled(UserHandle user) {
+            return isUserEnabled(user.getIdentifier());
+        }
+
+        private boolean isUserEnabled(int userId) {
             long ident = injectClearCallingIdentity();
             try {
-                UserInfo targetUserInfo = mUm.getUserInfo(user.getIdentifier());
+                UserInfo targetUserInfo = mUm.getUserInfo(userId);
                 return targetUserInfo != null && targetUserInfo.isEnabled();
             } finally {
                 injectRestoreCallingIdentity(ident);
@@ -346,8 +353,12 @@
         }
 
         private void ensureShortcutPermission(@NonNull String callingPackage, UserHandle user) {
+            ensureShortcutPermission(callingPackage, user.getIdentifier());
+        }
+
+        private void ensureShortcutPermission(@NonNull String callingPackage, int userId) {
             verifyCallingPackage(callingPackage);
-            ensureInUserProfiles(user, "Cannot start activity for unrelated profile " + user);
+            ensureInUserProfiles(userId, "Cannot start activity for unrelated profile " + userId);
 
             if (!mShortcutServiceInternal.hasShortcutHostPermission(getCallingUserId(),
                     callingPackage)) {
@@ -357,32 +368,24 @@
 
         @Override
         public ParceledListSlice getShortcuts(String callingPackage, long changedSince,
-                String packageName, ComponentName componentName, int flags, UserHandle user) {
+                String packageName, List shortcutIds, ComponentName componentName, int flags,
+                UserHandle user) {
             ensureShortcutPermission(callingPackage, user);
             if (!isUserEnabled(user)) {
                 return new ParceledListSlice<>(new ArrayList(0));
             }
+            if (shortcutIds != null && packageName == null) {
+                throw new IllegalArgumentException(
+                        "To query by shortcut ID, package name must also be set");
+            }
 
             return new ParceledListSlice<>(
                     mShortcutServiceInternal.getShortcuts(getCallingUserId(),
-                            callingPackage, changedSince, packageName,
+                            callingPackage, changedSince, packageName, shortcutIds,
                             componentName, flags, user.getIdentifier()));
         }
 
         @Override
-        public ParceledListSlice getShortcutInfo(String callingPackage, String packageName,
-                List<String> ids, UserHandle user) {
-            ensureShortcutPermission(callingPackage, user);
-            if (!isUserEnabled(user)) {
-                return new ParceledListSlice<>(new ArrayList(0));
-            }
-
-            return new ParceledListSlice<>(
-                    mShortcutServiceInternal.getShortcutInfo(getCallingUserId(),
-                            callingPackage, packageName, ids, user.getIdentifier()));
-        }
-
-        @Override
         public void pinShortcuts(String callingPackage, String packageName, List<String> ids,
                 UserHandle user) {
             ensureShortcutPermission(callingPackage, user);
@@ -396,27 +399,27 @@
         }
 
         @Override
-        public int getShortcutIconResId(String callingPackage, ShortcutInfo shortcut,
-                UserHandle user) {
-            ensureShortcutPermission(callingPackage, user);
-            if (!isUserEnabled(user)) {
+        public int getShortcutIconResId(String callingPackage, String packageName, String id,
+                int userId) {
+            ensureShortcutPermission(callingPackage, userId);
+            if (!isUserEnabled(userId)) {
                 return 0;
             }
 
             return mShortcutServiceInternal.getShortcutIconResId(getCallingUserId(),
-                    callingPackage, shortcut, user.getIdentifier());
+                    callingPackage, packageName, id, userId);
         }
 
         @Override
-        public ParcelFileDescriptor getShortcutIconFd(String callingPackage, ShortcutInfo shortcut,
-                UserHandle user) {
-            ensureShortcutPermission(callingPackage, user);
-            if (!isUserEnabled(user)) {
+        public ParcelFileDescriptor getShortcutIconFd(String callingPackage,
+                String packageName, String id, int userId) {
+            ensureShortcutPermission(callingPackage, userId);
+            if (!isUserEnabled(userId)) {
                 return null;
             }
 
             return mShortcutServiceInternal.getShortcutIconFd(getCallingUserId(),
-                    callingPackage, shortcut, user.getIdentifier());
+                    callingPackage, packageName, id, userId);
         }
 
         @Override
@@ -428,23 +431,23 @@
 
         @Override
         public boolean startShortcut(String callingPackage, String packageName, String shortcutId,
-                Rect sourceBounds, Bundle startActivityOptions, UserHandle user) {
+                Rect sourceBounds, Bundle startActivityOptions, int userId) {
             verifyCallingPackage(callingPackage);
-            ensureInUserProfiles(user, "Cannot start activity for unrelated profile " + user);
+            ensureInUserProfiles(userId, "Cannot start activity for unrelated profile " + userId);
 
-            if (!isUserEnabled(user)) {
+            if (!isUserEnabled(userId)) {
                 throw new IllegalStateException("Cannot start a shortcut for disabled profile "
-                        + user);
+                        + userId);
             }
 
             // Even without the permission, pinned shortcuts are always launchable.
             if (!mShortcutServiceInternal.isPinnedByCaller(getCallingUserId(),
-                    callingPackage, packageName, shortcutId, user.getIdentifier())) {
-                ensureShortcutPermission(callingPackage, user);
+                    callingPackage, packageName, shortcutId, userId)) {
+                ensureShortcutPermission(callingPackage, userId);
             }
 
             final Intent intent = mShortcutServiceInternal.createShortcutIntent(getCallingUserId(),
-                    callingPackage, packageName, shortcutId, user.getIdentifier());
+                    callingPackage, packageName, shortcutId, userId);
             if (intent == null) {
                 return false;
             }
@@ -455,7 +458,7 @@
 
             final long ident = Binder.clearCallingIdentity();
             try {
-                mContext.startActivityAsUser(intent, startActivityOptions, user);
+                mContext.startActivityAsUser(intent, startActivityOptions, UserHandle.of(userId));
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
@@ -768,7 +771,8 @@
                     final List<ShortcutInfo> list =
                             mShortcutServiceInternal.getShortcuts(launcherUserId,
                                     cookie.packageName,
-                                    /* changedSince= */ 0, packageName, /* component= */ null,
+                                    /* changedSince= */ 0, packageName, /* shortcutIds=*/ null,
+                                    /* component= */ null,
                                     ShortcutQuery.FLAG_GET_KEY_FIELDS_ONLY
                                     | ShortcutQuery.FLAG_GET_PINNED
                                     | ShortcutQuery.FLAG_GET_DYNAMIC
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index c81984e..3b07fe1 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -229,6 +229,7 @@
 import com.android.internal.os.InstallerConnection.InstallerException;
 import com.android.internal.os.SomeArgs;
 import com.android.internal.os.Zygote;
+import com.android.internal.telephony.CarrierAppUtils;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.FastPrintWriter;
 import com.android.internal.util.FastXmlSerializer;
@@ -2051,6 +2052,10 @@
         PackageManagerService m = new PackageManagerService(context, installer,
                 factoryTest, onlyCore);
         m.enableSystemUserPackages();
+        // Disable any carrier apps. We do this very early in boot to prevent the apps from being
+        // disabled after already being started.
+        CarrierAppUtils.disableCarrierAppsUntilPrivileged(context.getOpPackageName(), m,
+                UserHandle.USER_SYSTEM);
         ServiceManager.addService("package", m);
         return m;
     }
@@ -4716,27 +4721,39 @@
     @Override
     public ResolveInfo resolveIntent(Intent intent, String resolvedType,
             int flags, int userId) {
-        if (!sUserManager.exists(userId)) return null;
-        flags = updateFlagsForResolve(flags, userId, intent);
-        enforceCrossUserPermission(Binder.getCallingUid(), userId,
-                false /* requireFullPermission */, false /* checkShell */, "resolve intent");
-        final List<ResolveInfo> query = queryIntentActivitiesInternal(intent, resolvedType, flags,
-                userId);
-        final ResolveInfo bestChoice =
-                chooseBestActivity(intent, resolvedType, flags, query, userId);
+        try {
+            Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "resolveIntent");
 
-        if (isEphemeralAllowed(intent, query, userId)) {
-            final EphemeralResolveInfo ai =
-                    getEphemeralResolveInfo(intent, resolvedType, userId);
-            if (ai != null) {
-                if (DEBUG_EPHEMERAL) {
-                    Slog.v(TAG, "Returning an EphemeralResolveInfo");
+            if (!sUserManager.exists(userId)) return null;
+            flags = updateFlagsForResolve(flags, userId, intent);
+            enforceCrossUserPermission(Binder.getCallingUid(), userId,
+                    false /*requireFullPermission*/, false /*checkShell*/, "resolve intent");
+
+            Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "queryIntentActivities");
+            final List<ResolveInfo> query = queryIntentActivitiesInternal(intent, resolvedType,
+                    flags, userId);
+            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+
+            final ResolveInfo bestChoice =
+                    chooseBestActivity(intent, resolvedType, flags, query, userId);
+
+            if (isEphemeralAllowed(intent, query, userId)) {
+                Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "resolveEphemeral");
+                final EphemeralResolveInfo ai =
+                        getEphemeralResolveInfo(intent, resolvedType, userId);
+                if (ai != null) {
+                    if (DEBUG_EPHEMERAL) {
+                        Slog.v(TAG, "Returning an EphemeralResolveInfo");
+                    }
+                    bestChoice.ephemeralInstaller = mEphemeralInstallerInfo;
+                    bestChoice.ephemeralResolveInfo = ai;
                 }
-                bestChoice.ephemeralInstaller = mEphemeralInstallerInfo;
-                bestChoice.ephemeralResolveInfo = ai;
+                Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
             }
+            return bestChoice;
+        } finally {
+            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
         }
-        return bestChoice;
     }
 
     @Override
@@ -5183,8 +5200,14 @@
     @Override
     public @NonNull ParceledListSlice<ResolveInfo> queryIntentActivities(Intent intent,
             String resolvedType, int flags, int userId) {
-        return new ParceledListSlice<>(
-                queryIntentActivitiesInternal(intent, resolvedType, flags, userId));
+        try {
+            Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "queryIntentActivities");
+
+            return new ParceledListSlice<>(
+                    queryIntentActivitiesInternal(intent, resolvedType, flags, userId));
+        } finally {
+            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+        }
     }
 
     private @NonNull List<ResolveInfo> queryIntentActivitiesInternal(Intent intent,
@@ -13648,6 +13671,16 @@
                 }
             }
 
+            // 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;
+            }
+
             // In case of rollback, remember per-user/profile install state
             allUsers = sUserManager.getUserIds();
         }
@@ -13897,15 +13930,6 @@
             setInstallAndUpdateTime(newPackage, deletedPkgSetting.firstInstallTime,
                     System.currentTimeMillis());
 
-            // Check for shared user id changes
-            String invalidPackageName = getParentOrChildPackageChangedSharedUser(
-                    deletedPackage, newPackage);
-            if (invalidPackageName != null) {
-                res.setError(INSTALL_FAILED_SHARED_USER_INCOMPATIBLE,
-                        "Forbidding shared user change from " + deletedPkgSetting.sharedUser
-                                + " to " + invalidPackageName);
-            }
-
             // Update the package dynamic state if succeeded
             if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
                 // Now that the install succeeded make sure we remove data
@@ -14516,7 +14540,6 @@
                 return;
             }
 
-
             Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt");
             // Do not run PackageDexOptimizer through the local performDexOpt
             // method because `pkg` is not in `mPackages` yet.
@@ -14524,10 +14547,15 @@
                     false /* checkProfiles */, getCompilerFilterForReason(REASON_INSTALL));
             Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
             if (result == PackageDexOptimizer.DEX_OPT_FAILED) {
-                String msg = "Extracking package failed for " + pkgName;
+                String msg = "Extracting package failed for " + pkgName;
                 res.setError(INSTALL_FAILED_DEXOPT, msg);
                 return;
             }
+
+            // Notify BackgroundDexOptService that the package has been changed.
+            // If this is an update of a package which used to fail to compile,
+            // BDOS will remove it from its blacklist.
+            BackgroundDexOptService.notifyPackageChanged(pkg.packageName);
         }
 
         if (!args.doRename(res.returnCode, pkg, oldCodePath)) {
@@ -17034,8 +17062,13 @@
         }
         PackageSetting pkgSetting;
         final int uid = Binder.getCallingUid();
-        final int permission = mContext.checkCallingOrSelfPermission(
-                android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
+        final int permission;
+        if (uid == Process.SYSTEM_UID) {
+            permission = PackageManager.PERMISSION_GRANTED;
+        } else {
+            permission = mContext.checkCallingOrSelfPermission(
+                    android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
+        }
         enforceCrossUserPermission(uid, userId,
                 false /* requireFullPermission */, true /* checkShell */, "set enabled");
         final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java
index 1076a7a..58559a5 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackage.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackage.java
@@ -17,6 +17,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UserIdInt;
 import android.content.ComponentName;
 import android.content.Intent;
 import android.content.pm.ShortcutInfo;
@@ -522,7 +523,7 @@
                         ret.getPackageInfo().loadFromXml(parser, fromBackup);
                         continue;
                     case TAG_SHORTCUT:
-                        final ShortcutInfo si = parseShortcut(parser, packageName);
+                        final ShortcutInfo si = parseShortcut(parser, packageName, ownerUserId);
 
                         // Don't use addShortcut(), we don't need to save the icon.
                         ret.mShortcuts.put(si.getId(), si);
@@ -534,8 +535,8 @@
         return ret;
     }
 
-    private static ShortcutInfo parseShortcut(XmlPullParser parser, String packageName)
-            throws IOException, XmlPullParserException {
+    private static ShortcutInfo parseShortcut(XmlPullParser parser, String packageName,
+            @UserIdInt int userId) throws IOException, XmlPullParserException {
         String id;
         ComponentName activityComponent;
         // Icon icon;
@@ -586,7 +587,7 @@
             throw ShortcutService.throwForInvalidTag(depth, tag);
         }
         return new ShortcutInfo(
-                id, packageName, activityComponent, /* icon =*/ null, title, text, intent,
+                userId, id, packageName, activityComponent, /* icon =*/ null, title, text, intent,
                 intentPersistableExtras, weight, extras, lastChangedTimestamp, flags,
                 iconRes, bitmapPath);
     }
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 5c1e7a8..c124255 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -968,7 +968,8 @@
                 return; // has no icon
             }
 
-            Bitmap bitmap = null;
+            Bitmap bitmap;
+            Bitmap bitmapToRecycle = null;
             try {
                 switch (icon.getType()) {
                     case Icon.TYPE_RESOURCE: {
@@ -979,7 +980,7 @@
                         return;
                     }
                     case Icon.TYPE_BITMAP: {
-                        bitmap = icon.getBitmap();
+                        bitmap = icon.getBitmap(); // Don't recycle in this case.
                         break;
                     }
                     case Icon.TYPE_URI: {
@@ -987,7 +988,8 @@
 
                         try (InputStream is = mContext.getContentResolver().openInputStream(uri)) {
 
-                            bitmap = BitmapFactory.decodeStream(is);
+                            bitmapToRecycle = BitmapFactory.decodeStream(is);
+                            bitmap = bitmapToRecycle;
 
                         } catch (IOException e) {
                             Slog.e(TAG, "Unable to load icon from " + uri);
@@ -1011,8 +1013,14 @@
                     try {
                         path = out.getFile();
 
-                        shrinkBitmap(bitmap, mMaxIconDimension)
-                                .compress(mIconPersistFormat, mIconPersistQuality, out);
+                        Bitmap shrunk = shrinkBitmap(bitmap, mMaxIconDimension);
+                        try {
+                            shrunk.compress(mIconPersistFormat, mIconPersistQuality, out);
+                        } finally {
+                            if (bitmap != shrunk) {
+                                shrunk.recycle();
+                            }
+                        }
 
                         shortcut.setBitmapPath(out.getFile().getAbsolutePath());
                         shortcut.addFlags(ShortcutInfo.FLAG_HAS_ICON_FILE);
@@ -1027,8 +1035,8 @@
                     }
                 }
             } finally {
-                if (bitmap != null) {
-                    bitmap.recycle();
+                if (bitmapToRecycle != null) {
+                    bitmapToRecycle.recycle();
                 }
                 // Once saved, we won't use the original icon information, so null it out.
                 shortcut.clearIcon();
@@ -1076,8 +1084,6 @@
 
         c.drawBitmap(in, /*src=*/ null, dst, /* paint =*/ null);
 
-        in.recycle();
-
         return scaledBitmap;
     }
 
@@ -1580,13 +1586,17 @@
         @Override
         public List<ShortcutInfo> getShortcuts(int launcherUserId,
                 @NonNull String callingPackage, long changedSince,
-                @Nullable String packageName, @Nullable ComponentName componentName,
+                @Nullable String packageName, @Nullable List<String> shortcutIds,
+                @Nullable ComponentName componentName,
                 int queryFlags, int userId) {
             final ArrayList<ShortcutInfo> ret = new ArrayList<>();
             final int cloneFlag =
                     ((queryFlags & ShortcutQuery.FLAG_GET_KEY_FIELDS_ONLY) == 0)
                             ? ShortcutInfo.CLONE_REMOVE_FOR_LAUNCHER
                             : ShortcutInfo.CLONE_REMOVE_NON_KEY_INFO;
+            if (packageName == null) {
+                shortcutIds = null; // LauncherAppsService already threw for it though.
+            }
 
             synchronized (mLock) {
                 getLauncherShortcutsLocked(callingPackage, userId, launcherUserId)
@@ -1594,14 +1604,14 @@
 
                 if (packageName != null) {
                     getShortcutsInnerLocked(launcherUserId,
-                            callingPackage, packageName, changedSince,
+                            callingPackage, packageName, shortcutIds, changedSince,
                             componentName, queryFlags, userId, ret, cloneFlag);
                 } else {
                     final ArrayMap<String, ShortcutPackage> packages =
                             getUserShortcutsLocked(userId).getAllPackages();
                     for (int i = packages.size() - 1; i >= 0; i--) {
                         getShortcutsInnerLocked(launcherUserId,
-                                callingPackage, packages.keyAt(i), changedSince,
+                                callingPackage, packages.keyAt(i), shortcutIds, changedSince,
                                 componentName, queryFlags, userId, ret, cloneFlag);
                     }
                 }
@@ -1610,14 +1620,20 @@
         }
 
         private void getShortcutsInnerLocked(int launcherUserId, @NonNull String callingPackage,
-                @Nullable String packageName,long changedSince,
+                @Nullable String packageName, @Nullable List<String> shortcutIds, long changedSince,
                 @Nullable ComponentName componentName, int queryFlags,
                 int userId, ArrayList<ShortcutInfo> ret, int cloneFlag) {
+            final ArraySet<String> ids = shortcutIds == null ? null
+                    : new ArraySet<>(shortcutIds);
+
             getPackageShortcutsLocked(packageName, userId).findAll(ShortcutService.this, ret,
                     (ShortcutInfo si) -> {
                         if (si.getLastChangedTimestamp() < changedSince) {
                             return false;
                         }
+                        if (ids != null && !ids.contains(si.getId())) {
+                            return false;
+                        }
                         if (componentName != null
                                 && !componentName.equals(si.getActivityComponent())) {
                             return false;
@@ -1633,27 +1649,6 @@
         }
 
         @Override
-        public List<ShortcutInfo> getShortcutInfo(int launcherUserId,
-                @NonNull String callingPackage,
-                @NonNull String packageName, @Nullable List<String> ids, int userId) {
-            // Calling permission must be checked by LauncherAppsImpl.
-            Preconditions.checkStringNotEmpty(packageName, "packageName");
-
-            final ArrayList<ShortcutInfo> ret = new ArrayList<>(ids.size());
-            final ArraySet<String> idSet = new ArraySet<>(ids);
-            synchronized (mLock) {
-                getLauncherShortcutsLocked(callingPackage, userId, launcherUserId)
-                        .attemptToRestoreIfNeededAndSave(ShortcutService.this);
-
-                getPackageShortcutsLocked(packageName, userId).findAll(
-                        ShortcutService.this, ret,
-                        (ShortcutInfo si) -> idSet.contains(si.getId()),
-                        ShortcutInfo.CLONE_REMOVE_FOR_LAUNCHER, callingPackage, launcherUserId);
-            }
-            return ret;
-        }
-
-        @Override
         public boolean isPinnedByCaller(int launcherUserId, @NonNull String callingPackage,
                 @NonNull String packageName, @NonNull String shortcutId, int userId) {
             Preconditions.checkStringNotEmpty(packageName, "packageName");
@@ -1733,17 +1728,18 @@
         }
 
         @Override
-        public int getShortcutIconResId(int launcherUserId,
-                @NonNull String callingPackage,
-                @NonNull ShortcutInfo shortcut, int userId) {
-            Preconditions.checkNotNull(shortcut, "shortcut");
+        public int getShortcutIconResId(int launcherUserId, @NonNull String callingPackage,
+                @NonNull String packageName, @NonNull String shortcutId, int userId) {
+            Preconditions.checkNotNull(callingPackage, "callingPackage");
+            Preconditions.checkNotNull(packageName, "packageName");
+            Preconditions.checkNotNull(shortcutId, "shortcutId");
 
             synchronized (mLock) {
                 getLauncherShortcutsLocked(callingPackage, userId, launcherUserId)
                         .attemptToRestoreIfNeededAndSave(ShortcutService.this);
 
                 final ShortcutInfo shortcutInfo = getPackageShortcutsLocked(
-                        shortcut.getPackageName(), userId).findShortcutById(shortcut.getId());
+                        packageName, userId).findShortcutById(shortcutId);
                 return (shortcutInfo != null && shortcutInfo.hasIconResource())
                         ? shortcutInfo.getIconResourceId() : 0;
             }
@@ -1751,16 +1747,18 @@
 
         @Override
         public ParcelFileDescriptor getShortcutIconFd(int launcherUserId,
-                @NonNull String callingPackage,
-                @NonNull ShortcutInfo shortcutIn, int userId) {
-            Preconditions.checkNotNull(shortcutIn, "shortcut");
+                @NonNull String callingPackage, @NonNull String packageName,
+                @NonNull String shortcutId, int userId) {
+            Preconditions.checkNotNull(callingPackage, "callingPackage");
+            Preconditions.checkNotNull(packageName, "packageName");
+            Preconditions.checkNotNull(shortcutId, "shortcutId");
 
             synchronized (mLock) {
                 getLauncherShortcutsLocked(callingPackage, userId, launcherUserId)
                         .attemptToRestoreIfNeededAndSave(ShortcutService.this);
 
                 final ShortcutInfo shortcutInfo = getPackageShortcutsLocked(
-                        shortcutIn.getPackageName(), userId).findShortcutById(shortcutIn.getId());
+                        packageName, userId).findShortcutById(shortcutId);
                 if (shortcutInfo == null || !shortcutInfo.hasIconFile()) {
                     return null;
                 }
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 60a0d62..60ea254 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -65,6 +65,7 @@
 import android.system.Os;
 import android.system.OsConstants;
 import android.util.AtomicFile;
+import android.util.IntArray;
 import android.util.Log;
 import android.util.Slog;
 import android.util.SparseArray;
@@ -483,13 +484,50 @@
         }
     }
 
+    @Override
+    public int[] getProfileIds(int userId, boolean enabledOnly) {
+        if (userId != UserHandle.getCallingUserId()) {
+            checkManageUsersPermission("getting profiles related to user " + userId);
+        }
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            synchronized (mUsersLock) {
+                return getProfileIdsLU(userId, enabledOnly).toArray();
+            }
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
     /** Assume permissions already checked and caller's identity cleared */
     private List<UserInfo> getProfilesLU(int userId, boolean enabledOnly, boolean fullInfo) {
+        IntArray profileIds = getProfileIdsLU(userId, enabledOnly);
+        ArrayList<UserInfo> users = new ArrayList<>(profileIds.size());
+        for (int i = 0; i < profileIds.size(); i++) {
+            int profileId = profileIds.get(i);
+            UserInfo userInfo = mUsers.get(profileId).info;
+            // If full info is not required - clear PII data to prevent 3P apps from reading it
+            if (!fullInfo) {
+                userInfo = new UserInfo(userInfo);
+                userInfo.name = null;
+                userInfo.iconPath = null;
+            } else {
+                userInfo = userWithName(userInfo);
+            }
+            users.add(userInfo);
+        }
+        return users;
+    }
+
+    /**
+     *  Assume permissions already checked and caller's identity cleared
+     */
+    private IntArray getProfileIdsLU(int userId, boolean enabledOnly) {
         UserInfo user = getUserInfoLU(userId);
-        ArrayList<UserInfo> users = new ArrayList<UserInfo>(mUsers.size());
+        IntArray result = new IntArray(mUsers.size());
         if (user == null) {
             // Probably a dying user
-            return users;
+            return result;
         }
         final int userSize = mUsers.size();
         for (int i = 0; i < userSize; i++) {
@@ -506,16 +544,9 @@
             if (profile.partial) {
                 continue;
             }
-            UserInfo userInfo = userWithName(profile);
-            // If full info is not required - clear PII data to prevent 3P apps from reading it
-            if (!fullInfo) {
-                userInfo = new UserInfo(userInfo);
-                userInfo.name = null;
-                userInfo.iconPath = null;
-            }
-            users.add(userInfo);
+            result.add(profile.id);
         }
-        return users;
+        return result;
     }
 
     @Override
diff --git a/services/core/java/com/android/server/vr/EnabledComponentsObserver.java b/services/core/java/com/android/server/vr/EnabledComponentsObserver.java
index eb926c1..30194bf 100644
--- a/services/core/java/com/android/server/vr/EnabledComponentsObserver.java
+++ b/services/core/java/com/android/server/vr/EnabledComponentsObserver.java
@@ -24,7 +24,6 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
-import android.content.pm.UserInfo;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.UserHandle;
@@ -213,18 +212,7 @@
         if (userManager == null) {
             return null;
         }
-        int currentUserId = ActivityManager.getCurrentUser();
-        List<UserInfo> profiles = userManager.getProfiles(currentUserId);
-        if (profiles == null) {
-            return null;
-        }
-        final int s = profiles.size();
-        int[] userIds = new int[s];
-        int ctr = 0;
-        for (UserInfo info : profiles) {
-            userIds[ctr++] = info.id;
-        }
-        return userIds;
+        return userManager.getProfileIdsWithDisabled(ActivityManager.getCurrentUser());
     }
 
     public static ArraySet<ComponentName> loadComponentNames(PackageManager pm, int userId,
diff --git a/services/core/java/com/android/server/webkit/SystemImpl.java b/services/core/java/com/android/server/webkit/SystemImpl.java
index 9486cfd..ed935ce 100644
--- a/services/core/java/com/android/server/webkit/SystemImpl.java
+++ b/services/core/java/com/android/server/webkit/SystemImpl.java
@@ -19,6 +19,7 @@
 import android.app.ActivityManagerNative;
 import android.app.AppGlobals;
 import android.content.Context;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageDeleteObserver;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
@@ -187,7 +188,8 @@
         enablePackageForAllUsers(context, packageName, false);
         try {
             PackageManager pm = AppGlobals.getInitialApplication().getPackageManager();
-            if (pm.getApplicationInfo(packageName, 0).isUpdatedSystemApp()) {
+            ApplicationInfo applicationInfo = pm.getApplicationInfo(packageName, 0);
+            if (applicationInfo != null && applicationInfo.isUpdatedSystemApp()) {
                 pm.deletePackage(packageName, new IPackageDeleteObserver.Stub() {
                         public void packageDeleted(String packageName, int returnCode) {
                             enablePackageForAllUsers(context, packageName, false);
@@ -214,8 +216,9 @@
                     enable ? PackageManager.COMPONENT_ENABLED_STATE_DEFAULT :
                     PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER, 0,
                     userId, null);
-        } catch (RemoteException e) {
-            Log.w(TAG, "Tried to disable " + packageName + " for user " + userId + ": " + e);
+        } catch (RemoteException | IllegalArgumentException e) {
+            Log.w(TAG, "Tried to " + (enable ? "enable " : "disable ") + packageName
+                    + " for user " + userId + ": " + e);
         }
     }
 
diff --git a/services/core/java/com/android/server/webkit/WebViewUpdateService.java b/services/core/java/com/android/server/webkit/WebViewUpdateService.java
index 1f6fb2a..bbb4951 100644
--- a/services/core/java/com/android/server/webkit/WebViewUpdateService.java
+++ b/services/core/java/com/android/server/webkit/WebViewUpdateService.java
@@ -242,7 +242,12 @@
                 throw new SecurityException(msg);
             }
 
-            WebViewUpdateService.this.mImpl.enableFallbackLogic(enable);
+            long callingId = Binder.clearCallingIdentity();
+            try {
+                WebViewUpdateService.this.mImpl.enableFallbackLogic(enable);
+            } finally {
+                Binder.restoreCallingIdentity(callingId);
+            }
         }
     }
 }
diff --git a/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java b/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java
index 32b195b..cd976e7 100644
--- a/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java
+++ b/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java
@@ -160,6 +160,8 @@
             isFallbackEnabled = isEnabledPackage(
                     mSystemInterface.getPackageInfoForProvider(fallbackProvider));
         } catch (NameNotFoundException e) {
+            // No fallback package installed -> early out.
+            return;
         }
 
         if (existsValidNonFallbackProvider
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index eae7838..6bc633f 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -670,7 +670,6 @@
         if (SHOW_TRANSACTIONS) Slog.i(
                 TAG, ">>> OPEN TRANSACTION animateLocked");
         SurfaceControl.openTransaction();
-        SurfaceControl.setAnimationTransaction();
         try {
             final int numDisplays = mDisplayContentsAnimators.size();
             for (int i = 0; i < numDisplays; i++) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 72eebb5..d229633 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -21,8 +21,6 @@
 import static android.app.admin.DevicePolicyManager.WIPE_EXTERNAL_STORAGE;
 import static android.app.admin.DevicePolicyManager.WIPE_RESET_PROTECTION_DATA;
 import static android.content.pm.PackageManager.GET_UNINSTALLED_PACKAGES;
-import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE;
-import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
 
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW;
 import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
@@ -57,7 +55,6 @@
 import android.app.backup.IBackupManager;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
-import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
@@ -85,7 +82,6 @@
 import android.os.AsyncTask;
 import android.os.Binder;
 import android.os.Build;
-import android.os.Build.VERSION_CODES;
 import android.os.Bundle;
 import android.os.Environment;
 import android.os.FileUtils;
@@ -2065,10 +2061,9 @@
      */
     private void sendAdminCommandToSelfAndProfilesLocked(String action, int reqPolicy,
             int userHandle) {
-        List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
-        for (UserInfo ui : profiles) {
-            int id = ui.id;
-            sendAdminCommandLocked(action, reqPolicy, id);
+        int[] profileIds = mUserManager.getProfileIdsWithDisabled(userHandle);
+        for (int profileId : profileIds) {
+            sendAdminCommandLocked(action, reqPolicy, profileId);
         }
     }
 
@@ -3968,9 +3963,9 @@
         // moment so we set the screen off timeout regardless of whether it affects the parent user
         // or the profile challenge only.
         long timeMs = Long.MAX_VALUE;
-        List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
-        for (UserInfo userInfo : profiles) {
-            DevicePolicyData policy = getUserDataUnchecked(userInfo.id);
+        int[] profileIds = mUserManager.getProfileIdsWithDisabled(userHandle);
+        for (int profileId : profileIds) {
+            DevicePolicyData policy = getUserDataUnchecked(profileId);
             final int N = policy.mAdminList.size();
             for (int i = 0; i < N; i++) {
                 ActiveAdmin admin = policy.mAdminList.get(i);
@@ -6708,19 +6703,18 @@
             // If we have multiple profiles we return the intersection of the
             // permitted lists. This can happen in cases where we have a device
             // and profile owner.
-            List<UserInfo> profiles = mUserManager.getProfiles(userId);
-            final int PROFILES_SIZE = profiles.size();
-            for (int i = 0; i < PROFILES_SIZE; ++i) {
+            int[] profileIds = mUserManager.getProfileIdsWithDisabled(userId);
+            for (int profileId : profileIds) {
                 // Just loop though all admins, only device or profiles
                 // owners can have permitted lists set.
-                DevicePolicyData policy = getUserDataUnchecked(profiles.get(i).id);
+                DevicePolicyData policy = getUserDataUnchecked(profileId);
                 final int N = policy.mAdminList.size();
                 for (int j = 0; j < N; j++) {
                     ActiveAdmin admin = policy.mAdminList.get(j);
                     List<String> fromAdmin = admin.permittedAccessiblityServices;
                     if (fromAdmin != null) {
                         if (result == null) {
-                            result = new ArrayList<String>(fromAdmin);
+                            result = new ArrayList<>(fromAdmin);
                         } else {
                             result.retainAll(fromAdmin);
                         }
@@ -6888,12 +6882,11 @@
             // If we have multiple profiles we return the intersection of the
             // permitted lists. This can happen in cases where we have a device
             // and profile owner.
-            List<UserInfo> profiles = mUserManager.getProfiles(userId);
-            final int PROFILES_SIZE = profiles.size();
-            for (int i = 0; i < PROFILES_SIZE; ++i) {
+            int[] profileIds = mUserManager.getProfileIdsWithDisabled(userId);
+            for (int profileId : profileIds) {
                 // Just loop though all admins, only device or profiles
                 // owners can have permitted lists set.
-                DevicePolicyData policy = getUserDataUnchecked(profiles.get(i).id);
+                DevicePolicyData policy = getUserDataUnchecked(profileId);
                 final int N = policy.mAdminList.size();
                 for (int j = 0; j < N; j++) {
                     ActiveAdmin admin = policy.mAdminList.get(j);
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
index 60d7382..f6e35f5 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
@@ -39,7 +39,6 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.os.UserManagerInternal;
-import android.os.storage.StorageManager;
 import android.telephony.TelephonyManager;
 import android.test.mock.MockContentResolver;
 import android.test.mock.MockContext;
@@ -343,31 +342,25 @@
                     @Override
                     public List<UserInfo> answer(InvocationOnMock invocation) throws Throwable {
                         final int userId = (int) invocation.getArguments()[0];
-                        final ArrayList<UserInfo> ret = new ArrayList<UserInfo>();
-                        UserInfo parent = null;
-                        for (UserInfo ui : mUserInfos) {
-                            if (ui.id == userId) {
-                                parent = ui;
-                                break;
-                            }
-                        }
-                        if (parent == null) {
-                            return ret;
-                        }
-                        ret.add(parent);
-                        for (UserInfo ui : mUserInfos) {
-                            if (ui.id == userId) {
-                                continue;
-                            }
-                            if (ui.profileGroupId != UserInfo.NO_PROFILE_GROUP_ID
-                                    && ui.profileGroupId == parent.profileGroupId) {
-                                ret.add(ui);
-                            }
-                        }
-                        return ret;
+                        return getProfiles(userId);
                     }
                 }
         );
+        when(userManager.getProfileIdsWithDisabled(anyInt())).thenAnswer(
+                new Answer<int[]>() {
+                    @Override
+                    public int[] answer(InvocationOnMock invocation) throws Throwable {
+                        final int userId = (int) invocation.getArguments()[0];
+                        List<UserInfo> profiles = getProfiles(userId);
+                        int[] results = new int[profiles.size()];
+                        for (int i = 0; i < results.length; i++) {
+                            results[i] = profiles.get(i).id;
+                        }
+                        return results;
+                    }
+                }
+        );
+
 
         // Create a data directory.
         final File dir = new File(dataDir, "user" + userId);
@@ -377,6 +370,31 @@
         return dir;
     }
 
+    private List<UserInfo> getProfiles(int userId) {
+        final ArrayList<UserInfo> ret = new ArrayList<UserInfo>();
+        UserInfo parent = null;
+        for (UserInfo ui : mUserInfos) {
+            if (ui.id == userId) {
+                parent = ui;
+                break;
+            }
+        }
+        if (parent == null) {
+            return ret;
+        }
+        ret.add(parent);
+        for (UserInfo ui : mUserInfos) {
+            if (ui.id == userId) {
+                continue;
+            }
+            if (ui.profileGroupId != UserInfo.NO_PROFILE_GROUP_ID
+                    && ui.profileGroupId == parent.profileGroupId) {
+                ret.add(ui);
+            }
+        }
+        return ret;
+    }
+
     /**
      * Add multiple users at once.  They'll all have flag 0.
      */
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java
index baa5d36..b08bd72 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java
@@ -172,6 +172,11 @@
         public String getPackageName() {
             return mInjectedClientPackage;
         }
+
+        @Override
+        public int getUserId() {
+            return getCallingUserId();
+        }
     }
 
     /** Context used in the service side */
@@ -190,6 +195,11 @@
         public void startActivityAsUser(@RequiresPermission Intent intent, @Nullable Bundle options,
                 UserHandle userId) {
         }
+
+        @Override
+        public int getUserId() {
+            return UserHandle.USER_SYSTEM;
+        }
     }
 
     /** ShortcutService with injection override methods. */
@@ -1152,9 +1162,25 @@
         return intentCaptor.getValue();
     }
 
+    private Intent launchShortcutAndGetIntent_withShortcutInfo(
+            @NonNull String packageName, @NonNull String shortcutId, int userId) {
+        reset(mServiceContext);
+
+        assertTrue(mLauncherApps.startShortcut(
+                getShortcutInfoAsLauncher(packageName, shortcutId, userId), null, null));
+
+        final ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
+        verify(mServiceContext).startActivityAsUser(
+                intentCaptor.capture(),
+                any(Bundle.class),
+                eq(UserHandle.of(userId)));
+        return intentCaptor.getValue();
+    }
+
     private void assertShortcutLaunchable(@NonNull String packageName, @NonNull String shortcutId,
             int userId) {
         assertNotNull(launchShortcutAndGetIntent(packageName, shortcutId, userId));
+        assertNotNull(launchShortcutAndGetIntent_withShortcutInfo(packageName, shortcutId, userId));
     }
 
     private void assertShortcutNotLaunchable(@NonNull String packageName,
@@ -1193,6 +1219,14 @@
         return getLauncherShortcuts(launcher, userId, ShortcutQuery.FLAG_GET_PINNED);
     }
 
+    private ShortcutInfo getShortcutInfoAsLauncher(String packageName, String shortcutId,
+            int userId) {
+        final List<ShortcutInfo> infoList =
+                mLauncherApps.getShortcutInfo(packageName, list(shortcutId),
+                        UserHandle.of(userId));
+        assertEquals("No shortcutInfo found (or too many of them)", 1, infoList.size());
+        return infoList.get(0);
+    }
 
     private Intent genPackageDeleteIntent(String pakcageName, int userId) {
         Intent i = new Intent(Intent.ACTION_PACKAGE_REMOVED);
@@ -1728,6 +1762,16 @@
                 "res64x64",
                 "none");
 
+        // Different profile.  Note the names and the contents don't match.
+        setCaller(CALLING_PACKAGE_1, USER_P0);
+        assertTrue(mManager.setDynamicShortcuts(list(
+                makeShortcutWithIcon("res32x32", res512x512),
+                makeShortcutWithIcon("bmp32x32", bmp512x512)
+        )));
+        assertShortcutIds(assertAllNotHaveIcon(mManager.getDynamicShortcuts()),
+                "res32x32",
+                "bmp32x32");
+
         // Re-initialize and load from the files.
         mService.saveDirtyInfo();
         initService();
@@ -1737,61 +1781,90 @@
 
         setCaller(LAUNCHER_1);
         // Check hasIconResource()/hasIconFile().
-        assertShortcutIds(assertAllHaveIconResId(mLauncherApps.getShortcutInfo(
-                CALLING_PACKAGE_1, list("res32x32"),
-                getCallingUser())), "res32x32");
+        assertShortcutIds(assertAllHaveIconResId(
+                list(getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "res32x32", USER_0))),
+                "res32x32");
 
-        assertShortcutIds(assertAllHaveIconResId(mLauncherApps.getShortcutInfo(
-                CALLING_PACKAGE_1, list("res64x64"), getCallingUser())),
+        assertShortcutIds(assertAllHaveIconResId(
+                list(getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "res64x64", USER_0))),
                 "res64x64");
 
-        assertShortcutIds(assertAllHaveIconFile(mLauncherApps.getShortcutInfo(
-                CALLING_PACKAGE_1, list("bmp32x32"), getCallingUser())),
+        assertShortcutIds(assertAllHaveIconFile(
+                list(getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "bmp32x32", USER_0))),
                 "bmp32x32");
 
-        assertShortcutIds(assertAllHaveIconFile(mLauncherApps.getShortcutInfo(
-                CALLING_PACKAGE_1, list("bmp64x64"), getCallingUser())),
+        assertShortcutIds(assertAllHaveIconFile(
+                list(getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "bmp64x64", USER_0))),
                 "bmp64x64");
 
-        assertShortcutIds(assertAllHaveIconFile(mLauncherApps.getShortcutInfo(
-                CALLING_PACKAGE_1, list("bmp512x512"), getCallingUser())),
+        assertShortcutIds(assertAllHaveIconFile(
+                list(getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "bmp512x512", USER_0))),
                 "bmp512x512");
 
+        assertShortcutIds(assertAllHaveIconResId(
+                list(getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "res32x32", USER_P0))),
+                "res32x32");
+        assertShortcutIds(assertAllHaveIconFile(
+                list(getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "bmp32x32", USER_P0))),
+                "bmp32x32");
+
         // Check
         assertEquals(
                 R.drawable.black_32x32,
                 mLauncherApps.getShortcutIconResId(
-                        makePackageShortcut(CALLING_PACKAGE_1, "res32x32"), getCallingUser()));
+                        getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "res32x32", USER_0)));
 
         assertEquals(
                 R.drawable.black_64x64,
                 mLauncherApps.getShortcutIconResId(
-
-                        makePackageShortcut(CALLING_PACKAGE_1, "res64x64"), getCallingUser()));
+                        getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "res64x64", USER_0)));
 
         assertEquals(
                 0, // because it's not a resource
                 mLauncherApps.getShortcutIconResId(
-                        makePackageShortcut(CALLING_PACKAGE_1, "bmp32x32"), getCallingUser()));
+                        getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "bmp32x32", USER_0)));
         assertEquals(
                 0, // because it's not a resource
                 mLauncherApps.getShortcutIconResId(
-                        makePackageShortcut(CALLING_PACKAGE_1, "bmp64x64"), getCallingUser()));
+                        getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "bmp64x64", USER_0)));
         assertEquals(
                 0, // because it's not a resource
                 mLauncherApps.getShortcutIconResId(
-                        makePackageShortcut(CALLING_PACKAGE_1, "bmp512x512"), getCallingUser()));
+                        getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "bmp512x512", USER_0)));
 
         bmp = pfdToBitmap(mLauncherApps.getShortcutIconFd(
-                makePackageShortcut(CALLING_PACKAGE_1, "bmp32x32"), getCallingUser()));
+                getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "bmp32x32", USER_0)));
         assertBitmapSize(32, 32, bmp);
 
         bmp = pfdToBitmap(mLauncherApps.getShortcutIconFd(
-                makePackageShortcut(CALLING_PACKAGE_1, "bmp64x64"), getCallingUser()));
+                getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "bmp64x64", USER_0)));
         assertBitmapSize(64, 64, bmp);
 
         bmp = pfdToBitmap(mLauncherApps.getShortcutIconFd(
-                makePackageShortcut(CALLING_PACKAGE_1, "bmp512x512"), getCallingUser()));
+                getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "bmp512x512", USER_0)));
+        assertBitmapSize(128, 128, bmp);
+
+        assertEquals(
+                R.drawable.black_512x512,
+                mLauncherApps.getShortcutIconResId(
+                        getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "res32x32", USER_P0)));
+        // Should be 512x512, so shrunk.
+        bmp = pfdToBitmap(mLauncherApps.getShortcutIconFd(
+                getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "bmp32x32", USER_P0)));
+        assertBitmapSize(128, 128, bmp);
+
+        // Also check the overload APIs too.
+        assertEquals(
+                R.drawable.black_32x32,
+                mLauncherApps.getShortcutIconResId(CALLING_PACKAGE_1, "res32x32", HANDLE_USER_0));
+        assertEquals(
+                R.drawable.black_64x64,
+                mLauncherApps.getShortcutIconResId(CALLING_PACKAGE_1, "res64x64", HANDLE_USER_0));
+        assertEquals(
+                R.drawable.black_512x512,
+                mLauncherApps.getShortcutIconResId(CALLING_PACKAGE_1, "res32x32", HANDLE_USER_P0));
+        bmp = pfdToBitmap(
+                mLauncherApps.getShortcutIconFd(CALLING_PACKAGE_1, "bmp32x32", HANDLE_USER_P0));
         assertBitmapSize(128, 128, bmp);
 
         // TODO Test the content URI case too.
@@ -2034,9 +2107,16 @@
     private static ShortcutQuery buildQuery(long changedSince,
             String packageName, ComponentName componentName,
             /* @ShortcutQuery.QueryFlags */ int flags) {
+        return buildQuery(changedSince, packageName, null, componentName, flags);
+    }
+
+    private static ShortcutQuery buildQuery(long changedSince,
+            String packageName, List<String> shortcutIds, ComponentName componentName,
+            /* @ShortcutQuery.QueryFlags */ int flags) {
         final ShortcutQuery q = new ShortcutQuery();
         q.setChangedSince(changedSince);
         q.setPackage(packageName);
+        q.setShortcutIds(shortcutIds);
         q.setActivity(componentName);
         q.setQueryFlags(flags);
         return q;
@@ -2110,6 +2190,36 @@
                         getCallingUser())),
                 "s2", "s3"))));
 
+        // With ID.
+        assertAllDynamic(assertAllNotHaveTitle(assertAllNotHaveIntents(assertShortcutIds(
+                assertAllKeyFieldsOnly(mLauncherApps.getShortcuts(buildQuery(
+                        /* time =*/ 1000, CALLING_PACKAGE_2, list("s3"),
+                        /* activity =*/ null,
+                        ShortcutQuery.FLAG_GET_DYNAMIC | ShortcutQuery.FLAG_GET_KEY_FIELDS_ONLY),
+                        getCallingUser())),
+                "s3"))));
+        assertAllDynamic(assertAllNotHaveTitle(assertAllNotHaveIntents(assertShortcutIds(
+                assertAllKeyFieldsOnly(mLauncherApps.getShortcuts(buildQuery(
+                        /* time =*/ 1000, CALLING_PACKAGE_2, list("s3", "s2", "ss"),
+                        /* activity =*/ null,
+                        ShortcutQuery.FLAG_GET_DYNAMIC | ShortcutQuery.FLAG_GET_KEY_FIELDS_ONLY),
+                        getCallingUser())),
+                "s2", "s3"))));
+        assertAllDynamic(assertAllNotHaveTitle(assertAllNotHaveIntents(assertShortcutIds(
+                assertAllKeyFieldsOnly(mLauncherApps.getShortcuts(buildQuery(
+                        /* time =*/ 1000, CALLING_PACKAGE_2, list("s3x", "s2x"),
+                        /* activity =*/ null,
+                        ShortcutQuery.FLAG_GET_DYNAMIC | ShortcutQuery.FLAG_GET_KEY_FIELDS_ONLY),
+                        getCallingUser()))
+                /* empty */))));
+        assertAllDynamic(assertAllNotHaveTitle(assertAllNotHaveIntents(assertShortcutIds(
+                assertAllKeyFieldsOnly(mLauncherApps.getShortcuts(buildQuery(
+                        /* time =*/ 1000, CALLING_PACKAGE_2, list(),
+                        /* activity =*/ null,
+                        ShortcutQuery.FLAG_GET_DYNAMIC | ShortcutQuery.FLAG_GET_KEY_FIELDS_ONLY),
+                        getCallingUser()))
+                /* empty */))));
+
         // Pin some shortcuts.
         mLauncherApps.pinShortcuts(CALLING_PACKAGE_2,
                 list("s3", "s4"), getCallingUser());
@@ -2132,6 +2242,13 @@
                         getCallingUser())),
                 "s1", "s3");
 
+        TestUtils.assertExpectException(
+                IllegalArgumentException.class, "package name must also be set", () -> {
+            mLauncherApps.getShortcuts(buildQuery(
+                    /* time =*/ 0, /* package= */ null, list("id"),
+                    /* activity =*/ null, /* flags */ 0), getCallingUser());
+        });
+
         // TODO More tests: pinned but dynamic, filter by activity
     }
 
@@ -5063,12 +5180,15 @@
     }
 
     public void testShortcutInfoParcel() {
-        ShortcutInfo si = parceled(new ShortcutInfo.Builder(getTestContext())
+        setCaller(CALLING_PACKAGE_1, USER_10);
+        ShortcutInfo si = parceled(new ShortcutInfo.Builder(mClientContext)
                 .setId("id")
                 .setTitle("title")
                 .setIntent(makeIntent("action", ShortcutActivity.class))
                 .build());
-        assertEquals(getTestContext().getPackageName(), si.getPackageName());
+        assertEquals(mClientContext.getPackageName(), si.getPackageName());
+        assertEquals(USER_10, si.getUserId());
+        assertEquals(HANDLE_USER_10, si.getUserHandle());
         assertEquals("id", si.getId());
         assertEquals("title", si.getTitle());
         assertEquals("action", si.getIntent().getAction());
@@ -5109,9 +5229,11 @@
     }
 
     public void testShortcutInfoClone() {
+        setCaller(CALLING_PACKAGE_1, USER_11);
+
         PersistableBundle pb = new PersistableBundle();
         pb.putInt("k", 1);
-        ShortcutInfo sorig = new ShortcutInfo.Builder(getTestContext())
+        ShortcutInfo sorig = new ShortcutInfo.Builder(mClientContext)
                 .setId("id")
                 .setActivityComponent(new ComponentName("a", "b"))
                 .setIcon(Icon.createWithContentUri("content://a.b.c/"))
@@ -5127,7 +5249,9 @@
 
         ShortcutInfo si = sorig.clone(/* clone flags*/ 0);
 
-        assertEquals(getTestContext().getPackageName(), si.getPackageName());
+        assertEquals(USER_11, si.getUserId());
+        assertEquals(HANDLE_USER_11, si.getUserHandle());
+        assertEquals(mClientContext.getPackageName(), si.getPackageName());
         assertEquals("id", si.getId());
         assertEquals(new ComponentName("a", "b"), si.getActivityComponent());
         assertEquals("content://a.b.c/", si.getIcon().getUriString());
@@ -5144,7 +5268,7 @@
 
         si = sorig.clone(ShortcutInfo.CLONE_REMOVE_FOR_CREATOR);
 
-        assertEquals(getTestContext().getPackageName(), si.getPackageName());
+        assertEquals(mClientContext.getPackageName(), si.getPackageName());
         assertEquals("id", si.getId());
         assertEquals(new ComponentName("a", "b"), si.getActivityComponent());
         assertEquals(null, si.getIcon());
@@ -5161,7 +5285,7 @@
 
         si = sorig.clone(ShortcutInfo.CLONE_REMOVE_FOR_LAUNCHER);
 
-        assertEquals(getTestContext().getPackageName(), si.getPackageName());
+        assertEquals(mClientContext.getPackageName(), si.getPackageName());
         assertEquals("id", si.getId());
         assertEquals(new ComponentName("a", "b"), si.getActivityComponent());
         assertEquals(null, si.getIcon());
@@ -5177,7 +5301,7 @@
 
         si = sorig.clone(ShortcutInfo.CLONE_REMOVE_NON_KEY_INFO);
 
-        assertEquals(getTestContext().getPackageName(), si.getPackageName());
+        assertEquals(mClientContext.getPackageName(), si.getPackageName());
         assertEquals("id", si.getId());
         assertEquals(null, si.getActivityComponent());
         assertEquals(null, si.getIcon());
@@ -5267,7 +5391,7 @@
     }
 
     public void testShortcutInfoSaveAndLoad() throws InterruptedException {
-        setCaller(CALLING_PACKAGE_1, USER_0);
+        setCaller(CALLING_PACKAGE_1, USER_10);
 
         final Icon bmp32x32 = Icon.createWithBitmap(BitmapFactory.decodeResource(
                 getTestContext().getResources(), R.drawable.black_32x32));
@@ -5293,11 +5417,13 @@
         // Save and load.
         mService.saveDirtyInfo();
         initService();
-        mService.handleUnlockUser(USER_0);
+        mService.handleUnlockUser(USER_10);
 
         ShortcutInfo si;
-        si = mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "id", USER_0);
+        si = mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "id", USER_10);
 
+        assertEquals(USER_10, si.getUserId());
+        assertEquals(HANDLE_USER_10, si.getUserHandle());
         assertEquals(CALLING_PACKAGE_1, si.getPackageName());
         assertEquals("id", si.getId());
         assertEquals(ShortcutActivity2.class.getName(), si.getActivityComponent().getClassName());
diff --git a/telephony/java/com/android/internal/telephony/CarrierAppUtils.java b/telephony/java/com/android/internal/telephony/CarrierAppUtils.java
new file mode 100644
index 0000000..ca7354f
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/CarrierAppUtils.java
@@ -0,0 +1,234 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.internal.telephony;
+
+import android.annotation.Nullable;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.IPackageManager;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.os.RemoteException;
+import android.telephony.TelephonyManager;
+import android.util.Slog;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Utilities for handling carrier applications.
+ * @hide
+ */
+public final class CarrierAppUtils {
+    private static final String TAG = "CarrierAppUtils";
+
+    private static final boolean DEBUG = false; // STOPSHIP if true
+
+    private CarrierAppUtils() {}
+
+    /**
+     * Handle preinstalled carrier apps which should be disabled until a matching SIM is inserted.
+     *
+     * Evaluates the list of applications in config_disabledUntilUsedPreinstalledCarrierApps. We
+     * want to disable each such application which is present on the system image until the user
+     * inserts a SIM which causes that application to gain carrier privilege (indicating a "match"),
+     * without interfering with the user if they opt to enable/disable the app explicitly.
+     *
+     * So, for each such app, we either disable until used IFF the app is not carrier privileged AND
+     * in the default state (e.g. not explicitly DISABLED/DISABLED_BY_USER/ENABLED), or we enable if
+     * the app is carrier privileged and in either the default state or DISABLED_UNTIL_USED.
+     *
+     * When enabling a carrier app we also grant it default permissions.
+     *
+     * This method is idempotent and is safe to be called at any time; it should be called once at
+     * system startup prior to any application running, as well as any time the set of carrier
+     * privileged apps may have changed.
+     */
+    public synchronized static void disableCarrierAppsUntilPrivileged(String callingPackage,
+            IPackageManager packageManager, TelephonyManager telephonyManager, int userId) {
+        if (DEBUG) {
+            Slog.d(TAG, "disableCarrierAppsUntilPrivileged");
+        }
+        String[] systemCarrierAppsDisabledUntilUsed = Resources.getSystem().getStringArray(
+                com.android.internal.R.array.config_disabledUntilUsedPreinstalledCarrierApps);
+        disableCarrierAppsUntilPrivileged(callingPackage, packageManager, telephonyManager, userId,
+                systemCarrierAppsDisabledUntilUsed);
+    }
+
+    /**
+     * Like {@link #disableCarrierAppsUntilPrivileged(String, IPackageManager, TelephonyManager,
+     * int)}, but assumes that no carrier apps have carrier privileges.
+     *
+     * This prevents a potential race condition on first boot - since the app's default state is
+     * enabled, we will initially disable it when the telephony stack is first initialized as it has
+     * not yet read the carrier privilege rules. However, since telephony is initialized later on
+     * late in boot, the app being disabled may have already been started in response to certain
+     * broadcasts. The app will continue to run (briefly) after being disabled, before the Package
+     * Manager can kill it, and this can lead to crashes as the app is in an unexpected state.
+     */
+    public synchronized static void disableCarrierAppsUntilPrivileged(String callingPackage,
+            IPackageManager packageManager, int userId) {
+        if (DEBUG) {
+            Slog.d(TAG, "disableCarrierAppsUntilPrivileged");
+        }
+        String[] systemCarrierAppsDisabledUntilUsed = Resources.getSystem().getStringArray(
+                com.android.internal.R.array.config_disabledUntilUsedPreinstalledCarrierApps);
+        disableCarrierAppsUntilPrivileged(callingPackage, packageManager,
+                null /* telephonyManager */, userId, systemCarrierAppsDisabledUntilUsed);
+    }
+
+    // Must be public b/c framework unit tests can't access package-private methods.
+    @VisibleForTesting
+    public static void disableCarrierAppsUntilPrivileged(String callingPackage,
+            IPackageManager packageManager, @Nullable TelephonyManager telephonyManager, int userId,
+            String[] systemCarrierAppsDisabledUntilUsed) {
+        List<ApplicationInfo> candidates = getDefaultCarrierAppCandidatesHelper(packageManager,
+                userId, systemCarrierAppsDisabledUntilUsed);
+        if (candidates == null || candidates.isEmpty()) {
+            return;
+        }
+
+        List<String> enabledCarrierPackages = new ArrayList<>();
+
+        try {
+            for (ApplicationInfo ai : candidates) {
+                String packageName = ai.packageName;
+                boolean hasPrivileges = telephonyManager != null &&
+                        telephonyManager.checkCarrierPrivilegesForPackageAnyPhone(packageName) ==
+                                TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
+
+                // Only update enabled state for the app on /system. Once it has been updated we
+                // shouldn't touch it.
+                if (!ai.isUpdatedSystemApp()) {
+                    if (hasPrivileges
+                            && (ai.enabledSetting == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT
+                            || ai.enabledSetting ==
+                            PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED)) {
+                        Slog.i(TAG, "Update state(" + packageName + "): ENABLED for user "
+                                + userId);
+                        packageManager.setApplicationEnabledSetting(packageName,
+                                PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
+                                PackageManager.DONT_KILL_APP, userId, callingPackage);
+                    } else if (!hasPrivileges
+                            && ai.enabledSetting ==
+                            PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) {
+                        Slog.i(TAG, "Update state(" + packageName
+                                + "): DISABLED_UNTIL_USED for user " + userId);
+                        packageManager.setApplicationEnabledSetting(packageName,
+                                PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED, 0,
+                                userId, callingPackage);
+                    }
+                }
+
+                // Always re-grant default permissions to carrier apps w/ privileges.
+                if (hasPrivileges) {
+                    enabledCarrierPackages.add(ai.packageName);
+                }
+            }
+
+            if (!enabledCarrierPackages.isEmpty()) {
+                // Since we enabled at least one app, ensure we grant default permissions to those
+                // apps.
+                String[] packageNames = new String[enabledCarrierPackages.size()];
+                enabledCarrierPackages.toArray(packageNames);
+                packageManager.grantDefaultPermissionsToEnabledCarrierApps(packageNames, userId);
+            }
+        } catch (RemoteException e) {
+            Slog.w(TAG, "Could not reach PackageManager", e);
+        }
+    }
+
+    /**
+     * Returns the list of "default" carrier apps.
+     *
+     * This is the subset of apps returned by
+     * {@link #getDefaultCarrierAppCandidates(IPackageManager, int)} which currently have carrier
+     * privileges per the SIM(s) inserted in the device.
+     */
+    public static List<ApplicationInfo> getDefaultCarrierApps(IPackageManager packageManager,
+            TelephonyManager telephonyManager, int userId) {
+        // Get all system apps from the default list.
+        List<ApplicationInfo> candidates = getDefaultCarrierAppCandidates(packageManager, userId);
+        if (candidates == null || candidates.isEmpty()) {
+            return null;
+        }
+
+        // Filter out apps without carrier privileges.
+        // Iterate from the end to avoid creating an Iterator object and because we will be removing
+        // elements from the list as we pass through it.
+        for (int i = candidates.size() - 1; i >= 0; i--) {
+            ApplicationInfo ai = candidates.get(i);
+            String packageName = ai.packageName;
+            boolean hasPrivileges =
+                    telephonyManager.checkCarrierPrivilegesForPackageAnyPhone(packageName) ==
+                            TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
+            if (!hasPrivileges) {
+                candidates.remove(i);
+            }
+        }
+
+        return candidates;
+    }
+
+    /**
+     * Returns the list of "default" carrier app candidates.
+     *
+     * These are the apps subject to the hiding/showing logic in
+     * {@link CarrierAppUtils#disableCarrierAppsUntilPrivileged(String, IPackageManager,
+     * TelephonyManager, int)}, as well as the apps which should have default permissions granted,
+     * when a matching SIM is inserted.
+     *
+     * Whether or not the app is actually considered a default app depends on whether the app has
+     * carrier privileges as determined by the SIMs in the device.
+     */
+    public static List<ApplicationInfo> getDefaultCarrierAppCandidates(
+            IPackageManager packageManager, int userId) {
+        String[] systemCarrierAppsDisabledUntilUsed = Resources.getSystem().getStringArray(
+                com.android.internal.R.array.config_disabledUntilUsedPreinstalledCarrierApps);
+        return getDefaultCarrierAppCandidatesHelper(packageManager, userId,
+                systemCarrierAppsDisabledUntilUsed);
+    }
+
+    private static List<ApplicationInfo> getDefaultCarrierAppCandidatesHelper(
+            IPackageManager packageManager, int userId,
+            String[] systemCarrierAppsDisabledUntilUsed) {
+        if (systemCarrierAppsDisabledUntilUsed == null
+                || systemCarrierAppsDisabledUntilUsed.length == 0) {
+            return null;
+        }
+        List<ApplicationInfo> apps = null;
+        try {
+            apps = new ArrayList<>(systemCarrierAppsDisabledUntilUsed.length);
+            for (String packageName : systemCarrierAppsDisabledUntilUsed) {
+                ApplicationInfo ai = packageManager.getApplicationInfo(packageName,
+                        PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS, userId);
+                if (ai == null) {
+                    // No app found for packageName
+                    continue;
+                }
+                if (!ai.isSystemApp()) {
+                    continue;
+                }
+                apps.add(ai);
+            }
+        } catch (RemoteException e) {
+            Slog.w(TAG, "Could not reach PackageManager", e);
+        }
+        return apps;
+    }
+}