Cleanup zen rule instances.

1. When a user revokes zen access
2. When a user clears data

Bug: 25472361
Change-Id: Ia439a7c2bd6dc07a60a374caf4157508131e3578
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index c1d5b19..c504ce3 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -93,6 +93,7 @@
     AutomaticZenRule addAutomaticZenRule(in AutomaticZenRule automaticZenRule);
     boolean updateAutomaticZenRule(in AutomaticZenRule automaticZenRule);
     boolean removeAutomaticZenRule(String id);
+    boolean removeAutomaticZenRules(String packageName);
 
     byte[] getBackupPayload(int user);
     void applyRestore(in byte[] payload, int user);
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index 3eb3e0f..89610e9 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -470,6 +470,20 @@
     }
 
     /**
+     * Deletes all automatic zen rules owned by the given package.
+     *
+     * @hide
+     */
+    public boolean removeAutomaticZenRules(String packageName) {
+        INotificationManager service = getService();
+        try {
+            return service.removeAutomaticZenRules(packageName);
+        } catch (RemoteException e) {
+        }
+        return false;
+    }
+
+    /**
      * Checks the ability to read/modify notification policy for the calling package.
      *
      * <p>
diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java
index b3399d0..541623d 100644
--- a/core/java/android/service/notification/ZenModeConfig.java
+++ b/core/java/android/service/notification/ZenModeConfig.java
@@ -1110,7 +1110,7 @@
             if (!Objects.equals(id, to.id)) {
                 d.addLine(item, "id", id, to.id);
             }
-            if (creationTime == to.creationTime) {
+            if (creationTime != to.creationTime) {
                 d.addLine(item, "creationTime", creationTime, to.creationTime);
             }
         }
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index bbf8652..f6dee89 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -5386,6 +5386,11 @@
                     removeUriPermissionsForPackageLocked(packageName, userId, true);
                 }
 
+                // Remove all zen rules created by this package; revoke it's zen access.
+                INotificationManager inm = NotificationManager.getService();
+                inm.removeAutomaticZenRules(packageName);
+                inm.setNotificationPolicyAccessGranted(packageName, false);
+
                 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
                         Uri.fromParts("package", packageName, null));
                 intent.putExtra(Intent.EXTRA_UID, pkgUid);
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 38893b8..e0b7370 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -1634,6 +1634,14 @@
         }
 
         @Override
+        public boolean removeAutomaticZenRules(String packageName) throws RemoteException {
+            Preconditions.checkNotNull(packageName, "Package name is null");
+            enforceSystemOrSystemUI("removeAutomaticZenRules");
+
+            return mZenModeHelper.removeAutomaticZenRules(packageName, "removeAutomaticZenRules");
+        }
+
+        @Override
         public void setInterruptionFilter(String pkg, int filter) throws RemoteException {
             enforcePolicyAccess(pkg, "setInterruptionFilter");
             final int zen = NotificationManager.zenModeFromInterruptionFilter(filter, -1);
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index dbdc3f4..3c891df 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -41,6 +41,7 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
+import android.os.Process;
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.provider.Settings.Global;
@@ -274,7 +275,7 @@
             newConfig = mConfig.copy();
         }
         final String ruleId = automaticZenRule.getId();
-        ZenModeConfig.ZenRule rule = new ZenModeConfig.ZenRule();
+        ZenModeConfig.ZenRule rule;
         if (ruleId == null) {
             throw new IllegalArgumentException("Rule doesn't exist");
         } else {
@@ -307,13 +308,32 @@
         return setConfig(newConfig, reason, true);
     }
 
+    public boolean removeAutomaticZenRules(String packageName, String reason) {
+        ZenModeConfig newConfig;
+        synchronized (mConfig) {
+            if (mConfig == null) return false;
+            newConfig = mConfig.copy();
+        }
+        for (int i = newConfig.automaticRules.size() - 1; i >= 0; i--) {
+            ZenRule rule = newConfig.automaticRules.get(newConfig.automaticRules.keyAt(i));
+            if (rule.component.getPackageName().equals(packageName)
+                    && canManageAutomaticZenRule(rule)) {
+                newConfig.automaticRules.removeAt(i);
+            }
+        }
+        return setConfig(newConfig, reason, true);
+    }
+
     public boolean canManageAutomaticZenRule(ZenRule rule) {
-        if (mContext.checkCallingPermission(android.Manifest.permission.MANAGE_NOTIFICATIONS)
+        final int callingUid = Binder.getCallingUid();
+        if (callingUid == 0 || callingUid == Process.SYSTEM_UID) {
+            return true;
+        } else if (mContext.checkCallingPermission(android.Manifest.permission.MANAGE_NOTIFICATIONS)
                 == PackageManager.PERMISSION_GRANTED) {
             return true;
         } else {
-            String[] packages = mContext.getPackageManager().getPackagesForUid(
-                    Binder.getCallingUid());
+            String[] packages =
+                    mContext.getPackageManager().getPackagesForUid(Binder.getCallingUid());
             if (packages != null) {
                 final int packageCount = packages.length;
                 for (int i = 0; i < packageCount; i++) {