Store DND rule owners

Test: uiservicestest, cts
Bug: 189332346
Bug: 235823407

Change-Id: Ie546c15c25fcbd193b67cb997220f075691e9bab
Merged-In: Ie546c15c25fcbd193b67cb997220f075691e9bab
diff --git a/core/java/android/app/AutomaticZenRule.java b/core/java/android/app/AutomaticZenRule.java
index 7180c01..a6cd6d5 100644
--- a/core/java/android/app/AutomaticZenRule.java
+++ b/core/java/android/app/AutomaticZenRule.java
@@ -45,6 +45,7 @@
     private long creationTime;
     private ZenPolicy mZenPolicy;
     private boolean mModified = false;
+    private String mPkg;
 
     /**
      * Creates an automatic zen rule.
@@ -123,6 +124,7 @@
         creationTime = source.readLong();
         mZenPolicy = source.readParcelable(null);
         mModified = source.readInt() == ENABLED;
+        mPkg = source.readString();
     }
 
     /**
@@ -244,6 +246,20 @@
         this.configurationActivity = componentName;
     }
 
+    /**
+     * @hide
+     */
+    public void setPackageName(String pkgName) {
+        mPkg = pkgName;
+    }
+
+    /**
+     * @hide
+     */
+    public String getPackageName() {
+        return mPkg;
+    }
+
     @Override
     public int describeContents() {
         return 0;
@@ -265,6 +281,7 @@
         dest.writeLong(creationTime);
         dest.writeParcelable(mZenPolicy, 0);
         dest.writeInt(mModified ? ENABLED : DISABLED);
+        dest.writeString(mPkg);
     }
 
     @Override
@@ -273,6 +290,7 @@
                 .append("enabled=").append(enabled)
                 .append(",name=").append(name)
                 .append(",interruptionFilter=").append(interruptionFilter)
+                .append(",pkg=").append(mPkg)
                 .append(",conditionId=").append(conditionId)
                 .append(",owner=").append(owner)
                 .append(",configActivity=").append(configurationActivity)
@@ -294,13 +312,14 @@
                 && Objects.equals(other.owner, owner)
                 && Objects.equals(other.mZenPolicy, mZenPolicy)
                 && Objects.equals(other.configurationActivity, configurationActivity)
+                && Objects.equals(other.mPkg, mPkg)
                 && other.creationTime == creationTime;
     }
 
     @Override
     public int hashCode() {
         return Objects.hash(enabled, name, interruptionFilter, conditionId, owner,
-                configurationActivity, mZenPolicy, mModified, creationTime);
+                configurationActivity, mZenPolicy, mModified, creationTime, mPkg);
     }
 
     public static final @android.annotation.NonNull Parcelable.Creator<AutomaticZenRule> CREATOR
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index e57738f..3661876 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -182,7 +182,7 @@
     void setNotificationPolicyAccessGrantedForUser(String pkg, int userId, boolean granted);
     AutomaticZenRule getAutomaticZenRule(String id);
     List<ZenModeConfig.ZenRule> getZenRules();
-    String addAutomaticZenRule(in AutomaticZenRule automaticZenRule);
+    String addAutomaticZenRule(in AutomaticZenRule automaticZenRule, String pkg);
     boolean updateAutomaticZenRule(String id, in AutomaticZenRule automaticZenRule);
     boolean removeAutomaticZenRule(String id);
     boolean removeAutomaticZenRules(String packageName);
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index dd39376..c84490a 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -923,10 +923,12 @@
             List<ZenModeConfig.ZenRule> rules = service.getZenRules();
             Map<String, AutomaticZenRule> ruleMap = new HashMap<>();
             for (ZenModeConfig.ZenRule rule : rules) {
-                ruleMap.put(rule.id, new AutomaticZenRule(rule.name, rule.component,
+                AutomaticZenRule azr = new AutomaticZenRule(rule.name, rule.component,
                         rule.configurationActivity, rule.conditionId, rule.zenPolicy,
                         zenModeToInterruptionFilter(rule.zenMode), rule.enabled,
-                        rule.creationTime));
+                        rule.creationTime);
+                azr.setPackageName(rule.pkg);
+                ruleMap.put(rule.id, azr);
             }
             return ruleMap;
         } catch (RemoteException e) {
@@ -967,7 +969,7 @@
     public String addAutomaticZenRule(AutomaticZenRule automaticZenRule) {
         INotificationManager service = getService();
         try {
-            return service.addAutomaticZenRule(automaticZenRule);
+            return service.addAutomaticZenRule(automaticZenRule, mContext.getPackageName());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java
index 93bcdbf..e473417 100644
--- a/core/java/android/service/notification/ZenModeConfig.java
+++ b/core/java/android/service/notification/ZenModeConfig.java
@@ -43,6 +43,7 @@
 import android.util.proto.ProtoOutputStream;
 
 import com.android.internal.R;
+import com.android.internal.util.XmlUtils;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -151,6 +152,7 @@
     private static final String RULE_ATT_ENABLED = "enabled";
     private static final String RULE_ATT_SNOOZING = "snoozing";
     private static final String RULE_ATT_NAME = "name";
+    private static final String RULE_ATT_PKG = "pkg";
     private static final String RULE_ATT_COMPONENT = "component";
     private static final String RULE_ATT_CONFIG_ACTIVITY = "configActivity";
     private static final String RULE_ATT_ZEN = "zen";
@@ -644,11 +646,11 @@
         rt.conditionId = safeUri(parser, RULE_ATT_CONDITION_ID);
         rt.component = safeComponentName(parser, RULE_ATT_COMPONENT);
         rt.configurationActivity = safeComponentName(parser, RULE_ATT_CONFIG_ACTIVITY);
-        rt.pkg = (rt.component != null)
-                ? rt.component.getPackageName()
-                : (rt.configurationActivity != null)
-                        ? rt.configurationActivity.getPackageName()
-                        : null;
+        rt.pkg = XmlUtils.readStringAttribute(parser, RULE_ATT_PKG);
+        if (rt.pkg == null) {
+            // backfill from component, if present. configActivity is not safe to backfill from
+            rt.pkg = rt.component != null ? rt.component.getPackageName() : null;
+        }
         rt.creationTime = safeLong(parser, RULE_ATT_CREATION_TIME, 0);
         rt.enabler = parser.getAttributeValue(null, RULE_ATT_ENABLER);
         rt.condition = readConditionXml(parser);
@@ -670,6 +672,9 @@
             out.attribute(null, RULE_ATT_NAME, rule.name);
         }
         out.attribute(null, RULE_ATT_ZEN, Integer.toString(rule.zenMode));
+        if (rule.pkg != null) {
+            out.attribute(null, RULE_ATT_PKG, rule.pkg);
+        }
         if (rule.component != null) {
             out.attribute(null, RULE_ATT_COMPONENT, rule.component.flattenToString());
         }
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 55f890d..d2abb8a 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -3609,7 +3609,7 @@
         }
 
         @Override
-        public String addAutomaticZenRule(AutomaticZenRule automaticZenRule) {
+        public String addAutomaticZenRule(AutomaticZenRule automaticZenRule, String pkg) {
             Preconditions.checkNotNull(automaticZenRule, "automaticZenRule is null");
             Preconditions.checkNotNull(automaticZenRule.getName(), "Name is null");
             if (automaticZenRule.getOwner() == null
@@ -3618,6 +3618,7 @@
                         "Rule must have a conditionproviderservice and/or configuration activity");
             }
             Preconditions.checkNotNull(automaticZenRule.getConditionId(), "ConditionId is null");
+            checkCallerIsSameApp(pkg);
             if (automaticZenRule.getZenPolicy() != null
                     && automaticZenRule.getInterruptionFilter() != INTERRUPTION_FILTER_PRIORITY) {
                 throw new IllegalArgumentException("ZenPolicy is only applicable to "
@@ -3625,7 +3626,7 @@
             }
             enforcePolicyAccess(Binder.getCallingUid(), "addAutomaticZenRule");
 
-            return mZenModeHelper.addAutomaticZenRule(automaticZenRule,
+            return mZenModeHelper.addAutomaticZenRule(pkg, automaticZenRule,
                     "addAutomaticZenRule");
         }
 
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index 48f76e1..2775e56dc 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -289,7 +289,8 @@
         return null;
     }
 
-    public String addAutomaticZenRule(AutomaticZenRule automaticZenRule, String reason) {
+    public String addAutomaticZenRule(String pkg, AutomaticZenRule automaticZenRule,
+            String reason) {
         if (!isSystemRule(automaticZenRule)) {
             PackageItemInfo component = getServiceInfo(automaticZenRule.getOwner());
             if (component == null) {
@@ -322,7 +323,7 @@
             }
             newConfig = mConfig.copy();
             ZenRule rule = new ZenRule();
-            populateZenRule(automaticZenRule, rule, true);
+            populateZenRule(pkg, automaticZenRule, rule, true);
             newConfig.automaticRules.put(rule.id, rule);
             if (setConfigLocked(newConfig, reason, rule.component, true)) {
                 return rule.id;
@@ -352,7 +353,7 @@
                             "Cannot update rules not owned by your condition provider");
                 }
             }
-            populateZenRule(automaticZenRule, rule, false);
+            populateZenRule(rule.pkg, automaticZenRule, rule, false);
             return setConfigLocked(newConfig, reason, rule.component, true);
         }
     }
@@ -546,15 +547,14 @@
         return null;
     }
 
-    private void populateZenRule(AutomaticZenRule automaticZenRule, ZenRule rule, boolean isNew) {
+    private void populateZenRule(String pkg, AutomaticZenRule automaticZenRule, ZenRule rule,
+            boolean isNew) {
         if (isNew) {
             rule.id = ZenModeConfig.newRuleId();
             rule.creationTime = System.currentTimeMillis();
             rule.component = automaticZenRule.getOwner();
             rule.configurationActivity = automaticZenRule.getConfigurationActivity();
-            rule.pkg = (rule.component != null)
-                    ? rule.component.getPackageName()
-                    : rule.configurationActivity.getPackageName();
+            rule.pkg = pkg;
         }
 
         if (rule.enabled != automaticZenRule.isEnabled()) {
@@ -571,10 +571,13 @@
     }
 
     protected AutomaticZenRule createAutomaticZenRule(ZenRule rule) {
-        return new AutomaticZenRule(rule.name, rule.component, rule.configurationActivity,
+        AutomaticZenRule azr =  new AutomaticZenRule(rule.name, rule.component,
+                rule.configurationActivity,
                 rule.conditionId, rule.zenPolicy,
                 NotificationManager.zenModeToInterruptionFilter(rule.zenMode),
                 rule.enabled, rule.creationTime);
+        azr.setPackageName(rule.pkg);
+        return azr;
     }
 
     public void setManualZenMode(int zenMode, Uri conditionId, String caller, String reason) {
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 200e83d..517b957 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -5202,7 +5202,7 @@
                 zenPolicy, NotificationManager.INTERRUPTION_FILTER_NONE, isEnabled);
 
         try {
-            mBinderService.addAutomaticZenRule(rule);
+            mBinderService.addAutomaticZenRule(rule, mContext.getPackageName());
             fail("Zen policy only applies to priority only mode");
         } catch (IllegalArgumentException e) {
             // yay
@@ -5210,11 +5210,11 @@
 
         rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
                 zenPolicy, NotificationManager.INTERRUPTION_FILTER_PRIORITY, isEnabled);
-        mBinderService.addAutomaticZenRule(rule);
+        mBinderService.addAutomaticZenRule(rule, mContext.getPackageName());
 
         rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
                 null, NotificationManager.INTERRUPTION_FILTER_NONE, isEnabled);
-        mBinderService.addAutomaticZenRule(rule);
+        mBinderService.addAutomaticZenRule(rule, mContext.getPackageName());
     }
 
     @Test
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java
index dcab78e..6401987 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java
@@ -158,7 +158,7 @@
 
         ZenModeConfig.ZenRule rule = new ZenModeConfig.ZenRule();
         rule.configurationActivity = new ComponentName("a", "a");
-        rule.component = new ComponentName("a", "b");
+        rule.component = new ComponentName("b", "b");
         rule.conditionId = new Uri.Builder().scheme("hello").build();
         rule.condition = new Condition(rule.conditionId, "", Condition.STATE_TRUE);
         rule.enabled = true;
@@ -168,6 +168,7 @@
         rule.modified = true;
         rule.name = "name";
         rule.snoozing = true;
+        rule.pkg = "b";
 
         XmlSerializer out = new FastXmlSerializer();
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
@@ -183,8 +184,7 @@
                 new ByteArrayInputStream(baos.toByteArray())), null);
         parser.nextTag();
         ZenModeConfig.ZenRule fromXml = ZenModeConfig.readRuleXml(parser);
-        // read from backing component
-        assertEquals("a", fromXml.pkg);
+        assertEquals("b", fromXml.pkg);
         // always resets on reboot
         assertFalse(fromXml.snoozing);
         //should all match original
@@ -200,6 +200,55 @@
         assertEquals(rule.zenMode, fromXml.zenMode);
     }
 
+    @Test
+    public void testRuleXml_pkg_component() throws Exception {
+        String tag = "tag";
+
+        ZenModeConfig.ZenRule rule = new ZenModeConfig.ZenRule();
+        rule.configurationActivity = new ComponentName("a", "a");
+        rule.component = new ComponentName("b", "b");
+
+        XmlSerializer out = new FastXmlSerializer();
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        out.setOutput(new BufferedOutputStream(baos), "utf-8");
+        out.startDocument(null, true);
+        out.startTag(null, tag);
+        ZenModeConfig.writeRuleXml(rule, out);
+        out.endTag(null, tag);
+        out.endDocument();
+
+        XmlPullParser parser = Xml.newPullParser();
+        parser.setInput(new BufferedInputStream(
+                new ByteArrayInputStream(baos.toByteArray())), null);
+        parser.nextTag();
+        ZenModeConfig.ZenRule fromXml = ZenModeConfig.readRuleXml(parser);
+        assertEquals("b", fromXml.pkg);
+    }
+
+    @Test
+    public void testRuleXml_pkg_configActivity() throws Exception {
+        String tag = "tag";
+
+        ZenModeConfig.ZenRule rule = new ZenModeConfig.ZenRule();
+        rule.configurationActivity = new ComponentName("a", "a");
+
+        XmlSerializer out = new FastXmlSerializer();
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        out.setOutput(new BufferedOutputStream(baos), "utf-8");
+        out.startDocument(null, true);
+        out.startTag(null, tag);
+        ZenModeConfig.writeRuleXml(rule, out);
+        out.endTag(null, tag);
+        out.endDocument();
+
+        XmlPullParser parser = Xml.newPullParser();
+        parser.setInput(new BufferedInputStream(
+                new ByteArrayInputStream(baos.toByteArray())), null);
+        parser.nextTag();
+        ZenModeConfig.ZenRule fromXml = ZenModeConfig.readRuleXml(parser);
+        assertNull(fromXml.pkg);
+    }
+
     private ZenModeConfig getMutedNotificationsConfig() {
         ZenModeConfig config = new ZenModeConfig();
         // Allow alarms, media, and system
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
index cac6f09..94c33e2 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
@@ -1353,7 +1353,7 @@
                 new ComponentName("android", "ScheduleConditionProvider"),
                 ZenModeConfig.toScheduleConditionId(new ScheduleInfo()),
                 NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
-        String id = mZenModeHelperSpy.addAutomaticZenRule(zenRule, "test");
+        String id = mZenModeHelperSpy.addAutomaticZenRule("android", zenRule, "test");
 
         assertTrue(id != null);
         ZenModeConfig.ZenRule ruleInConfig = mZenModeHelperSpy.mConfig.automaticRules.get(id);
@@ -1377,7 +1377,7 @@
                     ZenModeConfig.toScheduleConditionId(si),
                     new ZenPolicy.Builder().build(),
                     NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
-            String id = mZenModeHelperSpy.addAutomaticZenRule(zenRule, "test");
+            String id = mZenModeHelperSpy.addAutomaticZenRule("android", zenRule, "test");
             assertNotNull(id);
         }
         try {
@@ -1387,7 +1387,7 @@
                     ZenModeConfig.toScheduleConditionId(new ScheduleInfo()),
                     new ZenPolicy.Builder().build(),
                     NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
-            String id = mZenModeHelperSpy.addAutomaticZenRule(zenRule, "test");
+            String id = mZenModeHelperSpy.addAutomaticZenRule("android", zenRule, "test");
             fail("allowed too many rules to be created");
         } catch (IllegalArgumentException e) {
             // yay