Merge "Update FloatingToolbar overflow button." into nyc-dev
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 269089e..7a18df6 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -1093,6 +1093,7 @@
      * returned.
      */
     public List<ComponentName> getActiveAdmins() {
+        throwIfParentInstance("getActiveAdmins");
         return getActiveAdminsAsUser(myUserId());
     }
 
@@ -1149,6 +1150,7 @@
      * @throws SecurityException if the caller is not in the owner application of {@code admin}.
      */
     public void removeActiveAdmin(@NonNull ComponentName admin) {
+        throwIfParentInstance("removeActiveAdmin");
         if (mService != null) {
             try {
                 mService.removeActiveAdmin(admin, myUserId());
@@ -1169,6 +1171,7 @@
      * @throws SecurityException if {@code admin} is not an active administrator.
      */
     public boolean hasGrantedPolicy(@NonNull ComponentName admin, int usesPolicy) {
+        throwIfParentInstance("hasGrantedPolicy");
         if (mService != null) {
             try {
                 return mService.hasGrantedPolicy(admin, usesPolicy, myUserId());
@@ -2216,9 +2219,7 @@
      *             that uses {@link DeviceAdminInfo#USES_POLICY_RESET_PASSWORD}
      */
     public boolean resetPassword(String password, int flags) {
-        if (mParentInstance) {
-            throw new SecurityException("Reset password does not work across profiles.");
-        }
+        throwIfParentInstance("resetPassword");
         if (mService != null) {
             try {
                 return mService.resetPassword(password, flags);
@@ -2355,6 +2356,7 @@
      *             that uses {@link DeviceAdminInfo#USES_POLICY_WIPE_DATA}
      */
     public void wipeData(int flags) {
+        throwIfParentInstance("wipeData");
         if (mService != null) {
             try {
                 mService.wipeData(flags);
@@ -2388,6 +2390,7 @@
      */
     public ComponentName setGlobalProxy(@NonNull ComponentName admin, Proxy proxySpec,
             List<String> exclusionList ) {
+        throwIfParentInstance("setGlobalProxy");
         if (proxySpec == null) {
             throw new NullPointerException();
         }
@@ -2453,6 +2456,7 @@
      */
     public void setRecommendedGlobalProxy(@NonNull ComponentName admin, @Nullable ProxyInfo
             proxyInfo) {
+        throwIfParentInstance("setRecommendedGlobalProxy");
         if (mService != null) {
             try {
                 mService.setRecommendedGlobalProxy(admin, proxyInfo);
@@ -2603,6 +2607,7 @@
      *             {@link DeviceAdminInfo#USES_ENCRYPTED_STORAGE}
      */
     public int setStorageEncryption(@NonNull ComponentName admin, boolean encrypt) {
+        throwIfParentInstance("setStorageEncryption");
         if (mService != null) {
             try {
                 return mService.setStorageEncryption(admin, encrypt);
@@ -2623,6 +2628,7 @@
      * @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());
@@ -2653,6 +2659,7 @@
      * or {@link #ENCRYPTION_STATUS_ACTIVE}.
      */
     public int getStorageEncryptionStatus() {
+        throwIfParentInstance("getStorageEncryptionStatus");
         return getStorageEncryptionStatus(myUserId());
     }
 
@@ -2718,6 +2725,7 @@
      *         owner.
      */
     public boolean installCaCert(@Nullable ComponentName admin, byte[] certBuffer) {
+        throwIfParentInstance("installCaCert");
         if (mService != null) {
             try {
                 return mService.installCaCert(admin, certBuffer);
@@ -2738,6 +2746,7 @@
      *         owner.
      */
     public void uninstallCaCert(@Nullable ComponentName admin, byte[] certBuffer) {
+        throwIfParentInstance("uninstallCaCert");
         if (mService != null) {
             try {
                 final String alias = getCaCertAlias(certBuffer);
@@ -2763,6 +2772,7 @@
      */
     public List<byte[]> getInstalledCaCerts(@Nullable ComponentName admin) {
         List<byte[]> certs = new ArrayList<byte[]>();
+        throwIfParentInstance("getInstalledCaCerts");
         if (mService != null) {
             try {
                 mService.enforceCanManageCaCerts(admin);
@@ -2791,6 +2801,7 @@
      *         owner.
      */
     public void uninstallAllUserCaCerts(@Nullable ComponentName admin) {
+        throwIfParentInstance("uninstallAllUserCaCerts");
         if (mService != null) {
             try {
                 mService.uninstallCaCerts(admin, new TrustedCertificateStore().userAliases()
@@ -2811,6 +2822,7 @@
      *         owner.
      */
     public boolean hasCaCertInstalled(@Nullable ComponentName admin, byte[] certBuffer) {
+        throwIfParentInstance("hasCaCertInstalled");
         if (mService != null) {
             try {
                 mService.enforceCanManageCaCerts(admin);
@@ -2879,6 +2891,7 @@
      */
     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;
@@ -2911,6 +2924,7 @@
      *         owner.
      */
     public boolean removeKeyPair(@Nullable ComponentName admin, @NonNull String alias) {
+        throwIfParentInstance("removeKeyPair");
         try {
             return mService.removeKeyPair(admin, alias);
         } catch (RemoteException e) {
@@ -2951,6 +2965,7 @@
      */
     public void setCertInstallerPackage(@NonNull ComponentName admin, @Nullable String
             installerPackage) throws SecurityException {
+        throwIfParentInstance("setCertInstallerPackage");
         if (mService != null) {
             try {
                 mService.setCertInstallerPackage(admin, installerPackage);
@@ -2970,6 +2985,7 @@
      * @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);
@@ -3000,6 +3016,7 @@
      */
     public void setAlwaysOnVpnPackage(@NonNull ComponentName admin, @Nullable String vpnPackage)
             throws NameNotFoundException, UnsupportedOperationException {
+        throwIfParentInstance("setAlwaysOnVpnPackage");
         if (mService != null) {
             try {
                 if (!mService.setAlwaysOnVpnPackage(admin, vpnPackage)) {
@@ -3021,6 +3038,7 @@
      * @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);
@@ -3048,6 +3066,7 @@
      *             {@link DeviceAdminInfo#USES_POLICY_DISABLE_CAMERA}.
      */
     public void setCameraDisabled(@NonNull ComponentName admin, boolean disabled) {
+        throwIfParentInstance("setCameraDisabled");
         if (mService != null) {
             try {
                 mService.setCameraDisabled(admin, disabled);
@@ -3064,6 +3083,7 @@
      * have disabled the camera
      */
     public boolean getCameraDisabled(@Nullable ComponentName admin) {
+        throwIfParentInstance("getCameraDisabled");
         return getCameraDisabled(admin, myUserId());
     }
 
@@ -3093,6 +3113,7 @@
      *             than the one managed by the device owner.
      */
     public boolean requestBugreport(@NonNull ComponentName admin) {
+        throwIfParentInstance("requestBugreport");
         if (mService != null) {
             try {
                 return mService.requestBugreport(admin);
@@ -3131,6 +3152,7 @@
      * @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);
@@ -3147,6 +3169,7 @@
      * have disabled screen capture.
      */
     public boolean getScreenCaptureDisabled(@Nullable ComponentName admin) {
+        throwIfParentInstance("getScreenCaptureDisabled");
         return getScreenCaptureDisabled(admin, myUserId());
     }
 
@@ -3176,6 +3199,7 @@
      * @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);
@@ -3189,6 +3213,7 @@
      * @return true if auto time is required.
      */
     public boolean getAutoTimeRequired() {
+        throwIfParentInstance("getAutoTimeRequired");
         if (mService != null) {
             try {
                 return mService.getAutoTimeRequired();
@@ -3215,6 +3240,7 @@
      */
     public void setForceEphemeralUsers(
             @NonNull ComponentName admin, boolean forceEphemeralUsers) {
+        throwIfParentInstance("setForceEphemeralUsers");
         if (mService != null) {
             try {
                 mService.setForceEphemeralUsers(admin, forceEphemeralUsers);
@@ -3230,6 +3256,7 @@
      * @hide
      */
     public boolean getForceEphemeralUsers(@NonNull ComponentName admin) {
+        throwIfParentInstance("getForceEphemeralUsers");
         if (mService != null) {
             try {
                 return mService.getForceEphemeralUsers(admin);
@@ -3517,6 +3544,7 @@
      * @return whether or not the package is registered as the device owner app.
      */
     public boolean isDeviceOwnerApp(String packageName) {
+        throwIfParentInstance("isDeviceOwnerApp");
         return isDeviceOwnerAppOnCallingUser(packageName);
     }
 
@@ -3614,6 +3642,7 @@
      *             does not own the current device owner component.
      */
     public void clearDeviceOwnerApp(String packageName) {
+        throwIfParentInstance("clearDeviceOwnerApp");
         if (mService != null) {
             try {
                 mService.clearDeviceOwner(packageName);
@@ -3632,6 +3661,7 @@
      */
     @SystemApi
     public String getDeviceOwner() {
+        throwIfParentInstance("getDeviceOwner");
         final ComponentName name = getDeviceOwnerComponentOnCallingUser();
         return name != null ? name.getPackageName() : null;
     }
@@ -3657,6 +3687,7 @@
      */
     @SystemApi
     public String getDeviceOwnerNameOnAnyUser() {
+        throwIfParentInstance("getDeviceOwnerNameOnAnyUser");
         if (mService != null) {
             try {
                 return mService.getDeviceOwnerName();
@@ -3708,6 +3739,7 @@
     @SystemApi
     public boolean setActiveProfileOwner(@NonNull ComponentName admin, @Deprecated String ownerName)
             throws IllegalArgumentException {
+        throwIfParentInstance("setActiveProfileOwner");
         if (mService != null) {
             try {
                 final int myUserId = myUserId();
@@ -3731,6 +3763,7 @@
      * @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);
@@ -3804,6 +3837,7 @@
      * @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);
@@ -3817,6 +3851,7 @@
      * @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();
@@ -3848,6 +3883,7 @@
      */
     public String[] setPackagesSuspended(@NonNull ComponentName admin, String[] packageNames,
             boolean suspended) {
+        throwIfParentInstance("setPackagesSuspended");
         if (mService != null) {
             try {
                 return mService.setPackagesSuspended(admin, packageNames, suspended);
@@ -3870,6 +3906,7 @@
      */
     public boolean isPackageSuspended(@NonNull ComponentName admin, String packageName)
             throws NameNotFoundException {
+        throwIfParentInstance("isPackageSuspended");
         if (mService != null) {
             try {
                 return mService.isPackageSuspended(admin, packageName);
@@ -3891,6 +3928,7 @@
      * @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);
@@ -3912,6 +3950,7 @@
      * @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);
@@ -3930,6 +3969,7 @@
      * @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());
@@ -3950,6 +3990,7 @@
      */
     @SystemApi
     public ComponentName getProfileOwner() throws IllegalArgumentException {
+        throwIfParentInstance("getProfileOwner");
         return getProfileOwnerAsUser(Process.myUserHandle().getIdentifier());
     }
 
@@ -3994,6 +4035,7 @@
      */
     @SystemApi
     public String getProfileOwnerNameAsUser(int userId) throws IllegalArgumentException {
+        throwIfParentInstance("getProfileOwnerNameAsUser");
         if (mService != null) {
             try {
                 return mService.getProfileOwnerName(userId);
@@ -4024,6 +4066,7 @@
      */
     public void addPersistentPreferredActivity(@NonNull ComponentName admin, IntentFilter filter,
             @NonNull ComponentName activity) {
+        throwIfParentInstance("addPersistentPreferredActivity");
         if (mService != null) {
             try {
                 mService.addPersistentPreferredActivity(admin, filter, activity);
@@ -4046,6 +4089,7 @@
      */
     public void clearPackagePersistentPreferredActivities(@NonNull ComponentName admin,
             String packageName) {
+        throwIfParentInstance("clearPackagePersistentPreferredActivities");
         if (mService != null) {
             try {
                 mService.clearPackagePersistentPreferredActivities(admin, packageName);
@@ -4074,6 +4118,7 @@
      */
     public void setApplicationRestrictionsManagingPackage(@NonNull ComponentName admin,
             @Nullable String packageName) throws NameNotFoundException {
+        throwIfParentInstance("setApplicationRestrictionsManagingPackage");
         if (mService != null) {
             try {
                 if (!mService.setApplicationRestrictionsManagingPackage(admin, packageName)) {
@@ -4095,6 +4140,7 @@
      * @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);
@@ -4114,6 +4160,7 @@
      * that method.
      */
     public boolean isCallerApplicationRestrictionsManagingPackage() {
+        throwIfParentInstance("isCallerApplicationRestrictionsManagingPackage");
         if (mService != null) {
             try {
                 return mService.isCallerApplicationRestrictionsManagingPackage();
@@ -4159,6 +4206,7 @@
      */
     public void setApplicationRestrictions(@Nullable ComponentName admin, String packageName,
             Bundle settings) {
+        throwIfParentInstance("setApplicationRestrictions");
         if (mService != null) {
             try {
                 mService.setApplicationRestrictions(admin, packageName, settings);
@@ -4257,6 +4305,7 @@
      * @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);
@@ -4277,6 +4326,7 @@
      * @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);
@@ -4317,6 +4367,7 @@
      */
     public void setCrossProfileContactsSearchDisabled(@NonNull ComponentName admin,
             boolean disabled) {
+        throwIfParentInstance("setCrossProfileContactsSearchDisabled");
         if (mService != null) {
             try {
                 mService.setCrossProfileContactsSearchDisabled(admin, disabled);
@@ -4337,6 +4388,7 @@
      * @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);
@@ -4407,6 +4459,7 @@
      * @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);
@@ -4429,6 +4482,7 @@
      * @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);
@@ -4472,6 +4526,7 @@
      * @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);
@@ -4490,6 +4545,7 @@
      * @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);
@@ -4519,6 +4575,7 @@
      */
     public boolean setPermittedAccessibilityServices(@NonNull ComponentName admin,
             List<String> packageNames) {
+        throwIfParentInstance("setPermittedAccessibilityServices");
         if (mService != null) {
             try {
                 return mService.setPermittedAccessibilityServices(admin, packageNames);
@@ -4540,6 +4597,7 @@
      * @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);
@@ -4587,6 +4645,7 @@
      */
      @SystemApi
      public List<String> getPermittedAccessibilityServices(int userId) {
+        throwIfParentInstance("getPermittedAccessibilityServices");
         if (mService != null) {
             try {
                 return mService.getPermittedAccessibilityServicesForUser(userId);
@@ -4617,6 +4676,7 @@
      * @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);
@@ -4639,6 +4699,7 @@
      * @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);
@@ -4684,6 +4745,7 @@
      */
     @SystemApi
     public List<String> getPermittedInputMethodsForCurrentUser() {
+        throwIfParentInstance("getPermittedInputMethodsForCurrentUser");
         if (mService != null) {
             try {
                 return mService.getPermittedInputMethodsForCurrentUser();
@@ -4704,6 +4766,7 @@
      * @hide
      */
     public List<String> getKeepUninstalledPackages(@NonNull ComponentName admin) {
+        throwIfParentInstance("getKeepUninstalledPackages");
         if (mService != null) {
             try {
                 return mService.getKeepUninstalledPackages(admin);
@@ -4728,6 +4791,7 @@
      */
     public void setKeepUninstalledPackages(@NonNull ComponentName admin,
             @NonNull List<String> packageNames) {
+        throwIfParentInstance("setKeepUninstalledPackages");
         if (mService != null) {
             try {
                 mService.setKeepUninstalledPackages(admin, packageNames);
@@ -4834,6 +4898,7 @@
     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) {
@@ -4851,6 +4916,7 @@
      * @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) {
@@ -4868,6 +4934,7 @@
      * @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) {
@@ -4893,6 +4960,7 @@
      * @see {@link #setApplicationRestrictionsManagingPackage}
      */
     public Bundle getApplicationRestrictions(@Nullable ComponentName admin, String packageName) {
+        throwIfParentInstance("getApplicationRestrictions");
         if (mService != null) {
             try {
                 return mService.getApplicationRestrictions(admin, packageName);
@@ -4915,6 +4983,7 @@
      * @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);
@@ -4936,6 +5005,7 @@
      * @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);
@@ -4957,6 +5027,7 @@
      * @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 {
@@ -5001,6 +5072,7 @@
      */
     public boolean setApplicationHidden(@NonNull ComponentName admin, String packageName,
             boolean hidden) {
+        throwIfParentInstance("setApplicationHidden");
         if (mService != null) {
             try {
                 return mService.setApplicationHidden(admin, packageName, hidden);
@@ -5020,6 +5092,7 @@
      * @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);
@@ -5039,6 +5112,7 @@
      * @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);
@@ -5059,6 +5133,7 @@
      * @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);
@@ -5091,6 +5166,7 @@
      */
     public void setAccountManagementDisabled(@NonNull ComponentName admin, String accountType,
             boolean disabled) {
+        throwIfParentInstance("setAccountManagementDisabled");
         if (mService != null) {
             try {
                 mService.setAccountManagementDisabled(admin, accountType, disabled);
@@ -5111,6 +5187,7 @@
      * @see #setAccountManagementDisabled
      */
     public String[] getAccountTypesWithManagementDisabled() {
+        throwIfParentInstance("getAccountTypesWithManagementDisabled");
         return getAccountTypesWithManagementDisabledAsUser(myUserId());
     }
 
@@ -5148,6 +5225,7 @@
      */
     public void setLockTaskPackages(@NonNull ComponentName admin, String[] packages)
             throws SecurityException {
+        throwIfParentInstance("setLockTaskPackages");
         if (mService != null) {
             try {
                 mService.setLockTaskPackages(admin, packages);
@@ -5164,6 +5242,7 @@
      * @hide
      */
     public String[] getLockTaskPackages(@NonNull ComponentName admin) {
+        throwIfParentInstance("getLockTaskPackages");
         if (mService != null) {
             try {
                 return mService.getLockTaskPackages(admin);
@@ -5180,6 +5259,7 @@
      * @param pkg The package to check
      */
     public boolean isLockTaskPermitted(String pkg) {
+        throwIfParentInstance("isLockTaskPermitted");
         if (mService != null) {
             try {
                 return mService.isLockTaskPermitted(pkg);
@@ -5228,6 +5308,7 @@
      * @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);
@@ -5260,6 +5341,7 @@
      * @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);
@@ -5283,6 +5365,7 @@
      */
     public void setRestrictionsProvider(@NonNull ComponentName admin,
             @Nullable ComponentName provider) {
+        throwIfParentInstance("setRestrictionsProvider");
         if (mService != null) {
             try {
                 mService.setRestrictionsProvider(admin, provider);
@@ -5300,6 +5383,7 @@
      * @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);
@@ -5317,6 +5401,7 @@
      * @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);
@@ -5337,6 +5422,7 @@
      */
     public void setUninstallBlocked(@NonNull ComponentName admin, String packageName,
             boolean uninstallBlocked) {
+        throwIfParentInstance("setUninstallBlocked");
         if (mService != null) {
             try {
                 mService.setUninstallBlocked(admin, packageName, uninstallBlocked);
@@ -5362,6 +5448,7 @@
      * @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);
@@ -5389,6 +5476,7 @@
      * @see #getCrossProfileWidgetProviders(android.content.ComponentName)
      */
     public boolean addCrossProfileWidgetProvider(@NonNull ComponentName admin, String packageName) {
+        throwIfParentInstance("addCrossProfileWidgetProvider");
         if (mService != null) {
             try {
                 return mService.addCrossProfileWidgetProvider(admin, packageName);
@@ -5416,6 +5504,7 @@
      */
     public boolean removeCrossProfileWidgetProvider(
             @NonNull ComponentName admin, String packageName) {
+        throwIfParentInstance("removeCrossProfileWidgetProvider");
         if (mService != null) {
             try {
                 return mService.removeCrossProfileWidgetProvider(admin, packageName);
@@ -5437,6 +5526,7 @@
      * @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);
@@ -5458,6 +5548,7 @@
      * @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) {
@@ -5477,6 +5568,7 @@
      * @see SystemUpdatePolicy
      */
     public void setSystemUpdatePolicy(@NonNull ComponentName admin, SystemUpdatePolicy policy) {
+        throwIfParentInstance("setSystemUpdatePolicy");
         if (mService != null) {
             try {
                 mService.setSystemUpdatePolicy(admin, policy);
@@ -5492,6 +5584,7 @@
      * @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();
@@ -5517,6 +5610,7 @@
      * @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) {
@@ -5535,6 +5629,7 @@
      * @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) {
@@ -5553,6 +5648,7 @@
      */
     @SystemApi
     public void notifyPendingSystemUpdate(long updateReceivedTime) {
+        throwIfParentInstance("notifyPendingSystemUpdate");
         if (mService != null) {
             try {
                 mService.notifyPendingSystemUpdate(updateReceivedTime);
@@ -5580,6 +5676,7 @@
      * @see #setPermissionGrantState
      */
     public void setPermissionPolicy(@NonNull ComponentName admin, int policy) {
+        throwIfParentInstance("setPermissionPolicy");
         try {
             mService.setPermissionPolicy(admin, policy);
         } catch (RemoteException re) {
@@ -5594,6 +5691,7 @@
      * @return the current policy for future permission requests.
      */
     public int getPermissionPolicy(ComponentName admin) {
+        throwIfParentInstance("getPermissionPolicy");
         try {
             return mService.getPermissionPolicy(admin);
         } catch (RemoteException re) {
@@ -5630,6 +5728,7 @@
      */
     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) {
@@ -5658,6 +5757,7 @@
      */
     public int getPermissionGrantState(@NonNull ComponentName admin, String packageName,
             String permission) {
+        throwIfParentInstance("getPermissionGrantState");
         try {
             return mService.getPermissionGrantState(admin, packageName, permission);
         } catch (RemoteException re) {
@@ -5673,6 +5773,7 @@
      * @throws IllegalArgumentException if the supplied action is not valid.
      */
     public boolean isProvisioningAllowed(String action) {
+        throwIfParentInstance("isProvisioningAllowed");
         try {
             return mService.isProvisioningAllowed(action);
         } catch (RemoteException re) {
@@ -5688,6 +5789,7 @@
      * @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) {
@@ -5721,6 +5823,7 @@
      * @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) {
@@ -5737,6 +5840,7 @@
      * @see TelephonyManager#CALL_STATE_IDLE
      */
     public void reboot(@NonNull ComponentName admin) {
+        throwIfParentInstance("reboot");
         try {
             mService.reboot(admin);
         } catch (RemoteException re) {
@@ -5763,6 +5867,7 @@
      */
     public void setShortSupportMessage(@NonNull ComponentName admin,
             @Nullable CharSequence message) {
+        throwIfParentInstance("setShortSupportMessage");
         if (mService != null) {
             try {
                 mService.setShortSupportMessage(admin, message);
@@ -5781,6 +5886,7 @@
      * @throws SecurityException if {@code admin} is not an active administrator.
      */
     public CharSequence getShortSupportMessage(@NonNull ComponentName admin) {
+        throwIfParentInstance("getShortSupportMessage");
         if (mService != null) {
             try {
                 return mService.getShortSupportMessage(admin);
@@ -5807,6 +5913,7 @@
      */
     public void setLongSupportMessage(@NonNull ComponentName admin,
             @Nullable CharSequence message) {
+        throwIfParentInstance("setLongSupportMessage");
         if (mService != null) {
             try {
                 mService.setLongSupportMessage(admin, message);
@@ -5825,6 +5932,7 @@
      * @throws SecurityException if {@code admin} is not an active administrator.
      */
     public CharSequence getLongSupportMessage(@NonNull ComponentName admin) {
+        throwIfParentInstance("getLongSupportMessage");
         if (mService != null) {
             try {
                 return mService.getLongSupportMessage(admin);
@@ -5922,6 +6030,7 @@
      * @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.");
@@ -5948,6 +6057,7 @@
      * @see #retrieveSecurityLogs
      */
     public void setSecurityLoggingEnabled(@NonNull ComponentName admin, boolean enabled) {
+        throwIfParentInstance("setSecurityLoggingEnabled");
         try {
             mService.setSecurityLoggingEnabled(admin, enabled);
         } catch (RemoteException re) {
@@ -5966,6 +6076,7 @@
      * @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) {
@@ -5989,6 +6100,7 @@
      * @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) {
@@ -6034,6 +6146,7 @@
      * @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();
@@ -6055,6 +6168,7 @@
      * @throws SecurityException if {@code admin} is not a profile owner.
      */
     public void setOrganizationColor(@NonNull ComponentName admin, int color) {
+        throwIfParentInstance("setOrganizationColor");
         try {
             // always enforce alpha channel to have 100% opacity
             color |= 0xFF000000;
@@ -6094,6 +6208,7 @@
      * @throws SecurityException if {@code admin} is not a profile owner.
      */
     public @ColorInt int getOrganizationColor(@NonNull ComponentName admin) {
+        throwIfParentInstance("getOrganizationColor");
         try {
             return mService.getOrganizationColor(admin);
         } catch (RemoteException re) {
@@ -6129,6 +6244,7 @@
      * @throws SecurityException if {@code admin} is not a profile owner.
      */
     public void setOrganizationName(@NonNull ComponentName admin, @Nullable CharSequence title) {
+        throwIfParentInstance("setOrganizationName");
         try {
             mService.setOrganizationName(admin, title);
         } catch (RemoteException re) {
@@ -6145,6 +6261,7 @@
      * @throws SecurityException if {@code admin} is not a profile owner.
      */
     public CharSequence getOrganizationName(@NonNull ComponentName admin) {
+        throwIfParentInstance("getOrganizationName");
         try {
             return mService.getOrganizationName(admin);
         } catch (RemoteException re) {
@@ -6176,6 +6293,7 @@
     @SystemApi
     @UserProvisioningState
     public int getUserProvisioningState() {
+        throwIfParentInstance("getUserProvisioningState");
         if (mService != null) {
             try {
                 return mService.getUserProvisioningState();
@@ -6222,6 +6340,7 @@
      * @param ids A set of opaque affiliation ids.
      */
     public void setAffiliationIds(@NonNull ComponentName admin, Set<String> ids) {
+        throwIfParentInstance("setAffiliationIds");
         try {
             mService.setAffiliationIds(admin, new ArrayList<String>(ids));
         } catch (RemoteException e) {
@@ -6237,6 +6356,7 @@
      * @return whether this user/profile is affiliated with the device.
      */
     public boolean isAffiliatedUser() {
+        throwIfParentInstance("isAffiliatedUser");
         try {
             return mService != null && mService.isAffiliatedUser();
         } catch (RemoteException e) {
@@ -6270,4 +6390,10 @@
             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/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index aa1e372..4108f6d 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -1210,7 +1210,7 @@
             // For those APKs we only care about extracting signer certificates, and don't care
             // about verifying integrity.
             boolean signatureSchemeRollbackProtectionsEnforced =
-                    (parseFlags & PARSE_IS_SYSTEM) == 0;
+                    (parseFlags & PARSE_IS_SYSTEM_DIR) == 0;
             jarFile = new StrictJarFile(
                     apkPath,
                     !verified, // whether to verify JAR signature
@@ -1239,7 +1239,7 @@
             toVerify.add(manifestEntry);
 
             // If we're parsing an untrusted package, verify all contents
-            if ((parseFlags & PARSE_IS_SYSTEM) == 0) {
+            if ((parseFlags & PARSE_IS_SYSTEM_DIR) == 0) {
                 final Iterator<ZipEntry> i = jarFile.iterator();
                 while (i.hasNext()) {
                     final ZipEntry entry = i.next();
@@ -1679,7 +1679,6 @@
     private Package parseBaseApkCommon(Package pkg, Set<String> acceptedTags, Resources res,
             XmlResourceParser parser, int flags, String[] outError) throws XmlPullParserException,
             IOException {
-        final boolean trustedOverlay = (flags & PARSE_TRUSTED_OVERLAY) != 0;
         mParseInstrumentationArgs = null;
         mParseActivityArgs = null;
         mParseServiceArgs = null;
@@ -1769,8 +1768,6 @@
                     return null;
                 }
             } else if (tagName.equals(TAG_OVERLAY)) {
-                pkg.mTrustedOverlay = trustedOverlay;
-
                 sa = res.obtainAttributes(parser,
                         com.android.internal.R.styleable.AndroidManifestResourceOverlay);
                 pkg.mOverlayTarget = sa.getString(
@@ -2924,12 +2921,14 @@
             ai.flags |= ApplicationInfo.FLAG_EXTRACT_NATIVE_LIBS;
         }
 
-        if (sa.getBoolean(R.styleable.AndroidManifestApplication_defaultToDeviceProtectedStorage,
-                false) && (flags & PARSE_IS_SYSTEM) != 0) {
+        if (sa.getBoolean(
+                R.styleable.AndroidManifestApplication_defaultToDeviceProtectedStorage,
+                false)) {
             ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE;
         }
-        if (sa.getBoolean(R.styleable.AndroidManifestApplication_directBootAware, false)
-                && (flags & PARSE_IS_SYSTEM) != 0) {
+        if (sa.getBoolean(
+                R.styleable.AndroidManifestApplication_directBootAware,
+                false)) {
             ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_DIRECT_BOOT_AWARE;
         }
 
@@ -3554,7 +3553,7 @@
 
             a.info.encryptionAware = a.info.directBootAware = sa.getBoolean(
                     R.styleable.AndroidManifestActivity_directBootAware,
-                    owner.applicationInfo.isDirectBootAware());
+                    false);
         } else {
             a.info.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
             a.info.configChanges = 0;
@@ -3572,7 +3571,7 @@
 
             a.info.encryptionAware = a.info.directBootAware = sa.getBoolean(
                     R.styleable.AndroidManifestActivity_directBootAware,
-                    owner.applicationInfo.isDirectBootAware());
+                    false);
         }
 
         if (a.info.directBootAware) {
@@ -3985,7 +3984,7 @@
 
         p.info.encryptionAware = p.info.directBootAware = sa.getBoolean(
                 R.styleable.AndroidManifestProvider_directBootAware,
-                owner.applicationInfo.isDirectBootAware());
+                false);
         if (p.info.directBootAware) {
             owner.applicationInfo.privateFlags |=
                     ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE;
@@ -4277,7 +4276,7 @@
 
         s.info.encryptionAware = s.info.directBootAware = sa.getBoolean(
                 R.styleable.AndroidManifestService_directBootAware,
-                owner.applicationInfo.isDirectBootAware());
+                false);
         if (s.info.directBootAware) {
             owner.applicationInfo.privateFlags |=
                     ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE;
diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl
index 67d3959..55b0d2a 100644
--- a/core/java/android/os/IUserManager.aidl
+++ b/core/java/android/os/IUserManager.aidl
@@ -20,6 +20,7 @@
 import android.os.Bundle;
 import android.os.PersistableBundle;
 import android.content.pm.UserInfo;
+import android.content.IntentSender;
 import android.content.RestrictionEntry;
 import android.graphics.Bitmap;
 import android.os.ParcelFileDescriptor;
@@ -70,6 +71,7 @@
     boolean markGuestForDeletion(int userHandle);
     void setQuietModeEnabled(int userHandle, boolean enableQuietMode);
     boolean isQuietModeEnabled(int userHandle);
+    boolean trySetQuietModeDisabled(int userHandle, in IntentSender target);
     void setSeedAccountData(int userHandle, in String accountName,
             in String accountType, in PersistableBundle accountOptions, boolean persist);
     String getSeedAccountName();
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index d5b3b35..086a977 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -29,6 +29,7 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.content.IntentSender;
 import android.content.pm.UserInfo;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
@@ -1691,6 +1692,23 @@
     }
 
     /**
+     * Tries disabling quiet mode for a given user. If the user is still locked, we unlock the user
+     * first by showing the confirm credentials screen and disable quiet mode upon successful
+     * unlocking. If the user is already unlocked, we call through to {@link #setQuietModeEnabled}
+     * directly.
+     *
+     * @return true if the quiet mode was disabled immediately
+     * @hide
+     */
+    public boolean trySetQuietModeDisabled(@UserIdInt int userHandle, IntentSender target) {
+        try {
+            return mService.trySetQuietModeDisabled(userHandle, target);
+        } catch (RemoteException re) {
+            throw re.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * If the target user is a managed profile of the calling user or the caller
      * is itself a managed profile, then this returns a badged copy of the given
      * icon to be able to distinguish it from the original icon. For badging an
diff --git a/core/java/com/android/internal/app/UnlaunchableAppActivity.java b/core/java/com/android/internal/app/UnlaunchableAppActivity.java
index 27588e9..d24cefe 100644
--- a/core/java/com/android/internal/app/UnlaunchableAppActivity.java
+++ b/core/java/com/android/internal/app/UnlaunchableAppActivity.java
@@ -107,9 +107,8 @@
     @Override
     public void onClick(DialogInterface dialog, int which) {
         if (mReason == UNLAUNCHABLE_REASON_QUIET_MODE && which == DialogInterface.BUTTON_POSITIVE) {
-            UserManager.get(this).setQuietModeEnabled(mUserId, false);
-
-            if (mTarget != null) {
+            if (UserManager.get(this).trySetQuietModeDisabled(mUserId, mTarget)
+                    && mTarget != null) {
                 try {
                     startIntentSenderForResult(mTarget, -1, null, 0, 0, 0);
                 } catch (IntentSender.SendIntentException e) {
diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp
index f46f45c..898cf77 100644
--- a/core/jni/android/graphics/Paint.cpp
+++ b/core/jni/android/graphics/Paint.cpp
@@ -815,10 +815,15 @@
             }
 
             if (prevCp != kStartOfString &&
-                ((0xFE00 <= cp && cp <= 0xFE0F) || (0xE0100 <= cp && cp <= 0xE01EF)) &&
-                !MinikinUtils::hasVariationSelector(typeface, prevCp, cp)) {
-                // No font has a glyph for the code point and variation selector pair.
-                return false;
+                ((0xFE00 <= cp && cp <= 0xFE0F) || (0xE0100 <= cp && cp <= 0xE01EF))) {
+                bool hasVS = MinikinUtils::hasVariationSelector(typeface, prevCp, cp);
+                if (!hasVS) {
+                    // No font has a glyph for the code point and variation selector pair.
+                    return false;
+                } else if (nChars == 1 && i + 1 == str.size()) {
+                    // The string is just a codepoint and a VS, we have an authoritative answer
+                    return true;
+                }
             }
             nChars++;
             prevCp = cp;
diff --git a/libs/hwui/VectorDrawable.h b/libs/hwui/VectorDrawable.h
index 691cfa0..1c6f48e 100644
--- a/libs/hwui/VectorDrawable.h
+++ b/libs/hwui/VectorDrawable.h
@@ -219,22 +219,24 @@
             int fillType = 0; /* non-zero or kWinding_FillType in Skia */
         };
         FullPathProperties(Node* mNode) : Properties(mNode), mTrimDirty(false) {}
+        ~FullPathProperties() {
+            SkSafeUnref(fillGradient);
+            SkSafeUnref(strokeGradient);
+        }
         void syncProperties(const FullPathProperties& prop) {
             mPrimitiveFields = prop.mPrimitiveFields;
             mTrimDirty = true;
-            fillGradient.reset(prop.fillGradient);
-            strokeGradient.reset(prop.strokeGradient);
+            UPDATE_SKPROP(fillGradient, prop.fillGradient);
+            UPDATE_SKPROP(strokeGradient, prop.strokeGradient);
             onPropertyChanged();
         }
         void setFillGradient(SkShader* gradient) {
-            if(fillGradient != gradient){
-                fillGradient.reset(gradient);
+            if(UPDATE_SKPROP(fillGradient, gradient)) {
                 onPropertyChanged();
             }
         }
         void setStrokeGradient(SkShader* gradient) {
-            if(strokeGradient != gradient){
-                strokeGradient.reset(gradient);
+            if(UPDATE_SKPROP(strokeGradient, gradient)) {
                 onPropertyChanged();
             }
         }
@@ -346,8 +348,8 @@
             count,
         };
         PrimitiveFields mPrimitiveFields;
-        SkAutoTUnref<SkShader> fillGradient;
-        SkAutoTUnref<SkShader> strokeGradient;
+        SkShader* fillGradient = nullptr;
+        SkShader* strokeGradient = nullptr;
     };
 
     // Called from UI thread
diff --git a/media/java/android/media/browse/MediaBrowser.java b/media/java/android/media/browse/MediaBrowser.java
index 7c6adad..2cd9872 100644
--- a/media/java/android/media/browse/MediaBrowser.java
+++ b/media/java/android/media/browse/MediaBrowser.java
@@ -27,6 +27,7 @@
 import android.media.MediaDescription;
 import android.media.session.MediaController;
 import android.media.session.MediaSession;
+import android.os.Binder;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
@@ -475,14 +476,8 @@
         // the service will be told when we connect.
         if (mState == CONNECT_STATE_CONNECTED) {
             try {
-                // NOTE: Do not call addSubscriptionWithOptions when options are null. Otherwise,
-                // it will break the action of support library which expects addSubscription will
-                // be called when options are null.
-                if (options == null) {
-                    mServiceBinder.addSubscription(parentId, mServiceCallbacks);
-                } else {
-                    mServiceBinder.addSubscriptionWithOptions(parentId, options, mServiceCallbacks);
-                }
+                mServiceBinder.addSubscription(parentId, callback.mToken, options,
+                        mServiceCallbacks);
             } catch (RemoteException ex) {
                 // Process is crashing. We will disconnect, and upon reconnect we will
                 // automatically reregister. So nothing to do here.
@@ -497,34 +492,37 @@
             throw new IllegalArgumentException("parentId is empty.");
         }
 
-        // Remove from our list.
         Subscription sub = mSubscriptions.get(parentId);
-
+        if (sub == null) {
+            return;
+        }
         // Tell the service if necessary.
-        if (mState == CONNECT_STATE_CONNECTED && sub != null) {
-            try {
-                if (callback == null) {
-                    mServiceBinder.removeSubscription(parentId, mServiceCallbacks);
-                } else {
-                    final List<SubscriptionCallback> callbacks = sub.getCallbacks();
-                    final List<Bundle> optionsList = sub.getOptionsList();
-                    for (int i = callbacks.size() - 1; i >= 0; --i) {
-                        if (callbacks.get(i) == callback) {
-                            mServiceBinder.removeSubscriptionWithOptions(
-                                    parentId, optionsList.get(i), mServiceCallbacks);
-                            callbacks.remove(i);
-                            optionsList.remove(i);
+        try {
+            if (callback == null) {
+                if (mState == CONNECT_STATE_CONNECTED) {
+                    mServiceBinder.removeSubscription(parentId, null, mServiceCallbacks);
+                }
+            } else {
+                final List<SubscriptionCallback> callbacks = sub.getCallbacks();
+                final List<Bundle> optionsList = sub.getOptionsList();
+                for (int i = callbacks.size() - 1; i >= 0; --i) {
+                    if (callbacks.get(i) == callback) {
+                        if (mState == CONNECT_STATE_CONNECTED) {
+                            mServiceBinder.removeSubscription(
+                                    parentId, callback.mToken, mServiceCallbacks);
                         }
+                        callbacks.remove(i);
+                        optionsList.remove(i);
                     }
                 }
-            } catch (RemoteException ex) {
-                // Process is crashing. We will disconnect, and upon reconnect we will
-                // automatically reregister. So nothing to do here.
-                Log.d(TAG, "removeSubscription failed with RemoteException parentId=" + parentId);
             }
+        } catch (RemoteException ex) {
+            // Process is crashing. We will disconnect, and upon reconnect we will
+            // automatically reregister. So nothing to do here.
+            Log.d(TAG, "removeSubscription failed with RemoteException parentId=" + parentId);
         }
 
-        if (sub != null && (sub.isEmpty() || callback == null)) {
+        if (sub.isEmpty() || callback == null) {
             mSubscriptions.remove(parentId);
         }
     }
@@ -579,17 +577,12 @@
                 for (Entry<String, Subscription> subscriptionEntry : mSubscriptions.entrySet()) {
                     String id = subscriptionEntry.getKey();
                     Subscription sub = subscriptionEntry.getValue();
-                    for (Bundle options : sub.getOptionsList()) {
+                    List<SubscriptionCallback> callbackList = sub.getCallbacks();
+                    List<Bundle> optionsList = sub.getOptionsList();
+                    for (int i = 0; i < callbackList.size(); ++i) {
                         try {
-                            // NOTE: Do not call addSubscriptionWithOptions when options are null.
-                            // Otherwise, it will break the action of support library which expects
-                            // addSubscription will be called when options are null.
-                            if (options == null) {
-                                mServiceBinder.addSubscription(id, mServiceCallbacks);
-                            } else {
-                                mServiceBinder.addSubscriptionWithOptions(
-                                        id, options, mServiceCallbacks);
-                            }
+                            mServiceBinder.addSubscription(id, callbackList.get(i).mToken,
+                                    optionsList.get(i), mServiceCallbacks);
                         } catch (RemoteException ex) {
                             // Process is crashing. We will disconnect, and upon reconnect we will
                             // automatically reregister. So nothing to do here.
@@ -859,6 +852,12 @@
      * Callbacks for subscription related events.
      */
     public static abstract class SubscriptionCallback {
+        Binder mToken;
+
+        public SubscriptionCallback() {
+            mToken = new Binder();
+        }
+
         /**
          * Called when the list of children is loaded or updated.
          *
@@ -1071,12 +1070,7 @@
         }
 
         @Override
-        public void onLoadChildren(String parentId, ParceledListSlice list) {
-            onLoadChildrenWithOptions(parentId, list, null);
-        }
-
-        @Override
-        public void onLoadChildrenWithOptions(String parentId, ParceledListSlice list,
+        public void onLoadChildren(String parentId, ParceledListSlice list,
                 final Bundle options) {
             MediaBrowser mediaBrowser = mMediaBrowser.get();
             if (mediaBrowser != null) {
diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java
index e134635..21211d7 100644
--- a/media/java/android/media/tv/TvInputService.java
+++ b/media/java/android/media/tv/TvInputService.java
@@ -839,9 +839,11 @@
         public abstract boolean onTune(Uri channelUri);
 
         /**
-         * Calls {@link #onTune(Uri)}. Override this method in order to handle domain-specific
+         * Tunes to a given channel. Override this method in order to handle domain-specific
          * features that are only known between certain TV inputs and their clients.
          *
+         * <p>The default implementation calls {@link #onTune(Uri)}.
+         *
          * @param channelUri The URI of the channel.
          * @param params Domain-specific data for this tune request. Keys <em>must</em> be a scoped
          *            name, i.e. prefixed with a package name you own, so that different developers
@@ -1693,11 +1695,12 @@
         public abstract void onTune(Uri channelUri);
 
         /**
-         * Calls {@link #onTune(Uri)}. Override this method in order to handle domain-specific
-         * features that are only known between certain TV inputs and their clients.
+         * Called when the application requests to tune to a given channel for TV program recording.
+         * Override this method in order to handle domain-specific features that are only known
+         * between certain TV inputs and their clients.
          *
          * <p>The application may call this method before starting or after stopping recording, but
-         * not during recording.
+         * not during recording. The default implementation calls {@link #onTune(Uri)}.
          *
          * <p>The session must call {@link #notifyTuned(Uri)} if the tune request was fulfilled, or
          * {@link #notifyError(int)} otherwise.
diff --git a/media/java/android/service/media/IMediaBrowserService.aidl b/media/java/android/service/media/IMediaBrowserService.aidl
index 6ca5ac5..eef5a7c 100644
--- a/media/java/android/service/media/IMediaBrowserService.aidl
+++ b/media/java/android/service/media/IMediaBrowserService.aidl
@@ -14,19 +14,11 @@
  * @hide
  */
 oneway interface IMediaBrowserService {
-
-    // Warning: DO NOT CHANGE the methods signature and order of methods.
-    // A change of the order or the method signatures could break the support library.
-
     void connect(String pkg, in Bundle rootHints, IMediaBrowserServiceCallbacks callbacks);
     void disconnect(IMediaBrowserServiceCallbacks callbacks);
 
-    void addSubscription(String uri, IMediaBrowserServiceCallbacks callbacks);
-    void removeSubscription(String uri, IMediaBrowserServiceCallbacks callbacks);
+    void addSubscription(String uri, in IBinder token, in Bundle options,
+            IMediaBrowserServiceCallbacks callbacks);
+    void removeSubscription(String uri, in IBinder token, IMediaBrowserServiceCallbacks callbacks);
     void getMediaItem(String uri, in ResultReceiver cb);
-
-    void addSubscriptionWithOptions(String uri, in Bundle options,
-            IMediaBrowserServiceCallbacks callbacks);
-    void removeSubscriptionWithOptions(String uri, in Bundle options,
-            IMediaBrowserServiceCallbacks callbacks);
 }
diff --git a/media/java/android/service/media/IMediaBrowserServiceCallbacks.aidl b/media/java/android/service/media/IMediaBrowserServiceCallbacks.aidl
index e6b0e8c..dadb025 100644
--- a/media/java/android/service/media/IMediaBrowserServiceCallbacks.aidl
+++ b/media/java/android/service/media/IMediaBrowserServiceCallbacks.aidl
@@ -13,10 +13,6 @@
  * @hide
  */
 oneway interface IMediaBrowserServiceCallbacks {
-
-    // Warning: DO NOT CHANGE the methods signature and order of methods.
-    // A change of the order or the method signatures could break the support library.
-
     /**
      * Invoked when the connected has been established.
      * @param root The root media id for browsing.
@@ -26,6 +22,5 @@
      */
     void onConnect(String root, in MediaSession.Token session, in Bundle extras);
     void onConnectFailed();
-    void onLoadChildren(String mediaId, in ParceledListSlice list);
-    void onLoadChildrenWithOptions(String mediaId, in ParceledListSlice list, in Bundle options);
+    void onLoadChildren(String mediaId, in ParceledListSlice list, in Bundle options);
 }
diff --git a/media/java/android/service/media/MediaBrowserService.java b/media/java/android/service/media/MediaBrowserService.java
index 6954045..ddc0e88 100644
--- a/media/java/android/service/media/MediaBrowserService.java
+++ b/media/java/android/service/media/MediaBrowserService.java
@@ -39,6 +39,7 @@
 import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.Log;
+import android.util.Pair;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -108,7 +109,7 @@
         Bundle rootHints;
         IMediaBrowserServiceCallbacks callbacks;
         BrowserRoot root;
-        HashMap<String, List<Bundle>> subscriptions = new HashMap<>();
+        HashMap<String, List<Pair<IBinder, Bundle>>> subscriptions = new HashMap<>();
     }
 
     /**
@@ -247,13 +248,7 @@
         }
 
         @Override
-        public void addSubscription(final String id,
-                final IMediaBrowserServiceCallbacks callbacks) {
-            addSubscriptionWithOptions(id, null, callbacks);
-        }
-
-        @Override
-        public void addSubscriptionWithOptions(final String id, final Bundle options,
+        public void addSubscription(final String id, final IBinder token, final Bundle options,
                 final IMediaBrowserServiceCallbacks callbacks) {
             mHandler.post(new Runnable() {
                     @Override
@@ -268,19 +263,13 @@
                             return;
                         }
 
-                        MediaBrowserService.this.addSubscription(id, connection, options);
+                        MediaBrowserService.this.addSubscription(id, connection, token, options);
                     }
                 });
         }
 
         @Override
-        public void removeSubscription(final String id,
-                final IMediaBrowserServiceCallbacks callbacks) {
-            removeSubscriptionWithOptions(id, null, callbacks);
-        }
-
-        @Override
-        public void removeSubscriptionWithOptions(final String id, final Bundle options,
+        public void removeSubscription(final String id, final IBinder token,
                 final IMediaBrowserServiceCallbacks callbacks) {
             mHandler.post(new Runnable() {
                 @Override
@@ -293,7 +282,7 @@
                                 + id);
                         return;
                     }
-                    if (!MediaBrowserService.this.removeSubscription(id, connection, options)) {
+                    if (!MediaBrowserService.this.removeSubscription(id, connection, token)) {
                         Log.w(TAG, "removeSubscription called for " + id
                                 + " which is not subscribed");
                     }
@@ -519,11 +508,12 @@
             public void run() {
                 for (IBinder binder : mConnections.keySet()) {
                     ConnectionRecord connection = mConnections.get(binder);
-                    List<Bundle> optionsList = connection.subscriptions.get(parentId);
-                    if (optionsList != null) {
-                        for (Bundle bundle : optionsList) {
-                            if (MediaBrowserUtils.hasDuplicatedItems(options, bundle)) {
-                                performLoadChildren(parentId, connection, bundle);
+                    List<Pair<IBinder, Bundle>> callbackList =
+                            connection.subscriptions.get(parentId);
+                    if (callbackList != null) {
+                        for (Pair<IBinder, Bundle> callback : callbackList) {
+                            if (MediaBrowserUtils.hasDuplicatedItems(options, callback.second)) {
+                                performLoadChildren(parentId, connection, callback.second);
                             }
                         }
                     }
@@ -553,19 +543,21 @@
     /**
      * Save the subscription and if it is a new subscription send the results.
      */
-    private void addSubscription(String id, ConnectionRecord connection, Bundle options) {
+    private void addSubscription(String id, ConnectionRecord connection, IBinder token,
+            Bundle options) {
         // Save the subscription
-        List<Bundle> optionsList = connection.subscriptions.get(id);
-        if (optionsList == null) {
-            optionsList = new ArrayList<>();
+        List<Pair<IBinder, Bundle>> callbackList = connection.subscriptions.get(id);
+        if (callbackList == null) {
+            callbackList = new ArrayList<>();
         }
-        for (Bundle bundle : optionsList) {
-            if (MediaBrowserUtils.areSameOptions(options, bundle)) {
+        for (Pair<IBinder, Bundle> callback : callbackList) {
+            if (token == callback.first
+                    && MediaBrowserUtils.areSameOptions(options, callback.second)) {
                 return;
             }
         }
-        optionsList.add(options);
-        connection.subscriptions.put(id, optionsList);
+        callbackList.add(new Pair<>(token, options));
+        connection.subscriptions.put(id, callbackList);
         // send the results
         performLoadChildren(id, connection, options);
     }
@@ -573,21 +565,20 @@
     /**
      * Remove the subscription.
      */
-    private boolean removeSubscription(String id, ConnectionRecord connection, Bundle options) {
-        if (options == null) {
+    private boolean removeSubscription(String id, ConnectionRecord connection, IBinder token) {
+        if (token == null) {
             return connection.subscriptions.remove(id) != null;
         }
         boolean removed = false;
-        List<Bundle> optionsList = connection.subscriptions.get(id);
-        if (optionsList != null) {
-            for (Bundle bundle : optionsList) {
-                if (MediaBrowserUtils.areSameOptions(options, bundle)) {
+        List<Pair<IBinder, Bundle>> callbackList = connection.subscriptions.get(id);
+        if (callbackList != null) {
+            for (Pair<IBinder, Bundle> callback : callbackList) {
+                if (token == callback.first) {
                     removed = true;
-                    optionsList.remove(bundle);
-                    break;
+                    callbackList.remove(callback);
                 }
             }
-            if (optionsList.size() == 0) {
+            if (callbackList.size() == 0) {
                 connection.subscriptions.remove(id);
             }
         }
@@ -619,14 +610,7 @@
                 final ParceledListSlice<MediaBrowser.MediaItem> pls =
                         filteredList == null ? null : new ParceledListSlice<>(filteredList);
                 try {
-                    // NOTE: Do not call onLoadChildrenWithOptions when options are null. Otherwise,
-                    // it will break the action of support library which expects onLoadChildren will
-                    // be called when options are null.
-                    if (options == null) {
-                        connection.callbacks.onLoadChildren(parentId, pls);
-                    } else {
-                        connection.callbacks.onLoadChildrenWithOptions(parentId, pls, options);
-                    }
+                    connection.callbacks.onLoadChildren(parentId, pls, options);
                 } catch (RemoteException ex) {
                     // The other side is in the process of crashing.
                     Log.w(TAG, "Calling onLoadChildren() failed for id=" + parentId
diff --git a/packages/SettingsLib/res/drawable/notification_auto_importance.xml b/packages/SettingsLib/res/drawable/notification_auto_importance.xml
new file mode 100644
index 0000000..a63e911b
--- /dev/null
+++ b/packages/SettingsLib/res/drawable/notification_auto_importance.xml
@@ -0,0 +1,27 @@
+<!--
+    Copyright (C) 2016 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+            android:fillColor="#FFFFFFFF"
+            android:pathData="M11.2,13.6l1.6,0l-0.8,-2.6z"/>
+    <path
+            android:fillColor="#FF000000"
+            android:pathData="M22.5,9.6L15,9l-3,-7L9,9L1.5,9.6l5.7,5L5.5,22l6.5,-3.9l6.5,3.9l-1.7,-7.4L22.5,9.6zM13.6,16l-0.5,-1.4h-2.3L10.4,16H9l2.3,-6.4h1.4L15,16H13.6z"/>
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/notification_guts.xml b/packages/SystemUI/res/layout/notification_guts.xml
index 062ae35..e1424f0 100644
--- a/packages/SystemUI/res/layout/notification_guts.xml
+++ b/packages/SystemUI/res/layout/notification_guts.xml
@@ -32,7 +32,7 @@
     <LinearLayout
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:paddingTop="14dp"
+            android:paddingTop="15dp"
             android:paddingEnd="8dp"
             android:id="@+id/notification_guts_header"
             android:orientation="horizontal"
@@ -99,6 +99,7 @@
             android:clickable="false"
             android:focusable="false"
             android:paddingEnd="8dp"
+            android:paddingTop="4dp"
             android:visibility="gone">
         <TextView
                 android:id="@+id/title"
@@ -123,21 +124,20 @@
 
         <FrameLayout
                 android:layout_width="match_parent"
-                android:layout_height="48dp"
+                android:layout_height="wrap_content"
                 android:paddingTop="8dp" >
 
             <ImageView
-                    android:id="@+id/low_importance"
-                    android:src="@*android:drawable/ic_notification_block"
+                    android:id="@+id/auto_importance"
+                    android:src="@drawable/notification_auto_importance"
                     android:layout_gravity="center_vertical|start"
-                    android:layout_width="24dp"
-                    android:layout_height="24dp"
-                    android:tint="@color/notification_guts_icon_tint"/>
+                    android:layout_width="48dp"
+                    android:layout_height="48dp" />
 
             <SeekBar
                     android:id="@+id/seekbar"
                     android:layout_marginStart="56dp"
-                    android:layout_marginEnd="56dp"
+                    android:layout_marginEnd="32dp"
                     android:layout_gravity="center_vertical"
                     android:layout_width="match_parent"
                     android:layout_height="48dp"
@@ -149,14 +149,6 @@
                     style="@android:style/Widget.Material.SeekBar.Discrete"
                     android:tickMarkTint="@android:color/black" />
 
-            <ImageView
-                    android:id="@+id/max_importance"
-                    android:src="@*android:drawable/ic_notification_alert"
-                    android:layout_gravity="center_vertical|end"
-                    android:layout_width="24dp"
-                    android:layout_height="24dp"
-                    android:tint="@color/notification_guts_icon_tint" />
-
         </FrameLayout>
     </LinearLayout>
     <!-- buttons -->
diff --git a/packages/SystemUI/res/layout/power_notification_controls_settings.xml b/packages/SystemUI/res/layout/power_notification_controls_settings.xml
new file mode 100644
index 0000000..83c8a51
--- /dev/null
+++ b/packages/SystemUI/res/layout/power_notification_controls_settings.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
+
+    <include layout="@layout/switch_bar" />
+
+    <TextView
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:padding="16dp"
+            android:text="@string/power_notification_controls_description"/>
+
+</LinearLayout>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index d26fb06..c75741c 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -108,6 +108,7 @@
     <!-- The "inside" of a notification, reached via longpress -->
     <color name="notification_guts_bg_color">#eeeeee</color>
     <color name="notification_guts_slider_color">@*android:color/material_deep_teal_500</color>
+    <color name="notification_guts_disabled_slider_color">@*android:color/material_grey_300</color>
     <color name="notification_guts_secondary_slider_color">#858383</color>
     <color name="notification_guts_icon_tint">#8a000000</color>
     <color name="notification_guts_disabled_icon_tint">#4d000000</color>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index a4d7a18..37b00bb 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1225,38 +1225,69 @@
     <string name="do_not_silence_block">Don\'t silence or block</string>
 
     <!-- [CHAR LIMIT=NONE] Importance Tuner setting title -->
-    <string name="tuner_full_importance_settings">Show full importance settings</string>
+    <string name="tuner_full_importance_settings">Power notification controls</string>
+    <string name="tuner_full_importance_settings_on">On</string>
+    <string name="tuner_full_importance_settings_off">Off</string>
+    <string name="power_notification_controls_description">With power notification controls, you can set an importance level from 0 to 5 for an app\'s notifications.
+        \n\n<b>Level 5</b>
+        \n- Show at the top of the notification list
+        \n- Allow full screen interruption
+        \n- Always peek
+        \n\n<b>Level 4</b>
+        \n- Prevent full screen interruption
+        \n- Always peek
+        \n\n<b>Level 3</b>
+        \n- Prevent full screen interruption
+        \n- Never peek
+        \n\n<b>Level 2</b>
+        \n- Prevent full screen interruption
+        \n- Never peek
+        \n- Never make sound and vibration
+        \n\n<b>Level 1</b>
+        \n- Prevent full screen interruption
+        \n- Never peek
+        \n- Never make sound or vibrate
+        \n- Hide from lock screen and status bar
+        \n- Show at the bottom of the notification list
+        \n\n<b>Level 0</b>
+        \n- Block all notifications from the app
+    </string>
 
+    <!-- Notification importance title, user unspecified status-->
+    <string name="user_unspecified_importance">Importance: Automatic</string>
     <!-- Notification importance title, blocked status-->
-    <string name="blocked_importance">Blocked</string>
+    <string name="blocked_importance">Importance: Level 0</string>
     <!-- Notification importance title, min status-->
-    <string name="min_importance">Min importance</string>
+    <string name="min_importance">Importance: Level 1</string>
     <!-- Notification importance title, low status-->
-    <string name="low_importance">Low importance</string>
+    <string name="low_importance">Importance: Level 2</string>
     <!-- Notification importance title, normal status-->
-    <string name="default_importance">Normal importance</string>
+    <string name="default_importance">Importance: Level 3</string>
     <!-- Notification importance title, high status-->
-    <string name="high_importance">High importance</string>
+    <string name="high_importance">Importance: Level 4</string>
     <!-- Notification importance title, max status-->
-    <string name="max_importance">Urgent importance</string>
+    <string name="max_importance">Importance: Level 5</string>
 
     <!-- [CHAR LIMIT=100] Notification Importance slider: blocked importance level description -->
-    <string name="notification_importance_blocked">Never show these notifications</string>
+    <string name="notification_importance_user_unspecified">App determines importance for each notification.</string>
+
+    <!-- [CHAR LIMIT=100] Notification Importance slider: blocked importance level description -->
+    <string name="notification_importance_blocked">Never show notifications from this app.</string>
 
     <!-- [CHAR LIMIT=100] Notification Importance slider: min importance level description -->
-    <string name="notification_importance_min">Silently show at the bottom of the notification list</string>
+    <string name="notification_importance_min">No full screen interruption, peeking, sound, or vibration. Hide from lock screen and status bar.</string>
 
     <!-- [CHAR LIMIT=100] Notification Importance slider: low importance level description -->
-    <string name="notification_importance_low">Silently show these notifications</string>
+    <string name="notification_importance_low">No full screen interruption, peeking, sound, or vibration.</string>
 
     <!-- [CHAR LIMIT=100] Notification Importance slider: normal importance level description -->
-    <string name="notification_importance_default">Allow these notification to make sounds</string>
+    <string name="notification_importance_default">No full screen interruption or peeking.</string>
 
     <!-- [CHAR LIMIT=100] Notification Importance slider: high importance level description -->
-    <string name="notification_importance_high">Peek onto the screen and allow sound and allow sound</string>
+    <string name="notification_importance_high">Always peek. No full screen interruption.</string>
 
     <!-- [CHAR LIMIT=100] Notification Importance slider: max importance level description -->
-    <string name="notification_importance_max">Show at the top of the notifications list, peek onto the screen and allow sound</string>
+    <string name="notification_importance_max">Always peek, and allow full screen interruption.</string>
 
     <!-- Notification: Control panel: Label for button that launches notification settings. [CHAR LIMIT=NONE] -->
     <string name="notification_more_settings">More settings</string>
diff --git a/packages/SystemUI/res/xml/other_settings.xml b/packages/SystemUI/res/xml/other_settings.xml
new file mode 100644
index 0000000..3c872fa
--- /dev/null
+++ b/packages/SystemUI/res/xml/other_settings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+                  xmlns:sysui="http://schemas.android.com/apk/res-auto"
+                  android:title="@string/other">
+
+    <com.android.systemui.tuner.TunerSwitch
+            android:key="overview_nav_bar_gesture"
+            android:title="@string/overview_nav_bar_gesture"
+            android:summary="@string/overview_nav_bar_gesture_desc" />
+
+    <!-- importance -->
+    <Preference
+            android:key="power_notification_controls"
+            android:title="@string/tuner_full_importance_settings"
+            android:fragment="com.android.systemui.tuner.PowerNotificationControlsFragment"/>
+
+</PreferenceScreen>
\ No newline at end of file
diff --git a/packages/SystemUI/res/xml/tuner_prefs.xml b/packages/SystemUI/res/xml/tuner_prefs.xml
index 1af9075..116bc69 100644
--- a/packages/SystemUI/res/xml/tuner_prefs.xml
+++ b/packages/SystemUI/res/xml/tuner_prefs.xml
@@ -135,21 +135,10 @@
         android:fragment="com.android.systemui.tuner.NavBarTuner" />
     -->
 
-    <PreferenceScreen
-        android:key="other"
-        android:title="@string/other" >
-
-        <com.android.systemui.tuner.TunerSwitch
-            android:key="overview_nav_bar_gesture"
-            android:title="@string/overview_nav_bar_gesture"
-            android:summary="@string/overview_nav_bar_gesture_desc" />
-
-        <!-- importance -->
-        <com.android.systemui.tuner.TunerSwitch
-                android:key="show_importance_slider"
-                android:title="@string/tuner_full_importance_settings" />
-
-    </PreferenceScreen>
+    <Preference
+            android:key="other"
+            android:title="@string/other"
+            android:fragment="com.android.systemui.tuner.OtherPrefs" />
 
     <!-- Warning, this goes last. -->
     <Preference
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
index 3c464d5..057b020 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
@@ -22,12 +22,14 @@
 import android.content.Context;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
+import android.content.res.ColorStateList;
 import android.graphics.Canvas;
 import android.graphics.drawable.Drawable;
 import android.os.Handler;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.service.notification.NotificationListenerService;
+import android.service.notification.NotificationListenerService.Ranking;
 import android.service.notification.StatusBarNotification;
 import android.util.AttributeSet;
 import android.view.View;
@@ -60,10 +62,18 @@
     private int mActualHeight;
     private boolean mExposed;
     private INotificationManager mINotificationManager;
-    private int mStartingImportance;
+    private int mStartingUserImportance;
+    private int mNotificationImportance;
     private boolean mShowSlider;
 
     private SeekBar mSeekBar;
+    private ImageView mAutoButton;
+    private ColorStateList mActiveSliderTint;
+    private ColorStateList mInactiveSliderTint;
+    private TextView mImportanceSummary;
+    private TextView mImportanceTitle;
+    private boolean mAuto;
+
     private RadioButton mBlock;
     private RadioButton mSilent;
     private RadioButton mReset;
@@ -145,9 +155,14 @@
 
     void bindImportance(final PackageManager pm, final StatusBarNotification sbn,
             final ExpandableNotificationRow row, final int importance) {
-        mStartingImportance = importance;
         mINotificationManager = INotificationManager.Stub.asInterface(
                 ServiceManager.getService(Context.NOTIFICATION_SERVICE));
+        mStartingUserImportance = NotificationListenerService.Ranking.IMPORTANCE_UNSPECIFIED;
+        try {
+            mStartingUserImportance =
+                    mINotificationManager.getImportance(sbn.getPackageName(), sbn.getUid());
+        } catch (RemoteException e) {}
+        mNotificationImportance = importance;
         boolean systemApp = false;
         try {
             final PackageInfo info =
@@ -160,29 +175,25 @@
         final View importanceSlider = row.findViewById(R.id.importance_slider);
         final View importanceButtons = row.findViewById(R.id.importance_buttons);
         if (mShowSlider) {
-            bindSlider(importanceSlider, sbn, systemApp);
+            bindSlider(importanceSlider, systemApp);
             importanceSlider.setVisibility(View.VISIBLE);
             importanceButtons.setVisibility(View.GONE);
         } else {
-            mStartingImportance = NotificationListenerService.Ranking.IMPORTANCE_UNSPECIFIED;
-            try {
-                mStartingImportance =
-                        mINotificationManager.getImportance(sbn.getPackageName(), sbn.getUid());
-            } catch (RemoteException e) {}
-            bindToggles(importanceButtons, mStartingImportance, systemApp);
+
+            bindToggles(importanceButtons, mStartingUserImportance, systemApp);
             importanceButtons.setVisibility(View.VISIBLE);
             importanceSlider.setVisibility(View.GONE);
         }
     }
 
     public boolean hasImportanceChanged() {
-        return mStartingImportance != getSelectedImportance();
+        return mStartingUserImportance != getSelectedImportance();
     }
 
     void saveImportance(final StatusBarNotification sbn) {
         int progress = getSelectedImportance();
         MetricsLogger.action(mContext, MetricsEvent.ACTION_SAVE_IMPORTANCE,
-                progress - mStartingImportance);
+                progress - mStartingUserImportance);
         try {
             mINotificationManager.setImportance(sbn.getPackageName(), sbn.getUid(), progress);
         } catch (RemoteException e) {
@@ -192,14 +203,18 @@
 
     private int getSelectedImportance() {
         if (mSeekBar!= null && mSeekBar.isShown()) {
-            return mSeekBar.getProgress();
+            if (mSeekBar.isEnabled()) {
+                return mSeekBar.getProgress();
+            } else {
+                return Ranking.IMPORTANCE_UNSPECIFIED;
+            }
         } else {
             if (mBlock.isChecked()) {
-                return NotificationListenerService.Ranking.IMPORTANCE_NONE;
+                return Ranking.IMPORTANCE_NONE;
             } else if (mSilent.isChecked()) {
-                return NotificationListenerService.Ranking.IMPORTANCE_LOW;
+                return Ranking.IMPORTANCE_LOW;
             } else {
-                return NotificationListenerService.Ranking.IMPORTANCE_UNSPECIFIED;
+                return Ranking.IMPORTANCE_UNSPECIFIED;
             }
         }
     }
@@ -229,16 +244,14 @@
         }
     }
 
-    private void bindSlider(final View importanceSlider, final StatusBarNotification sbn,
-            final boolean systemApp) {
-        final TextView importanceSummary = ((TextView) importanceSlider.findViewById(R.id.summary));
-        final TextView importanceTitle = ((TextView) importanceSlider.findViewById(R.id.title));
+    private void bindSlider(final View importanceSlider, final boolean systemApp) {
+        mActiveSliderTint = loadColorStateList(R.color.notification_guts_slider_color);
+        mInactiveSliderTint = loadColorStateList(R.color.notification_guts_disabled_slider_color);
+
+        mImportanceSummary = ((TextView) importanceSlider.findViewById(R.id.summary));
+        mImportanceTitle = ((TextView) importanceSlider.findViewById(R.id.title));
         mSeekBar = (SeekBar) importanceSlider.findViewById(R.id.seekbar);
 
-        if (systemApp) {
-            ((ImageView) importanceSlider.findViewById(R.id.low_importance)).getDrawable().setTint(
-                    mContext.getColor(R.color.notification_guts_disabled_icon_tint));
-        }
         final int minProgress = systemApp ?
                 NotificationListenerService.Ranking.IMPORTANCE_MIN
                 : NotificationListenerService.Ranking.IMPORTANCE_NONE;
@@ -267,42 +280,80 @@
                 // no-op
             }
 
-            private void updateTitleAndSummary(int progress) {
-                switch (progress) {
-                    case NotificationListenerService.Ranking.IMPORTANCE_NONE:
-                        importanceSummary.setText(mContext.getString(
-                                R.string.notification_importance_blocked));
-                        importanceTitle.setText(mContext.getString(R.string.blocked_importance));
-                        break;
-                    case NotificationListenerService.Ranking.IMPORTANCE_MIN:
-                        importanceSummary.setText(mContext.getString(
-                                R.string.notification_importance_min));
-                        importanceTitle.setText(mContext.getString(R.string.min_importance));
-                        break;
-                    case NotificationListenerService.Ranking.IMPORTANCE_LOW:
-                        importanceSummary.setText(mContext.getString(
-                                R.string.notification_importance_low));
-                        importanceTitle.setText(mContext.getString(R.string.low_importance));
-                        break;
-                    case NotificationListenerService.Ranking.IMPORTANCE_DEFAULT:
-                        importanceSummary.setText(mContext.getString(
-                                R.string.notification_importance_default));
-                        importanceTitle.setText(mContext.getString(R.string.default_importance));
-                        break;
-                    case NotificationListenerService.Ranking.IMPORTANCE_HIGH:
-                        importanceSummary.setText(mContext.getString(
-                                R.string.notification_importance_high));
-                        importanceTitle.setText(mContext.getString(R.string.high_importance));
-                        break;
-                    case NotificationListenerService.Ranking.IMPORTANCE_MAX:
-                        importanceSummary.setText(mContext.getString(
-                                R.string.notification_importance_max));
-                        importanceTitle.setText(mContext.getString(R.string.max_importance));
-                        break;
-                }
+
+        });
+        mSeekBar.setProgress(mNotificationImportance);
+
+        mAutoButton = (ImageView) importanceSlider.findViewById(R.id.auto_importance);
+        mAutoButton.setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                mAuto = !mAuto;
+                applyAuto();
             }
         });
-        mSeekBar.setProgress(mStartingImportance);
+        mAuto = mStartingUserImportance == Ranking.IMPORTANCE_UNSPECIFIED;
+        applyAuto();
+    }
+
+    private void applyAuto() {
+        mSeekBar.setEnabled(!mAuto);
+
+        final ColorStateList tint = mAuto ? mInactiveSliderTint : mActiveSliderTint;
+        Drawable icon = mAutoButton.getDrawable().mutate();
+        icon.setTintList(tint);
+        mAutoButton.setImageDrawable(icon);
+        mSeekBar.setProgressTintList(tint);
+        mSeekBar.setThumbTintList(tint);
+
+        if (mAuto) {
+            mSeekBar.setProgress(mNotificationImportance);
+            mImportanceSummary.setText(mContext.getString(
+                    R.string.notification_importance_user_unspecified));
+            mImportanceTitle.setText(mContext.getString(
+                    R.string.user_unspecified_importance));
+        } else {
+            updateTitleAndSummary(mSeekBar.getProgress());
+        }
+    }
+
+    private void updateTitleAndSummary(int progress) {
+        switch (progress) {
+            case Ranking.IMPORTANCE_NONE:
+                mImportanceSummary.setText(mContext.getString(
+                        R.string.notification_importance_blocked));
+                mImportanceTitle.setText(mContext.getString(R.string.blocked_importance));
+                break;
+            case Ranking.IMPORTANCE_MIN:
+                mImportanceSummary.setText(mContext.getString(
+                        R.string.notification_importance_min));
+                mImportanceTitle.setText(mContext.getString(R.string.min_importance));
+                break;
+            case Ranking.IMPORTANCE_LOW:
+                mImportanceSummary.setText(mContext.getString(
+                        R.string.notification_importance_low));
+                mImportanceTitle.setText(mContext.getString(R.string.low_importance));
+                break;
+            case Ranking.IMPORTANCE_DEFAULT:
+                mImportanceSummary.setText(mContext.getString(
+                        R.string.notification_importance_default));
+                mImportanceTitle.setText(mContext.getString(R.string.default_importance));
+                break;
+            case Ranking.IMPORTANCE_HIGH:
+                mImportanceSummary.setText(mContext.getString(
+                        R.string.notification_importance_high));
+                mImportanceTitle.setText(mContext.getString(R.string.high_importance));
+                break;
+            case Ranking.IMPORTANCE_MAX:
+                mImportanceSummary.setText(mContext.getString(
+                        R.string.notification_importance_max));
+                mImportanceTitle.setText(mContext.getString(R.string.max_importance));
+                break;
+        }
+    }
+
+    private ColorStateList loadColorStateList(int colorResId) {
+        return ColorStateList.valueOf(mContext.getColor(colorResId));
     }
 
     public void closeControls(int x, int y, boolean notify) {
@@ -353,7 +404,6 @@
 
     @Override
     public boolean hasOverlappingRendering() {
-
         // Prevents this view from creating a layer when alpha is animating.
         return false;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ManagedProfileController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ManagedProfileController.java
index 41eed56..951b096 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ManagedProfileController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ManagedProfileController.java
@@ -15,6 +15,7 @@
 package com.android.systemui.statusbar.phone;
 
 import android.app.ActivityManager;
+import android.app.StatusBarManager;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -57,10 +58,18 @@
         }
     }
 
-    public void setWorkModeEnabled(boolean enabled) {
+    public void setWorkModeEnabled(boolean enableWorkMode) {
         synchronized (mProfiles) {
             for (UserInfo ui : mProfiles) {
-                mUserManager.setQuietModeEnabled(ui.id, !enabled);
+                if (enableWorkMode) {
+                    if (!mUserManager.trySetQuietModeDisabled(ui.id, null)) {
+                        StatusBarManager statusBarManager = (StatusBarManager) mContext
+                                .getSystemService(android.app.Service.STATUS_BAR_SERVICE);
+                        statusBarManager.collapsePanels();
+                    }
+                } else {
+                    mUserManager.setQuietModeEnabled(ui.id, true);
+                }
             }
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/OtherPrefs.java b/packages/SystemUI/src/com/android/systemui/tuner/OtherPrefs.java
new file mode 100644
index 0000000..205db32
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/tuner/OtherPrefs.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.tuner;
+
+import android.os.Bundle;
+import android.support.v14.preference.PreferenceFragment;
+import com.android.systemui.R;
+
+public class OtherPrefs extends PreferenceFragment {
+    @Override
+    public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
+        addPreferencesFromResource(R.xml.other_settings);
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/PowerNotificationControlsFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/PowerNotificationControlsFragment.java
new file mode 100644
index 0000000..14fccf2
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/tuner/PowerNotificationControlsFragment.java
@@ -0,0 +1,93 @@
+/**
+ * Copyright (c) 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.tuner;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.systemui.R;
+
+import android.annotation.Nullable;
+import android.app.Fragment;
+import android.os.Bundle;
+import android.provider.Settings;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Switch;
+import android.widget.TextView;
+
+public class PowerNotificationControlsFragment extends Fragment {
+
+    private static final String KEY_SHOW_PNC = "show_importance_slider";
+
+    @Override
+    public void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+    }
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+            Bundle savedInstanceState) {
+        return inflater.inflate(R.layout.power_notification_controls_settings, container, false);
+    }
+
+    @Override
+    public void onViewCreated(View view, Bundle savedInstanceState) {
+        super.onViewCreated(view, savedInstanceState);
+        final View switchBar = view.findViewById(R.id.switch_bar);
+        final Switch switchWidget = (Switch) switchBar.findViewById(android.R.id.switch_widget);
+        final TextView switchText = (TextView) switchBar.findViewById(R.id.switch_text);
+        switchWidget.setChecked(isEnabled());
+        switchText.setText(isEnabled()
+                ? getString(R.string.switch_bar_on)
+                : getString(R.string.switch_bar_off));
+
+        switchWidget.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                boolean newState = !isEnabled();
+                MetricsLogger.action(getContext(),
+                        MetricsEvent.ACTION_TUNER_POWER_NOTIFICATION_CONTROLS, newState);
+                Settings.Secure.putInt(getContext().getContentResolver(),
+                        KEY_SHOW_PNC, newState ? 1 : 0);
+                switchWidget.setChecked(newState);
+                switchText.setText(newState
+                        ? getString(R.string.switch_bar_on)
+                        : getString(R.string.switch_bar_off));
+            }
+        });
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        MetricsLogger.visibility(
+                getContext(), MetricsEvent.TUNER_POWER_NOTIFICATION_CONTROLS, true);
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+        MetricsLogger.visibility(
+                getContext(), MetricsEvent.TUNER_POWER_NOTIFICATION_CONTROLS, false);
+    }
+
+    private boolean isEnabled() {
+        int setting = Settings.Secure.getInt(getContext().getContentResolver(), KEY_SHOW_PNC, 0);
+        return setting == 1;
+    }
+
+}
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index afea7f3..64b4842 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -2152,6 +2152,12 @@
     // User tried to dock an unresizable app.
     ACTION_WINDOW_DOCK_UNRESIZABLE = 391;
 
+    // System UI Tuner > Other > Power notification controls
+    TUNER_POWER_NOTIFICATION_CONTROLS = 392;
+
+    // System UI Tuner > Other > Power notification controls > Toggle on/off
+    ACTION_TUNER_POWER_NOTIFICATION_CONTROLS = 393;
+
     // Add new aosp constants above this line.
     // END OF AOSP CONSTANTS
   }
diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java
index f2b4e52..c1bacfa 100644
--- a/services/core/java/com/android/server/LockSettingsService.java
+++ b/services/core/java/com/android/server/LockSettingsService.java
@@ -261,7 +261,9 @@
                     showEncryptionNotification(userHandle);
                 } else {
                     UserInfo parent = mUserManager.getProfileParent(user.id);
-                    if (parent != null && mUserManager.isUserUnlocked(parent.getUserHandle())) {
+                    if (parent != null &&
+                            mUserManager.isUserUnlocked(parent.getUserHandle()) &&
+                            !mUserManager.isQuietModeEnabled(userHandle)) {
                         // Only show notifications for managed profiles once their parent
                         // user is unlocked.
                         showEncryptionNotificationForProfile(userHandle);
@@ -348,7 +350,8 @@
             UserInfo profile = profiles.get(i);
             if (profile.isManagedProfile()) {
                 UserHandle userHandle = profile.getUserHandle();
-                if (!mUserManager.isUserUnlocked(userHandle)) {
+                if (!mUserManager.isUserUnlocked(userHandle) &&
+                        !mUserManager.isQuietModeEnabled(userHandle)) {
                     showEncryptionNotificationForProfile(userHandle);
                 }
             }
@@ -702,6 +705,12 @@
             }
         };
 
+        // Check if the user is currently in quiet mode and start it otherwise
+        if (mUserManager.isQuietModeEnabled(new UserHandle(userId))
+                && mLockPatternUtils.isSeparateProfileChallengeEnabled(userId)) {
+            mUserManager.setQuietModeEnabled(userId, false);
+        }
+
         try {
             ActivityManagerNative.getDefault().unlockUser(userId, token, secret, listener);
         } catch (RemoteException e) {
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index 5ebb9a7..4292fcf 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -895,7 +895,10 @@
         synchronized (mService) {
             // Bail if already running unlocked, or if not running at all
             final UserState uss = mStartedUsers.get(userId);
-            if (uss == null) return false;
+            if (uss == null) {
+                progress.finish();
+                return false;
+            }
             switch (uss.state) {
                 case STATE_RUNNING_UNLOCKING:
                 case STATE_RUNNING_UNLOCKED:
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 1fb260d..dc81c65 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -2315,24 +2315,29 @@
             // For security and version matching reason, only consider
             // overlay packages if they reside in VENDOR_OVERLAY_DIR.
             File vendorOverlayDir = new File(VENDOR_OVERLAY_DIR);
-            scanDirTracedLI(vendorOverlayDir, PackageParser.PARSE_IS_SYSTEM
-                    | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags | SCAN_TRUSTED_OVERLAY, 0);
+            scanDirTracedLI(vendorOverlayDir, mDefParseFlags
+                    | PackageParser.PARSE_IS_SYSTEM
+                    | PackageParser.PARSE_IS_SYSTEM_DIR
+                    | PackageParser.PARSE_TRUSTED_OVERLAY, scanFlags | SCAN_TRUSTED_OVERLAY, 0);
 
             // Find base frameworks (resource packages without code).
-            scanDirTracedLI(frameworkDir, PackageParser.PARSE_IS_SYSTEM
+            scanDirTracedLI(frameworkDir, mDefParseFlags
+                    | PackageParser.PARSE_IS_SYSTEM
                     | PackageParser.PARSE_IS_SYSTEM_DIR
                     | PackageParser.PARSE_IS_PRIVILEGED,
                     scanFlags | SCAN_NO_DEX, 0);
 
             // Collected privileged system packages.
             final File privilegedAppDir = new File(Environment.getRootDirectory(), "priv-app");
-            scanDirTracedLI(privilegedAppDir, PackageParser.PARSE_IS_SYSTEM
+            scanDirTracedLI(privilegedAppDir, mDefParseFlags
+                    | PackageParser.PARSE_IS_SYSTEM
                     | PackageParser.PARSE_IS_SYSTEM_DIR
                     | PackageParser.PARSE_IS_PRIVILEGED, scanFlags, 0);
 
             // Collect ordinary system packages.
             final File systemAppDir = new File(Environment.getRootDirectory(), "app");
-            scanDirTracedLI(systemAppDir, PackageParser.PARSE_IS_SYSTEM
+            scanDirTracedLI(systemAppDir, mDefParseFlags
+                    | PackageParser.PARSE_IS_SYSTEM
                     | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);
 
             // Collect all vendor packages.
@@ -2342,12 +2347,14 @@
             } catch (IOException e) {
                 // failed to look up canonical path, continue with original one
             }
-            scanDirTracedLI(vendorAppDir, PackageParser.PARSE_IS_SYSTEM
+            scanDirTracedLI(vendorAppDir, mDefParseFlags
+                    | PackageParser.PARSE_IS_SYSTEM
                     | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);
 
             // Collect all OEM packages.
             final File oemAppDir = new File(Environment.getOemDirectory(), "app");
-            scanDirTracedLI(oemAppDir, PackageParser.PARSE_IS_SYSTEM
+            scanDirTracedLI(oemAppDir, mDefParseFlags
+                    | PackageParser.PARSE_IS_SYSTEM
                     | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);
 
             // Prune any system packages that no longer exist.
@@ -2428,10 +2435,12 @@
                         SystemClock.uptimeMillis());
                 scanDirTracedLI(mAppInstallDir, 0, scanFlags | SCAN_REQUIRE_KNOWN, 0);
 
-                scanDirTracedLI(mDrmAppPrivateInstallDir, PackageParser.PARSE_FORWARD_LOCK,
+                scanDirTracedLI(mDrmAppPrivateInstallDir, mDefParseFlags
+                        | PackageParser.PARSE_FORWARD_LOCK,
                         scanFlags | SCAN_REQUIRE_KNOWN, 0);
 
-                scanDirLI(mEphemeralInstallDir, PackageParser.PARSE_IS_EPHEMERAL,
+                scanDirLI(mEphemeralInstallDir, mDefParseFlags
+                        | PackageParser.PARSE_IS_EPHEMERAL,
                         scanFlags | SCAN_REQUIRE_KNOWN, 0);
 
                 /**
@@ -2476,7 +2485,7 @@
                         logCriticalInfo(Log.WARN, "Expected better " + packageName
                                 + " but never showed up; reverting to system");
 
-                        final int reparseFlags;
+                        int reparseFlags = mDefParseFlags;
                         if (FileUtils.contains(privilegedAppDir, scanFile)) {
                             reparseFlags = PackageParser.PARSE_IS_SYSTEM
                                     | PackageParser.PARSE_IS_SYSTEM_DIR
@@ -6501,7 +6510,7 @@
         return true;
     }
 
-    private void scanDirTracedLI(File dir, int parseFlags, int scanFlags, long currentTime) {
+    private void scanDirTracedLI(File dir, final int parseFlags, int scanFlags, long currentTime) {
         Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "scanDir");
         try {
             scanDirLI(dir, parseFlags, scanFlags, currentTime);
@@ -6510,7 +6519,7 @@
         }
     }
 
-    private void scanDirLI(File dir, int parseFlags, int scanFlags, long currentTime) {
+    private void scanDirLI(File dir, final int parseFlags, int scanFlags, long currentTime) {
         final File[] files = dir.listFiles();
         if (ArrayUtils.isEmpty(files)) {
             Log.d(TAG, "No files in app dir " + dir);
@@ -6576,7 +6585,7 @@
     }
 
     private void collectCertificatesLI(PackageSetting ps, PackageParser.Package pkg, File srcFile,
-            int parseFlags) throws PackageManagerException {
+            final int policyFlags) throws PackageManagerException {
         if (ps != null
                 && ps.codePath.equals(srcFile)
                 && ps.timeStamp == srcFile.lastModified()
@@ -6605,7 +6614,7 @@
         }
 
         try {
-            PackageParser.collectCertificates(pkg, parseFlags);
+            PackageParser.collectCertificates(pkg, policyFlags);
         } catch (PackageParserException e) {
             throw PackageManagerException.from(e);
         }
@@ -6615,8 +6624,8 @@
      *  Traces a package scan.
      *  @see #scanPackageLI(File, int, int, long, UserHandle)
      */
-    private PackageParser.Package scanPackageTracedLI(File scanFile, int parseFlags, int scanFlags,
-            long currentTime, UserHandle user) throws PackageManagerException {
+    private PackageParser.Package scanPackageTracedLI(File scanFile, final int parseFlags,
+            int scanFlags, long currentTime, UserHandle user) throws PackageManagerException {
         Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "scanPackage");
         try {
             return scanPackageLI(scanFile, parseFlags, scanFlags, currentTime, user);
@@ -6632,7 +6641,6 @@
     private PackageParser.Package scanPackageLI(File scanFile, int parseFlags, int scanFlags,
             long currentTime, UserHandle user) throws PackageManagerException {
         if (DEBUG_INSTALL) Slog.d(TAG, "Parsing: " + scanFile);
-        parseFlags |= mDefParseFlags;
         PackageParser pp = new PackageParser();
         pp.setSeparateProcesses(mSeparateProcesses);
         pp.setOnlyCoreApps(mOnlyCore);
@@ -6642,11 +6650,14 @@
             parseFlags |= PackageParser.PARSE_TRUSTED_OVERLAY;
         }
 
+        Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parsePackage");
         final PackageParser.Package pkg;
         try {
             pkg = pp.parsePackage(scanFile, parseFlags);
         } catch (PackageParserException e) {
             throw PackageManagerException.from(e);
+        } finally {
+            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
         }
 
         return scanPackageLI(pkg, scanFile, parseFlags, scanFlags, currentTime, user);
@@ -6657,7 +6668,7 @@
      *  @throws PackageManagerException on a parse error.
      */
     private PackageParser.Package scanPackageLI(PackageParser.Package pkg, File scanFile,
-            int parseFlags, int scanFlags, long currentTime, UserHandle user)
+            final int policyFlags, int scanFlags, long currentTime, UserHandle user)
             throws PackageManagerException {
         // If the package has children and this is the first dive in the function
         // we scan the package with the SCAN_CHECK_ONLY flag set to see whether all
@@ -6673,20 +6684,20 @@
         }
 
         // Scan the parent
-        PackageParser.Package scannedPkg = scanPackageInternalLI(pkg, scanFile, parseFlags,
+        PackageParser.Package scannedPkg = scanPackageInternalLI(pkg, scanFile, policyFlags,
                 scanFlags, currentTime, user);
 
         // Scan the children
         final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
         for (int i = 0; i < childCount; i++) {
             PackageParser.Package childPackage = pkg.childPackages.get(i);
-            scanPackageInternalLI(childPackage, scanFile, parseFlags, scanFlags,
+            scanPackageInternalLI(childPackage, scanFile, policyFlags, scanFlags,
                     currentTime, user);
         }
 
 
         if ((scanFlags & SCAN_CHECK_ONLY) != 0) {
-            return scanPackageLI(pkg, scanFile, parseFlags, scanFlags, currentTime, user);
+            return scanPackageLI(pkg, scanFile, policyFlags, scanFlags, currentTime, user);
         }
 
         return scannedPkg;
@@ -6697,7 +6708,7 @@
      *  @throws PackageManagerException on a parse error.
      */
     private PackageParser.Package scanPackageInternalLI(PackageParser.Package pkg, File scanFile,
-            int parseFlags, int scanFlags, long currentTime, UserHandle user)
+            int policyFlags, int scanFlags, long currentTime, UserHandle user)
             throws PackageManagerException {
         PackageSetting ps = null;
         PackageSetting updatedPkg;
@@ -6724,7 +6735,7 @@
             // may need to remove disabled child packages on the system partition
             // or may need to not add child packages if the parent apk is updated
             // on the data partition and no longer defines this child package.
-            if ((parseFlags & PackageParser.PARSE_IS_SYSTEM) != 0) {
+            if ((policyFlags & PackageParser.PARSE_IS_SYSTEM) != 0) {
                 // If this is a parent package for an updated system app and this system
                 // app got an OTA update which no longer defines some of the child packages
                 // we have to prune them from the disabled system packages.
@@ -6754,7 +6765,7 @@
 
         boolean updatedPkgBetter = false;
         // First check if this is a system package that may involve an update
-        if (updatedPkg != null && (parseFlags & PackageParser.PARSE_IS_SYSTEM) != 0) {
+        if (updatedPkg != null && (policyFlags & PackageParser.PARSE_IS_SYSTEM) != 0) {
             // If new package is not located in "/system/priv-app" (e.g. due to an OTA),
             // it needs to drop FLAG_PRIVILEGED.
             if (locationIsPrivileged(scanFile)) {
@@ -6836,17 +6847,17 @@
         if (updatedPkg != null) {
             // An updated system app will not have the PARSE_IS_SYSTEM flag set
             // initially
-            parseFlags |= PackageParser.PARSE_IS_SYSTEM;
+            policyFlags |= PackageParser.PARSE_IS_SYSTEM;
 
             // An updated privileged app will not have the PARSE_IS_PRIVILEGED
             // flag set initially
             if ((updatedPkg.pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0) {
-                parseFlags |= PackageParser.PARSE_IS_PRIVILEGED;
+                policyFlags |= PackageParser.PARSE_IS_PRIVILEGED;
             }
         }
 
         // Verify certificates against what was last scanned
-        collectCertificatesLI(ps, pkg, scanFile, parseFlags);
+        collectCertificatesLI(ps, pkg, scanFile, policyFlags);
 
         /*
          * A new system app appeared, but we already had a non-system one of the
@@ -6854,7 +6865,7 @@
          */
         boolean shouldHideSystemApp = false;
         if (updatedPkg == null && ps != null
-                && (parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) != 0 && !isSystemApp(ps)) {
+                && (policyFlags & PackageParser.PARSE_IS_SYSTEM_DIR) != 0 && !isSystemApp(ps)) {
             /*
              * Check to make sure the signatures match first. If they don't,
              * wipe the installed application and its data.
@@ -6902,16 +6913,16 @@
         // are kept in different files. (except for app in either system or
         // vendor path).
         // TODO grab this value from PackageSettings
-        if ((parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
+        if ((policyFlags & PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
             if (ps != null && !ps.codePath.equals(ps.resourcePath)) {
-                parseFlags |= PackageParser.PARSE_FORWARD_LOCK;
+                policyFlags |= PackageParser.PARSE_FORWARD_LOCK;
             }
         }
 
         // TODO: extend to support forward-locked splits
         String resourcePath = null;
         String baseResourcePath = null;
-        if ((parseFlags & PackageParser.PARSE_FORWARD_LOCK) != 0 && !updatedPkgBetter) {
+        if ((policyFlags & PackageParser.PARSE_FORWARD_LOCK) != 0 && !updatedPkgBetter) {
             if (ps != null && ps.resourcePathString != null) {
                 resourcePath = ps.resourcePathString;
                 baseResourcePath = ps.resourcePathString;
@@ -6934,7 +6945,7 @@
         pkg.setApplicationInfoSplitResourcePaths(pkg.splitCodePaths);
 
         // Note that we invoke the following method only if we are about to unpack an application
-        PackageParser.Package scannedPkg = scanPackageLI(pkg, parseFlags, scanFlags
+        PackageParser.Package scannedPkg = scanPackageLI(pkg, policyFlags, scanFlags
                 | SCAN_UPDATE_SIGNATURE, currentTime, user);
 
         /*
@@ -7576,8 +7587,9 @@
         return cpuAbiOverride;
     }
 
-    private PackageParser.Package scanPackageTracedLI(PackageParser.Package pkg, int parseFlags,
-            int scanFlags, long currentTime, UserHandle user) throws PackageManagerException {
+    private PackageParser.Package scanPackageTracedLI(PackageParser.Package pkg,
+            final int policyFlags, int scanFlags, long currentTime, UserHandle user)
+                    throws PackageManagerException {
         Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "scanPackage");
         // If the package has children and this is the first dive in the function
         // we recursively scan the package with the SCAN_CHECK_ONLY flag set to see
@@ -7595,12 +7607,12 @@
         final PackageParser.Package scannedPkg;
         try {
             // Scan the parent
-            scannedPkg = scanPackageLI(pkg, parseFlags, scanFlags, currentTime, user);
+            scannedPkg = scanPackageLI(pkg, policyFlags, scanFlags, currentTime, user);
             // Scan the children
             final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
             for (int i = 0; i < childCount; i++) {
                 PackageParser.Package childPkg = pkg.childPackages.get(i);
-                scanPackageLI(childPkg, parseFlags,
+                scanPackageLI(childPkg, policyFlags,
                         scanFlags, currentTime, user);
             }
         } finally {
@@ -7608,17 +7620,17 @@
         }
 
         if ((scanFlags & SCAN_CHECK_ONLY) != 0) {
-            return scanPackageTracedLI(pkg, parseFlags, scanFlags, currentTime, user);
+            return scanPackageTracedLI(pkg, policyFlags, scanFlags, currentTime, user);
         }
 
         return scannedPkg;
     }
 
-    private PackageParser.Package scanPackageLI(PackageParser.Package pkg, int parseFlags,
+    private PackageParser.Package scanPackageLI(PackageParser.Package pkg, final int policyFlags,
             int scanFlags, long currentTime, UserHandle user) throws PackageManagerException {
         boolean success = false;
         try {
-            final PackageParser.Package res = scanPackageDirtyLI(pkg, parseFlags, scanFlags,
+            final PackageParser.Package res = scanPackageDirtyLI(pkg, policyFlags, scanFlags,
                     currentTime, user);
             success = true;
             return res;
@@ -7632,8 +7644,8 @@
         }
     }
 
-    private PackageParser.Package scanPackageDirtyLI(PackageParser.Package pkg, int parseFlags,
-            int scanFlags, long currentTime, UserHandle user)
+    private PackageParser.Package scanPackageDirtyLI(PackageParser.Package pkg,
+            final int policyFlags, final int scanFlags, long currentTime, UserHandle user)
             throws PackageManagerException {
         final File scanFile = new File(pkg.codePath);
         if (pkg.applicationInfo.getCodePath() == null ||
@@ -7643,14 +7655,36 @@
                     "Code and resource paths haven't been set correctly");
         }
 
-        if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
+        // Apply policy
+        if ((policyFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
             pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
+            if (pkg.applicationInfo.isDirectBootAware()) {
+                // we're direct boot aware; set for all components
+                for (PackageParser.Service s : pkg.services) {
+                    s.info.encryptionAware = s.info.directBootAware = true;
+                }
+                for (PackageParser.Provider p : pkg.providers) {
+                    p.info.encryptionAware = p.info.directBootAware = true;
+                }
+                for (PackageParser.Activity a : pkg.activities) {
+                    a.info.encryptionAware = a.info.directBootAware = true;
+                }
+                for (PackageParser.Activity r : pkg.receivers) {
+                    r.info.encryptionAware = r.info.directBootAware = true;
+                }
+            }
         } else {
             // Only allow system apps to be flagged as core apps.
             pkg.coreApp = false;
+            // clear flags not applicable to regular apps
+            pkg.applicationInfo.privateFlags &=
+                    ~ApplicationInfo.PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE;
+            pkg.applicationInfo.privateFlags &=
+                    ~ApplicationInfo.PRIVATE_FLAG_DIRECT_BOOT_AWARE;
         }
+        pkg.mTrustedOverlay = (policyFlags&PackageParser.PARSE_TRUSTED_OVERLAY) != 0;
 
-        if ((parseFlags&PackageParser.PARSE_IS_PRIVILEGED) != 0) {
+        if ((policyFlags&PackageParser.PARSE_IS_PRIVILEGED) != 0) {
             pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
         }
 
@@ -7699,7 +7733,7 @@
         }
 
         if (DEBUG_PACKAGE_SCANNING) {
-            if ((parseFlags & PackageParser.PARSE_CHATTY) != 0)
+            if ((policyFlags & PackageParser.PARSE_CHATTY) != 0)
                 Log.d(TAG, "Scanning package " + pkg.packageName);
         }
 
@@ -7774,7 +7808,7 @@
                             + " for shared user failed");
                 }
                 if (DEBUG_PACKAGE_SCANNING) {
-                    if ((parseFlags & PackageParser.PARSE_CHATTY) != 0)
+                    if ((policyFlags & PackageParser.PARSE_CHATTY) != 0)
                         Log.d(TAG, "Shared UserID " + pkg.mSharedUserId + " (uid=" + suid.userId
                                 + "): packages=" + suid.packages);
                 }
@@ -7820,6 +7854,7 @@
                                     origPackage = null;
                                     continue;
                                 }
+                                // TODO: Add case when shared user id is added [b/28144775]
                             } else {
                                 if (DEBUG_UPGRADE) Log.v(TAG, "Renaming new package "
                                         + pkg.packageName + " to old name " + origPackage.name);
@@ -7886,7 +7921,7 @@
                 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
             }
 
-            if ((parseFlags&PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
+            if ((policyFlags&PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
                 // Check all shared libraries and map to their actual file path.
                 // We only do this here for apps not on a system dir, because those
                 // are the only ones that can fail an install due to this.  We
@@ -7907,7 +7942,7 @@
                     // over the latest parsed certs.
                     pkgSetting.signatures.mSignatures = pkg.mSignatures;
                 } else {
-                    if ((parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
+                    if ((policyFlags & PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
                         throw new PackageManagerException(INSTALL_FAILED_UPDATE_INCOMPATIBLE,
                                 "Package " + pkg.packageName + " upgrade keys do not match the "
                                 + "previously installed version");
@@ -7925,7 +7960,7 @@
                     // over the latest parsed certs.
                     pkgSetting.signatures.mSignatures = pkg.mSignatures;
                 } catch (PackageManagerException e) {
-                    if ((parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
+                    if ((policyFlags & PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
                         throw e;
                     }
                     // The signature has changed, but this package is in the system
@@ -8114,7 +8149,7 @@
 
         // Only privileged apps and updated privileged apps can add child packages.
         if (pkg.childPackages != null && !pkg.childPackages.isEmpty()) {
-            if ((parseFlags & PARSE_IS_PRIVILEGED) == 0) {
+            if ((policyFlags & PARSE_IS_PRIVILEGED) == 0) {
                 throw new PackageManagerException("Only privileged apps and updated "
                         + "privileged apps can add child packages. Ignoring package "
                         + pkg.packageName);
@@ -8240,7 +8275,7 @@
             } else if (pkgSetting.firstInstallTime == 0) {
                 // We need *something*.  Take time time stamp of the file.
                 pkgSetting.firstInstallTime = pkgSetting.lastUpdateTime = scanFileTime;
-            } else if ((parseFlags&PackageParser.PARSE_IS_SYSTEM_DIR) != 0) {
+            } else if ((policyFlags&PackageParser.PARSE_IS_SYSTEM_DIR) != 0) {
                 if (scanFileTime != pkgSetting.timeStamp) {
                     // A package on the system image has changed; consider this
                     // to be an update.
@@ -8283,7 +8318,7 @@
                                 p.info.authority = p.info.authority + ";" + names[j];
                             }
                             if (DEBUG_PACKAGE_SCANNING) {
-                                if ((parseFlags & PackageParser.PARSE_CHATTY) != 0)
+                                if ((policyFlags & PackageParser.PARSE_CHATTY) != 0)
                                     Log.d(TAG, "Registered content provider: " + names[j]
                                             + ", className = " + p.info.name + ", isSyncable = "
                                             + p.info.isSyncable);
@@ -8298,7 +8333,7 @@
                         }
                     }
                 }
-                if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
+                if ((policyFlags&PackageParser.PARSE_CHATTY) != 0) {
                     if (r == null) {
                         r = new StringBuilder(256);
                     } else {
@@ -8318,7 +8353,7 @@
                 s.info.processName = fixProcessName(pkg.applicationInfo.processName,
                         s.info.processName, pkg.applicationInfo.uid);
                 mServices.addService(s);
-                if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
+                if ((policyFlags&PackageParser.PARSE_CHATTY) != 0) {
                     if (r == null) {
                         r = new StringBuilder(256);
                     } else {
@@ -8338,7 +8373,7 @@
                 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
                         a.info.processName, pkg.applicationInfo.uid);
                 mReceivers.addActivity(a, "receiver");
-                if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
+                if ((policyFlags&PackageParser.PARSE_CHATTY) != 0) {
                     if (r == null) {
                         r = new StringBuilder(256);
                     } else {
@@ -8358,7 +8393,7 @@
                 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
                         a.info.processName, pkg.applicationInfo.uid);
                 mActivities.addActivity(a, "activity");
-                if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
+                if ((policyFlags&PackageParser.PARSE_CHATTY) != 0) {
                     if (r == null) {
                         r = new StringBuilder(256);
                     } else {
@@ -8378,7 +8413,7 @@
                 PackageParser.PermissionGroup cur = mPermissionGroups.get(pg.info.name);
                 if (cur == null) {
                     mPermissionGroups.put(pg.info.name, pg);
-                    if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
+                    if ((policyFlags&PackageParser.PARSE_CHATTY) != 0) {
                         if (r == null) {
                             r = new StringBuilder(256);
                         } else {
@@ -8390,7 +8425,7 @@
                     Slog.w(TAG, "Permission group " + pg.info.name + " from package "
                             + pg.info.packageName + " ignored: original from "
                             + cur.info.packageName);
-                    if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
+                    if ((policyFlags&PackageParser.PARSE_CHATTY) != 0) {
                         if (r == null) {
                             r = new StringBuilder(256);
                         } else {
@@ -8469,7 +8504,7 @@
                             bp.uid = pkg.applicationInfo.uid;
                             bp.sourcePackage = p.info.packageName;
                             p.info.flags |= PermissionInfo.FLAG_INSTALLED;
-                            if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
+                            if ((policyFlags&PackageParser.PARSE_CHATTY) != 0) {
                                 if (r == null) {
                                     r = new StringBuilder(256);
                                 } else {
@@ -8488,7 +8523,7 @@
                                 + p.info.packageName + " ignored: original from "
                                 + bp.sourcePackage);
                     }
-                } else if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
+                } else if ((policyFlags&PackageParser.PARSE_CHATTY) != 0) {
                     if (r == null) {
                         r = new StringBuilder(256);
                     } else {
@@ -8523,7 +8558,7 @@
                 // need other information about the application, like the ABI and what not ?
                 a.info.nativeLibraryDir = pkg.applicationInfo.nativeLibraryDir;
                 mInstrumentation.put(a.getComponentName(), a);
-                if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
+                if ((policyFlags&PackageParser.PARSE_CHATTY) != 0) {
                     if (r == null) {
                         r = new StringBuilder(256);
                     } else {
@@ -13538,8 +13573,8 @@
     /*
      * Install a non-existing package.
      */
-    private void installNewPackageLIF(PackageParser.Package pkg, int parseFlags, int scanFlags,
-            UserHandle user, String installerPackageName, String volumeUuid,
+    private void installNewPackageLIF(PackageParser.Package pkg, final int policyFlags,
+            int scanFlags, UserHandle user, String installerPackageName, String volumeUuid,
             PackageInstalledInfo res) {
         Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installNewPackage");
 
@@ -13568,7 +13603,7 @@
         }
 
         try {
-            PackageParser.Package newPackage = scanPackageTracedLI(pkg, parseFlags, scanFlags,
+            PackageParser.Package newPackage = scanPackageTracedLI(pkg, policyFlags, scanFlags,
                     System.currentTimeMillis(), user);
 
             updateSettingsLI(newPackage, installerPackageName, null, res, user);
@@ -13625,9 +13660,9 @@
         return false;
     }
 
-    private void replacePackageLIF(PackageParser.Package pkg, int parseFlags, int scanFlags,
+    private void replacePackageLIF(PackageParser.Package pkg, final int policyFlags, int scanFlags,
             UserHandle user, String installerPackageName, PackageInstalledInfo res) {
-        final boolean isEphemeral = (parseFlags & PackageParser.PARSE_IS_EPHEMERAL) != 0;
+        final boolean isEphemeral = (policyFlags & PackageParser.PARSE_IS_EPHEMERAL) != 0;
 
         final PackageParser.Package oldPackage;
         final String pkgName = pkg.packageName;
@@ -13715,10 +13750,18 @@
 
         boolean sysPkg = (isSystemApp(oldPackage));
         if (sysPkg) {
-            replaceSystemPackageLIF(oldPackage, pkg, parseFlags, scanFlags,
+            // Set the system/privileged flags as needed
+            final boolean privileged =
+                    (oldPackage.applicationInfo.privateFlags
+                            & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0;
+            final int systemPolicyFlags = policyFlags
+                    | PackageParser.PARSE_IS_SYSTEM
+                    | (privileged ? PackageParser.PARSE_IS_PRIVILEGED : 0);
+
+            replaceSystemPackageLIF(oldPackage, pkg, systemPolicyFlags, scanFlags,
                     user, allUsers, installerPackageName, res);
         } else {
-            replaceNonSystemPackageLIF(oldPackage, pkg, parseFlags, scanFlags,
+            replaceNonSystemPackageLIF(oldPackage, pkg, policyFlags, scanFlags,
                     user, allUsers, installerPackageName, res);
         }
     }
@@ -13733,7 +13776,7 @@
     }
 
     private void replaceNonSystemPackageLIF(PackageParser.Package deletedPackage,
-            PackageParser.Package pkg, int parseFlags, int scanFlags, UserHandle user,
+            PackageParser.Package pkg, final int policyFlags, int scanFlags, UserHandle user,
             int[] allUsers, String installerPackageName, PackageInstalledInfo res) {
         if (DEBUG_INSTALL) Slog.d(TAG, "replaceNonSystemPackageLI: new=" + pkg + ", old="
                 + deletedPackage);
@@ -13775,7 +13818,7 @@
             clearAppProfilesLIF(pkg);
 
             try {
-                final PackageParser.Package newPackage = scanPackageTracedLI(pkg, parseFlags,
+                final PackageParser.Package newPackage = scanPackageTracedLI(pkg, policyFlags,
                         scanFlags | SCAN_UPDATE_TIME, System.currentTimeMillis(), user);
                 updateSettingsLI(newPackage, installerPackageName, allUsers, res, user);
 
@@ -13872,20 +13915,13 @@
     }
 
     private void replaceSystemPackageLIF(PackageParser.Package deletedPackage,
-            PackageParser.Package pkg, int parseFlags, int scanFlags, UserHandle user,
+            PackageParser.Package pkg, final int policyFlags, int scanFlags, UserHandle user,
             int[] allUsers, String installerPackageName, PackageInstalledInfo res) {
         if (DEBUG_INSTALL) Slog.d(TAG, "replaceSystemPackageLI: new=" + pkg
                 + ", old=" + deletedPackage);
 
         final boolean disabledSystem;
 
-        // Set the system/privileged flags as needed
-        parseFlags |= PackageParser.PARSE_IS_SYSTEM;
-        if ((deletedPackage.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED)
-                != 0) {
-            parseFlags |= PackageParser.PARSE_IS_PRIVILEGED;
-        }
-
         // Remove existing system package
         removePackageLI(deletedPackage, true);
 
@@ -13914,7 +13950,7 @@
         PackageParser.Package newPackage = null;
         try {
             // Add the package to the internal data structures
-            newPackage = scanPackageTracedLI(pkg, parseFlags, scanFlags, 0, user);
+            newPackage = scanPackageTracedLI(pkg, policyFlags, scanFlags, 0, user);
 
             // Set the update and install times
             PackageSetting deletedPkgSetting = (PackageSetting) deletedPackage.mExtras;
@@ -13967,7 +14003,7 @@
             }
             // Add back the old system package
             try {
-                scanPackageTracedLI(deletedPackage, parseFlags, SCAN_UPDATE_SIGNATURE, 0, user);
+                scanPackageTracedLI(deletedPackage, policyFlags, SCAN_UPDATE_SIGNATURE, 0, user);
             } catch (PackageManagerException e) {
                 Slog.e(TAG, "Failed to restore original package: " + e.getMessage());
             }
@@ -15296,7 +15332,10 @@
 
         // Install the system package
         if (DEBUG_REMOVE) Slog.d(TAG, "Re-installing system package: " + disabledPs);
-        int parseFlags = PackageParser.PARSE_MUST_BE_APK | PackageParser.PARSE_IS_SYSTEM;
+        int parseFlags = mDefParseFlags
+                | PackageParser.PARSE_MUST_BE_APK
+                | PackageParser.PARSE_IS_SYSTEM
+                | PackageParser.PARSE_IS_SYSTEM_DIR;
         if (locationIsPrivileged(disabledPs.codePath)) {
             parseFlags |= PackageParser.PARSE_IS_PRIVILEGED;
         }
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index ac6510a..0ac5c1f 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -907,6 +907,16 @@
         }
     }
 
+    public void cleanupBitmapsForPackage(@UserIdInt int userId, String packageName) {
+        final File packagePath = new File(getUserBitmapFilePath(userId), packageName);
+        if (!packagePath.isDirectory()) {
+            return;
+        }
+        if (!(FileUtils.deleteContents(packagePath) && packagePath.delete())) {
+            Slog.w(TAG, "Unable to remove directory " + packagePath);
+        }
+    }
+
     @VisibleForTesting
     static class FileOutputStreamWithPath extends FileOutputStream {
         private final File mFile;
@@ -1572,7 +1582,7 @@
 
         // First, remove the package from the package list (if the package is a publisher).
         if (packageUserId == owningUserId) {
-            if (mUser.removePackage(packageName) != null) {
+            if (mUser.removePackage(this, packageName) != null) {
                 doNotify = true;
             }
         }
@@ -2084,11 +2094,11 @@
             pw.println(mIconPersistFormat);
             pw.print("    Icon quality: ");
             pw.println(mIconPersistQuality);
-            pw.print("    saveDelayMillis:");
+            pw.print("    saveDelayMillis: ");
             pw.println(mSaveDelayMillis);
-            pw.print("    resetInterval:");
+            pw.print("    resetInterval: ");
             pw.println(mResetInterval);
-            pw.print("    maxUpdatesPerInterval:");
+            pw.print("    maxUpdatesPerInterval: ");
             pw.println(mMaxUpdatesPerInterval);
             pw.print("    maxDynamicShortcuts:");
             pw.println(mMaxDynamicShortcuts);
@@ -2416,7 +2426,6 @@
         return mPackageManagerInternal;
     }
 
-    @VisibleForTesting
     File getUserBitmapFilePath(@UserIdInt int userId) {
         return new File(injectUserDataPath(userId), DIRECTORY_BITMAPS);
     }
diff --git a/services/core/java/com/android/server/pm/ShortcutUser.java b/services/core/java/com/android/server/pm/ShortcutUser.java
index 593f607..0b8c3a2 100644
--- a/services/core/java/com/android/server/pm/ShortcutUser.java
+++ b/services/core/java/com/android/server/pm/ShortcutUser.java
@@ -18,6 +18,7 @@
 import android.annotation.NonNull;
 import android.annotation.UserIdInt;
 import android.content.ComponentName;
+import android.text.format.Formatter;
 import android.util.ArrayMap;
 import android.util.Slog;
 
@@ -29,6 +30,7 @@
 import org.xmlpull.v1.XmlPullParserException;
 import org.xmlpull.v1.XmlSerializer;
 
+import java.io.File;
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.util.function.Consumer;
@@ -103,8 +105,12 @@
         return mPackages;
     }
 
-    public ShortcutPackage removePackage(@NonNull String packageName) {
-        return mPackages.remove(packageName);
+    public ShortcutPackage removePackage(@NonNull ShortcutService s, @NonNull String packageName) {
+        final ShortcutPackage removed = mPackages.remove(packageName);
+
+        s.cleanupBitmapsForPackage(mUserId, packageName);
+
+        return removed;
     }
 
     public ArrayMap<PackageWithUser, ShortcutLauncher> getAllLaunchers() {
@@ -279,18 +285,51 @@
         pw.print(mUserId);
         pw.println();
 
+        prefix += prefix + "  ";
+
         pw.print(prefix);
-        pw.print("  ");
         pw.print("Default launcher: ");
         pw.print(mLauncherComponent);
         pw.println();
 
         for (int i = 0; i < mLaunchers.size(); i++) {
-            mLaunchers.valueAt(i).dump(s, pw, prefix + "  ");
+            mLaunchers.valueAt(i).dump(s, pw, prefix);
         }
 
         for (int i = 0; i < mPackages.size(); i++) {
-            mPackages.valueAt(i).dump(s, pw, prefix + "  ");
+            mPackages.valueAt(i).dump(s, pw, prefix);
         }
+
+        pw.println();
+        pw.print(prefix);
+        pw.println("Bitmap directories: ");
+        dumpDirectorySize(s, pw, prefix + "  ", s.getUserBitmapFilePath(mUserId));
+    }
+
+    private void dumpDirectorySize(@NonNull ShortcutService s, @NonNull PrintWriter pw,
+            @NonNull String prefix, File path) {
+        int numFiles = 0;
+        long size = 0;
+        final File[] children = path.listFiles();
+        if (children != null) {
+            for (File child : path.listFiles()) {
+                if (child.isFile()) {
+                    numFiles++;
+                    size += child.length();
+                } else if (child.isDirectory()) {
+                    dumpDirectorySize(s, pw, prefix + "  ", child);
+                }
+            }
+        }
+        pw.print(prefix);
+        pw.print("Path: ");
+        pw.print(path.getName());
+        pw.print("/ has ");
+        pw.print(numFiles);
+        pw.print(" files, size=");
+        pw.print(size);
+        pw.print(" (");
+        pw.print(Formatter.formatFileSize(s.mContext, size));
+        pw.println(")");
     }
 }
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 60ea254..9b918f3 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -17,6 +17,9 @@
 
 package com.android.server.pm;
 
+import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
+import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
+
 import android.Manifest;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -27,10 +30,12 @@
 import android.app.ActivityManagerNative;
 import android.app.IActivityManager;
 import android.app.IStopUserCallback;
+import android.app.KeyguardManager;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.IntentSender;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.UserInfo;
@@ -693,6 +698,37 @@
     }
 
     @Override
+    public boolean trySetQuietModeDisabled(int userHandle, IntentSender target) {
+        if (mContext.getSystemService(StorageManager.class).isUserKeyUnlocked(userHandle)
+                || !mLockPatternUtils.isSecure(userHandle)
+                || !mLockPatternUtils.isSeparateProfileChallengeEnabled(userHandle)) {
+            // if the user is already unlocked, no need to show a profile challenge
+            setQuietModeEnabled(userHandle, false);
+            return true;
+        }
+
+        long identity = Binder.clearCallingIdentity();
+        try {
+            // otherwise, we show a profile challenge to trigger decryption of the user
+            final KeyguardManager km = (KeyguardManager) mContext.getSystemService(
+                    Context.KEYGUARD_SERVICE);
+            final Intent unlockIntent = km.createConfirmDeviceCredentialIntent(null, null,
+                    userHandle);
+            if (unlockIntent == null) {
+                return false;
+            }
+            if (target != null) {
+                unlockIntent.putExtra(Intent.EXTRA_INTENT, target);
+            }
+            unlockIntent.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+            mContext.startActivity(unlockIntent);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+        return false;
+    }
+
+    @Override
     public void setUserEnabled(int userId) {
         checkManageUsersPermission("enable user");
         synchronized (mPackagesLock) {
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 ce02a79..d20d5fa 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java
@@ -15,9 +15,36 @@
  */
 package com.android.server.pm;
 
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllDynamic;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllDynamicOrPinned;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllHaveIcon;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllHaveIconFile;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllHaveIconResId;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllHaveIntents;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllHaveTitle;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllKeyFieldsOnly;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllNotHaveIntents;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllNotHaveTitle;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllNotKeyFieldsOnly;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllPinned;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllUnique;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertBitmapSize;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertBundleEmpty;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertCallbackNotReceived;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertCallbackReceived;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertDynamicAndPinned;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertDynamicOnly;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertExpectException;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertShortcutIds;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.hashSet;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.list;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.makeBundle;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.pfdToBitmap;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.resetAll;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.set;
+
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyList;
 import static org.mockito.Matchers.anyString;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.doAnswer;
@@ -27,7 +54,6 @@
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
-import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.*;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -57,13 +83,11 @@
 import android.graphics.BitmapFactory;
 import android.graphics.drawable.Icon;
 import android.net.Uri;
-import android.os.BaseBundle;
 import android.os.Bundle;
 import android.os.FileUtils;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Parcel;
-import android.os.ParcelFileDescriptor;
 import android.os.PersistableBundle;
 import android.os.Process;
 import android.os.UserHandle;
@@ -71,7 +95,6 @@
 import android.test.InstrumentationTestCase;
 import android.test.mock.MockContext;
 import android.test.suitebuilder.annotation.SmallTest;
-import android.util.ArraySet;
 import android.util.Log;
 import android.util.Pair;
 import android.util.SparseArray;
@@ -84,9 +107,6 @@
 import com.android.server.pm.ShortcutService.ConfigConstants;
 import com.android.server.pm.ShortcutService.FileOutputStreamWithPath;
 import com.android.server.pm.ShortcutUser.PackageWithUser;
-import com.android.server.testutis.TestUtils;
-
-import libcore.io.IoUtils;
 
 import org.junit.Assert;
 import org.mockito.ArgumentCaptor;
@@ -98,8 +118,6 @@
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
@@ -4018,24 +4036,33 @@
         checkCanRestoreTo(false, spi2, 11, "x", "sig2x", "sig1", "y");
     }
 
+    private boolean bitmapDirectoryExists(String packageName, int userId) {
+        final File path = new File(mService.getUserBitmapFilePath(userId), packageName);
+        return path.isDirectory();
+    }
+
     public void testHandlePackageDelete() {
+        final Icon bmp32x32 = Icon.createWithBitmap(BitmapFactory.decodeResource(
+                getTestContext().getResources(), R.drawable.black_32x32));
         setCaller(CALLING_PACKAGE_1, USER_0);
-        assertTrue(mManager.addDynamicShortcuts(list(makeShortcut("s1"))));
+        assertTrue(mManager.addDynamicShortcuts(list(
+                makeShortcutWithIcon("s1", bmp32x32), makeShortcutWithIcon("s2", bmp32x32)
+        )));
 
         setCaller(CALLING_PACKAGE_2, USER_0);
-        assertTrue(mManager.addDynamicShortcuts(list(makeShortcut("s1"))));
+        assertTrue(mManager.addDynamicShortcuts(list(makeShortcutWithIcon("s1", bmp32x32))));
 
         setCaller(CALLING_PACKAGE_3, USER_0);
-        assertTrue(mManager.addDynamicShortcuts(list(makeShortcut("s1"))));
+        assertTrue(mManager.addDynamicShortcuts(list(makeShortcutWithIcon("s1", bmp32x32))));
 
         setCaller(CALLING_PACKAGE_1, USER_10);
-        assertTrue(mManager.addDynamicShortcuts(list(makeShortcut("s1"))));
+        assertTrue(mManager.addDynamicShortcuts(list(makeShortcutWithIcon("s1", bmp32x32))));
 
         setCaller(CALLING_PACKAGE_2, USER_10);
-        assertTrue(mManager.addDynamicShortcuts(list(makeShortcut("s1"))));
+        assertTrue(mManager.addDynamicShortcuts(list(makeShortcutWithIcon("s1", bmp32x32))));
 
         setCaller(CALLING_PACKAGE_3, USER_10);
-        assertTrue(mManager.addDynamicShortcuts(list(makeShortcut("s1"))));
+        assertTrue(mManager.addDynamicShortcuts(list(makeShortcutWithIcon("s1", bmp32x32))));
 
         assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_0));
         assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_0));
@@ -4044,6 +4071,13 @@
         assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_10));
         assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_3, "s1", USER_10));
 
+        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_0));
+        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_0));
+        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_0));
+        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_10));
+        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_10));
+        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_10));
+
         uninstallPackage(USER_0, CALLING_PACKAGE_1);
         mService.mPackageMonitor.onReceive(getTestContext(),
                 genPackageDeleteIntent(CALLING_PACKAGE_1, USER_0));
@@ -4055,6 +4089,13 @@
         assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_10));
         assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_3, "s1", USER_10));
 
+        assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_0));
+        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_0));
+        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_0));
+        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_10));
+        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_10));
+        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_10));
+
         uninstallPackage(USER_10, CALLING_PACKAGE_2);
         mService.mPackageMonitor.onReceive(getTestContext(),
                 genPackageDeleteIntent(CALLING_PACKAGE_2, USER_10));
@@ -4066,6 +4107,13 @@
         assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_10));
         assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_3, "s1", USER_10));
 
+        assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_0));
+        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_0));
+        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_0));
+        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_10));
+        assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_10));
+        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_10));
+
         mInjectedPackages.remove(CALLING_PACKAGE_1);
         mInjectedPackages.remove(CALLING_PACKAGE_3);
 
@@ -4078,6 +4126,13 @@
         assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_10));
         assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_3, "s1", USER_10));
 
+        assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_0));
+        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_0));
+        assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_0));
+        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_10));
+        assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_10));
+        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_10));
+
         mService.handleUnlockUser(USER_10);
 
         assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_0));
@@ -4086,6 +4141,13 @@
         assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_10));
         assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_10));
         assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_3, "s1", USER_10));
+
+        assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_0));
+        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_0));
+        assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_0));
+        assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_10));
+        assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_10));
+        assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_10));
     }
 
     private void backupAndRestore() {