Loading core/java/android/service/notification/ZenModeConfig.java +113 −36 Original line number Diff line number Diff line Loading @@ -64,6 +64,7 @@ import org.xmlpull.v1.XmlPullParserException; import java.io.IOException; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.time.Instant; import java.util.Arrays; import java.util.Calendar; import java.util.Date; Loading Loading @@ -233,6 +234,7 @@ public class ZenModeConfig implements Parcelable { private static final String MANUAL_TAG = "manual"; private static final String AUTOMATIC_TAG = "automatic"; private static final String AUTOMATIC_DELETED_TAG = "deleted"; private static final String RULE_ATT_ID = "ruleId"; private static final String RULE_ATT_ENABLED = "enabled"; Loading @@ -251,6 +253,7 @@ public class ZenModeConfig implements Parcelable { private static final String RULE_ATT_USER_MODIFIED_FIELDS = "userModifiedFields"; private static final String RULE_ATT_ICON = "rule_icon"; private static final String RULE_ATT_TRIGGER_DESC = "triggerDesc"; private static final String RULE_ATT_DELETION_INSTANT = "deletionInstant"; private static final String DEVICE_EFFECT_DISPLAY_GRAYSCALE = "zdeDisplayGrayscale"; private static final String DEVICE_EFFECT_SUPPRESS_AMBIENT_DISPLAY = Loading Loading @@ -292,6 +295,10 @@ public class ZenModeConfig implements Parcelable { @UnsupportedAppUsage public ArrayMap<String, ZenRule> automaticRules = new ArrayMap<>(); // Note: Map is *pkg|conditionId* (see deletedRuleKey()) -> ZenRule, // unlike automaticRules (which is id -> rule). public final ArrayMap<String, ZenRule> deletedRules = new ArrayMap<>(); @UnsupportedAppUsage public ZenModeConfig() { } Loading @@ -306,15 +313,9 @@ public class ZenModeConfig implements Parcelable { allowMessagesFrom = source.readInt(); user = source.readInt(); manualRule = source.readParcelable(null, ZenRule.class); final int len = source.readInt(); if (len > 0) { final String[] ids = new String[len]; final ZenRule[] rules = new ZenRule[len]; source.readStringArray(ids); source.readTypedArray(rules, ZenRule.CREATOR); for (int i = 0; i < len; i++) { automaticRules.put(ids[i], rules[i]); } readRulesFromParcel(automaticRules, source); if (Flags.modesApi()) { readRulesFromParcel(deletedRules, source); } allowAlarms = source.readInt() == 1; allowMedia = source.readInt() == 1; Loading @@ -328,6 +329,19 @@ public class ZenModeConfig implements Parcelable { } } private static void readRulesFromParcel(ArrayMap<String, ZenRule> ruleMap, Parcel source) { final int len = source.readInt(); if (len > 0) { final String[] ids = new String[len]; final ZenRule[] rules = new ZenRule[len]; source.readStringArray(ids); source.readTypedArray(rules, ZenRule.CREATOR); for (int i = 0; i < len; i++) { ruleMap.put(ids[i], rules[i]); } } } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeInt(allowCalls ? 1 : 0); Loading @@ -339,19 +353,9 @@ public class ZenModeConfig implements Parcelable { dest.writeInt(allowMessagesFrom); dest.writeInt(user); dest.writeParcelable(manualRule, 0); if (!automaticRules.isEmpty()) { final int len = automaticRules.size(); final String[] ids = new String[len]; final ZenRule[] rules = new ZenRule[len]; for (int i = 0; i < len; i++) { ids[i] = automaticRules.keyAt(i); rules[i] = automaticRules.valueAt(i); } dest.writeInt(len); dest.writeStringArray(ids); dest.writeTypedArray(rules, 0); } else { dest.writeInt(0); writeRulesToParcel(automaticRules, dest); if (Flags.modesApi()) { writeRulesToParcel(deletedRules, dest); } dest.writeInt(allowAlarms ? 1 : 0); dest.writeInt(allowMedia ? 1 : 0); Loading @@ -365,6 +369,23 @@ public class ZenModeConfig implements Parcelable { } } private static void writeRulesToParcel(ArrayMap<String, ZenRule> ruleMap, Parcel dest) { if (!ruleMap.isEmpty()) { final int len = ruleMap.size(); final String[] ids = new String[len]; final ZenRule[] rules = new ZenRule[len]; for (int i = 0; i < len; i++) { ids[i] = ruleMap.keyAt(i); rules[i] = ruleMap.valueAt(i); } dest.writeInt(len); dest.writeStringArray(ids); dest.writeTypedArray(rules, 0); } else { dest.writeInt(0); } } @Override public String toString() { StringBuilder sb = new StringBuilder(ZenModeConfig.class.getSimpleName()).append('[') Loading @@ -389,23 +410,26 @@ public class ZenModeConfig implements Parcelable { } else { sb.append(",areChannelsBypassingDnd=").append(areChannelsBypassingDnd); } return sb.append(",\nautomaticRules=").append(rulesToString()) .append(",\nmanualRule=").append(manualRule) .append(']').toString(); sb.append(",\nautomaticRules=").append(rulesToString(automaticRules)) .append(",\nmanualRule=").append(manualRule); if (Flags.modesApi()) { sb.append(",\ndeletedRules=").append(rulesToString(deletedRules)); } return sb.append(']').toString(); } private String rulesToString() { if (automaticRules.isEmpty()) { private static String rulesToString(ArrayMap<String, ZenRule> ruleList) { if (ruleList.isEmpty()) { return "{}"; } StringBuilder buffer = new StringBuilder(automaticRules.size() * 28); StringBuilder buffer = new StringBuilder(ruleList.size() * 28); buffer.append("{\n"); for (int i = 0; i < automaticRules.size(); i++) { for (int i = 0; i < ruleList.size(); i++) { if (i > 0) { buffer.append(",\n"); } Object value = automaticRules.valueAt(i); Object value = ruleList.valueAt(i); buffer.append(value); } buffer.append('}'); Loading Loading @@ -487,7 +511,9 @@ public class ZenModeConfig implements Parcelable { && other.allowConversations == allowConversations && other.allowConversationsFrom == allowConversationsFrom; if (Flags.modesApi()) { return eq && other.allowPriorityChannels == allowPriorityChannels; return eq && Objects.equals(other.deletedRules, deletedRules) && other.allowPriorityChannels == allowPriorityChannels; } return eq; } Loading Loading @@ -644,13 +670,21 @@ public class ZenModeConfig implements Parcelable { DEFAULT_SUPPRESSED_VISUAL_EFFECTS); } else if (MANUAL_TAG.equals(tag)) { rt.manualRule = readRuleXml(parser); } else if (AUTOMATIC_TAG.equals(tag)) { } else if (AUTOMATIC_TAG.equals(tag) || (Flags.modesApi() && AUTOMATIC_DELETED_TAG.equals(tag))) { final String id = parser.getAttributeValue(null, RULE_ATT_ID); final ZenRule automaticRule = readRuleXml(parser); if (id != null && automaticRule != null) { automaticRule.id = id; if (Flags.modesApi() && AUTOMATIC_DELETED_TAG.equals(tag)) { String deletedRuleKey = deletedRuleKey(automaticRule); if (deletedRuleKey != null) { rt.deletedRules.put(deletedRuleKey, automaticRule); } } else if (AUTOMATIC_TAG.equals(tag)) { rt.automaticRules.put(id, automaticRule); } } } else if (STATE_TAG.equals(tag)) { rt.areChannelsBypassingDnd = safeBoolean(parser, STATE_ATT_CHANNELS_BYPASSING_DND, DEFAULT_CHANNELS_BYPASSING_DND); Loading @@ -660,13 +694,24 @@ public class ZenModeConfig implements Parcelable { throw new IllegalStateException("Failed to reach END_DOCUMENT"); } /** Generates the map key used for a {@link ZenRule} in {@link #deletedRules}. */ @Nullable public static String deletedRuleKey(ZenRule rule) { if (rule.pkg != null && rule.conditionId != null) { return rule.pkg + "|" + rule.conditionId.toString(); } else { return null; } } /** * Writes XML of current ZenModeConfig * @param out serializer * @param version uses XML_VERSION if version is null * @throws IOException */ public void writeXml(TypedXmlSerializer out, Integer version) throws IOException { public void writeXml(TypedXmlSerializer out, Integer version, boolean forBackup) throws IOException { out.startTag(null, ZEN_TAG); out.attribute(null, ZEN_ATT_VERSION, version == null ? Integer.toString(XML_VERSION) : Integer.toString(version)); Loading Loading @@ -707,6 +752,15 @@ public class ZenModeConfig implements Parcelable { writeRuleXml(automaticRule, out); out.endTag(null, AUTOMATIC_TAG); } if (Flags.modesApi() && !forBackup) { for (int i = 0; i < deletedRules.size(); i++) { final ZenRule deletedRule = deletedRules.valueAt(i); out.startTag(null, AUTOMATIC_DELETED_TAG); out.attribute(null, RULE_ATT_ID, deletedRule.id); writeRuleXml(deletedRule, out); out.endTag(null, AUTOMATIC_DELETED_TAG); } } out.startTag(null, STATE_TAG); out.attributeBoolean(null, STATE_ATT_CHANNELS_BYPASSING_DND, areChannelsBypassingDnd); Loading Loading @@ -752,6 +806,11 @@ public class ZenModeConfig implements Parcelable { rt.triggerDescription = parser.getAttributeValue(null, RULE_ATT_TRIGGER_DESC); rt.type = safeInt(parser, RULE_ATT_TYPE, AutomaticZenRule.TYPE_UNKNOWN); rt.userModifiedFields = safeInt(parser, RULE_ATT_USER_MODIFIED_FIELDS, 0); Long deletionInstant = tryParseLong( parser.getAttributeValue(null, RULE_ATT_DELETION_INSTANT), null); if (deletionInstant != null) { rt.deletionInstant = Instant.ofEpochMilli(deletionInstant); } } return rt; } Loading Loading @@ -799,6 +858,10 @@ public class ZenModeConfig implements Parcelable { } out.attributeInt(null, RULE_ATT_TYPE, rule.type); out.attributeInt(null, RULE_ATT_USER_MODIFIED_FIELDS, rule.userModifiedFields); if (rule.deletionInstant != null) { out.attributeLong(null, RULE_ATT_DELETION_INSTANT, rule.deletionInstant.toEpochMilli()); } } } Loading Loading @@ -1998,6 +2061,7 @@ public class ZenModeConfig implements Parcelable { public String iconResName; public boolean allowManualInvocation; public int userModifiedFields; @Nullable public Instant deletionInstant; // Only set on deleted rules. public ZenRule() { } Loading Loading @@ -2031,6 +2095,9 @@ public class ZenModeConfig implements Parcelable { triggerDescription = source.readString(); type = source.readInt(); userModifiedFields = source.readInt(); if (source.readInt() == 1) { deletionInstant = Instant.ofEpochMilli(source.readLong()); } } } Loading Loading @@ -2091,6 +2158,12 @@ public class ZenModeConfig implements Parcelable { dest.writeString(triggerDescription); dest.writeInt(type); dest.writeInt(userModifiedFields); if (deletionInstant != null) { dest.writeInt(1); dest.writeLong(deletionInstant.toEpochMilli()); } else { dest.writeInt(0); } } } Loading Loading @@ -2121,6 +2194,9 @@ public class ZenModeConfig implements Parcelable { .append(",triggerDescription=").append(triggerDescription) .append(",type=").append(type) .append(",userModifiedFields=").append(userModifiedFields); if (deletionInstant != null) { sb.append(",deletionInstant=").append(deletionInstant); } } return sb.append(']').toString(); Loading Loading @@ -2180,7 +2256,8 @@ public class ZenModeConfig implements Parcelable { && Objects.equals(other.iconResName, iconResName) && Objects.equals(other.triggerDescription, triggerDescription) && other.type == type && other.userModifiedFields == userModifiedFields; && other.userModifiedFields == userModifiedFields && Objects.equals(other.deletionInstant, deletionInstant); } return finalEquals; Loading @@ -2192,7 +2269,7 @@ public class ZenModeConfig implements Parcelable { return Objects.hash(enabled, snoozing, name, zenMode, conditionId, condition, component, configurationActivity, pkg, id, enabler, zenPolicy, zenDeviceEffects, modified, allowManualInvocation, iconResName, triggerDescription, type, userModifiedFields); triggerDescription, type, userModifiedFields, deletionInstant); } return Objects.hash(enabled, snoozing, name, zenMode, conditionId, condition, component, configurationActivity, pkg, id, enabler, zenPolicy, modified); Loading core/java/android/service/notification/ZenModeDiff.java +5 −5 Original line number Diff line number Diff line Loading @@ -30,6 +30,11 @@ import java.util.Set; /** * ZenModeDiff is a utility class meant to encapsulate the diff between ZenModeConfigs and their * subcomponents (automatic and manual ZenRules). * * <p>Note that this class is intended to detect <em>meaningful</em> differences, so objects that * are not identical (as per their {@code equals()} implementation) can still produce an empty diff * if only "metadata" fields are updated. * * @hide */ public class ZenModeDiff { Loading Loading @@ -467,7 +472,6 @@ public class ZenModeDiff { public static final String FIELD_ICON_RES = "iconResName"; public static final String FIELD_TRIGGER_DESCRIPTION = "triggerDescription"; public static final String FIELD_TYPE = "type"; public static final String FIELD_USER_MODIFIED_FIELDS = "userModifiedFields"; // NOTE: new field strings must match the variable names in ZenModeConfig.ZenRule // Special field to track whether this rule became active or inactive Loading Loading @@ -563,10 +567,6 @@ public class ZenModeDiff { if (!Objects.equals(from.iconResName, to.iconResName)) { addField(FIELD_ICON_RES, new FieldDiff<>(from.iconResName, to.iconResName)); } if (from.userModifiedFields != to.userModifiedFields) { addField(FIELD_USER_MODIFIED_FIELDS, new FieldDiff<>(from.userModifiedFields, to.userModifiedFields)); } } } Loading services/core/java/com/android/server/notification/NotificationManagerService.java +3 −3 Original line number Diff line number Diff line Loading @@ -215,7 +215,6 @@ import android.content.IntentFilter; import android.content.pm.ApplicationInfo; import android.content.pm.IPackageManager; import android.content.pm.LauncherApps; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.PackageManagerInternal; Loading Loading @@ -373,6 +372,7 @@ import java.io.InputStream; import java.io.OutputStream; import java.io.PrintWriter; import java.nio.charset.StandardCharsets; import java.time.Clock; import java.time.Duration; import java.util.ArrayList; import java.util.Arrays; Loading Loading @@ -2466,8 +2466,8 @@ public class NotificationManagerService extends SystemService { mMetricsLogger = new MetricsLogger(); mRankingHandler = rankingHandler; mConditionProviders = conditionProviders; mZenModeHelper = new ZenModeHelper(getContext(), mHandler.getLooper(), mConditionProviders, flagResolver, new ZenModeEventLogger(mPackageManagerClient)); mZenModeHelper = new ZenModeHelper(getContext(), mHandler.getLooper(), Clock.systemUTC(), mConditionProviders, flagResolver, new ZenModeEventLogger(mPackageManagerClient)); mZenModeHelper.addCallback(new ZenModeHelper.Callback() { @Override public void onConfigChanged() { Loading services/core/java/com/android/server/notification/ZenModeHelper.java +125 −21 File changed.Preview size limit exceeded, changes collapsed. Show changes services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java +6 −1 Original line number Diff line number Diff line Loading @@ -60,6 +60,7 @@ import java.io.BufferedOutputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.time.Instant; @SmallTest @RunWith(AndroidJUnit4.class) Loading Loading @@ -407,6 +408,7 @@ public class ZenModeConfigTest extends UiServiceTestCase { rule.userModifiedFields = 16; rule.iconResName = ICON_RES_NAME; rule.triggerDescription = TRIGGER_DESC; rule.deletionInstant = Instant.ofEpochMilli(1701790147000L); Parcel parcel = Parcel.obtain(); rule.writeToParcel(parcel, 0); Loading @@ -432,9 +434,10 @@ public class ZenModeConfigTest extends UiServiceTestCase { assertEquals(rule.userModifiedFields, parceled.userModifiedFields); assertEquals(rule.triggerDescription, parceled.triggerDescription); assertEquals(rule.zenPolicy, parceled.zenPolicy); assertEquals(rule.deletionInstant, parceled.deletionInstant); assertEquals(rule, parceled); assertEquals(rule.hashCode(), parceled.hashCode()); } @Test Loading Loading @@ -510,6 +513,7 @@ public class ZenModeConfigTest extends UiServiceTestCase { rule.userModifiedFields = 4; rule.iconResName = ICON_RES_NAME; rule.triggerDescription = TRIGGER_DESC; rule.deletionInstant = Instant.ofEpochMilli(1701790147000L); ByteArrayOutputStream baos = new ByteArrayOutputStream(); writeRuleXml(rule, baos); Loading Loading @@ -539,6 +543,7 @@ public class ZenModeConfigTest extends UiServiceTestCase { assertEquals(rule.userModifiedFields, fromXml.userModifiedFields); assertEquals(rule.triggerDescription, fromXml.triggerDescription); assertEquals(rule.iconResName, fromXml.iconResName); assertEquals(rule.deletionInstant, fromXml.deletionInstant); } @Test Loading Loading
core/java/android/service/notification/ZenModeConfig.java +113 −36 Original line number Diff line number Diff line Loading @@ -64,6 +64,7 @@ import org.xmlpull.v1.XmlPullParserException; import java.io.IOException; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.time.Instant; import java.util.Arrays; import java.util.Calendar; import java.util.Date; Loading Loading @@ -233,6 +234,7 @@ public class ZenModeConfig implements Parcelable { private static final String MANUAL_TAG = "manual"; private static final String AUTOMATIC_TAG = "automatic"; private static final String AUTOMATIC_DELETED_TAG = "deleted"; private static final String RULE_ATT_ID = "ruleId"; private static final String RULE_ATT_ENABLED = "enabled"; Loading @@ -251,6 +253,7 @@ public class ZenModeConfig implements Parcelable { private static final String RULE_ATT_USER_MODIFIED_FIELDS = "userModifiedFields"; private static final String RULE_ATT_ICON = "rule_icon"; private static final String RULE_ATT_TRIGGER_DESC = "triggerDesc"; private static final String RULE_ATT_DELETION_INSTANT = "deletionInstant"; private static final String DEVICE_EFFECT_DISPLAY_GRAYSCALE = "zdeDisplayGrayscale"; private static final String DEVICE_EFFECT_SUPPRESS_AMBIENT_DISPLAY = Loading Loading @@ -292,6 +295,10 @@ public class ZenModeConfig implements Parcelable { @UnsupportedAppUsage public ArrayMap<String, ZenRule> automaticRules = new ArrayMap<>(); // Note: Map is *pkg|conditionId* (see deletedRuleKey()) -> ZenRule, // unlike automaticRules (which is id -> rule). public final ArrayMap<String, ZenRule> deletedRules = new ArrayMap<>(); @UnsupportedAppUsage public ZenModeConfig() { } Loading @@ -306,15 +313,9 @@ public class ZenModeConfig implements Parcelable { allowMessagesFrom = source.readInt(); user = source.readInt(); manualRule = source.readParcelable(null, ZenRule.class); final int len = source.readInt(); if (len > 0) { final String[] ids = new String[len]; final ZenRule[] rules = new ZenRule[len]; source.readStringArray(ids); source.readTypedArray(rules, ZenRule.CREATOR); for (int i = 0; i < len; i++) { automaticRules.put(ids[i], rules[i]); } readRulesFromParcel(automaticRules, source); if (Flags.modesApi()) { readRulesFromParcel(deletedRules, source); } allowAlarms = source.readInt() == 1; allowMedia = source.readInt() == 1; Loading @@ -328,6 +329,19 @@ public class ZenModeConfig implements Parcelable { } } private static void readRulesFromParcel(ArrayMap<String, ZenRule> ruleMap, Parcel source) { final int len = source.readInt(); if (len > 0) { final String[] ids = new String[len]; final ZenRule[] rules = new ZenRule[len]; source.readStringArray(ids); source.readTypedArray(rules, ZenRule.CREATOR); for (int i = 0; i < len; i++) { ruleMap.put(ids[i], rules[i]); } } } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeInt(allowCalls ? 1 : 0); Loading @@ -339,19 +353,9 @@ public class ZenModeConfig implements Parcelable { dest.writeInt(allowMessagesFrom); dest.writeInt(user); dest.writeParcelable(manualRule, 0); if (!automaticRules.isEmpty()) { final int len = automaticRules.size(); final String[] ids = new String[len]; final ZenRule[] rules = new ZenRule[len]; for (int i = 0; i < len; i++) { ids[i] = automaticRules.keyAt(i); rules[i] = automaticRules.valueAt(i); } dest.writeInt(len); dest.writeStringArray(ids); dest.writeTypedArray(rules, 0); } else { dest.writeInt(0); writeRulesToParcel(automaticRules, dest); if (Flags.modesApi()) { writeRulesToParcel(deletedRules, dest); } dest.writeInt(allowAlarms ? 1 : 0); dest.writeInt(allowMedia ? 1 : 0); Loading @@ -365,6 +369,23 @@ public class ZenModeConfig implements Parcelable { } } private static void writeRulesToParcel(ArrayMap<String, ZenRule> ruleMap, Parcel dest) { if (!ruleMap.isEmpty()) { final int len = ruleMap.size(); final String[] ids = new String[len]; final ZenRule[] rules = new ZenRule[len]; for (int i = 0; i < len; i++) { ids[i] = ruleMap.keyAt(i); rules[i] = ruleMap.valueAt(i); } dest.writeInt(len); dest.writeStringArray(ids); dest.writeTypedArray(rules, 0); } else { dest.writeInt(0); } } @Override public String toString() { StringBuilder sb = new StringBuilder(ZenModeConfig.class.getSimpleName()).append('[') Loading @@ -389,23 +410,26 @@ public class ZenModeConfig implements Parcelable { } else { sb.append(",areChannelsBypassingDnd=").append(areChannelsBypassingDnd); } return sb.append(",\nautomaticRules=").append(rulesToString()) .append(",\nmanualRule=").append(manualRule) .append(']').toString(); sb.append(",\nautomaticRules=").append(rulesToString(automaticRules)) .append(",\nmanualRule=").append(manualRule); if (Flags.modesApi()) { sb.append(",\ndeletedRules=").append(rulesToString(deletedRules)); } return sb.append(']').toString(); } private String rulesToString() { if (automaticRules.isEmpty()) { private static String rulesToString(ArrayMap<String, ZenRule> ruleList) { if (ruleList.isEmpty()) { return "{}"; } StringBuilder buffer = new StringBuilder(automaticRules.size() * 28); StringBuilder buffer = new StringBuilder(ruleList.size() * 28); buffer.append("{\n"); for (int i = 0; i < automaticRules.size(); i++) { for (int i = 0; i < ruleList.size(); i++) { if (i > 0) { buffer.append(",\n"); } Object value = automaticRules.valueAt(i); Object value = ruleList.valueAt(i); buffer.append(value); } buffer.append('}'); Loading Loading @@ -487,7 +511,9 @@ public class ZenModeConfig implements Parcelable { && other.allowConversations == allowConversations && other.allowConversationsFrom == allowConversationsFrom; if (Flags.modesApi()) { return eq && other.allowPriorityChannels == allowPriorityChannels; return eq && Objects.equals(other.deletedRules, deletedRules) && other.allowPriorityChannels == allowPriorityChannels; } return eq; } Loading Loading @@ -644,13 +670,21 @@ public class ZenModeConfig implements Parcelable { DEFAULT_SUPPRESSED_VISUAL_EFFECTS); } else if (MANUAL_TAG.equals(tag)) { rt.manualRule = readRuleXml(parser); } else if (AUTOMATIC_TAG.equals(tag)) { } else if (AUTOMATIC_TAG.equals(tag) || (Flags.modesApi() && AUTOMATIC_DELETED_TAG.equals(tag))) { final String id = parser.getAttributeValue(null, RULE_ATT_ID); final ZenRule automaticRule = readRuleXml(parser); if (id != null && automaticRule != null) { automaticRule.id = id; if (Flags.modesApi() && AUTOMATIC_DELETED_TAG.equals(tag)) { String deletedRuleKey = deletedRuleKey(automaticRule); if (deletedRuleKey != null) { rt.deletedRules.put(deletedRuleKey, automaticRule); } } else if (AUTOMATIC_TAG.equals(tag)) { rt.automaticRules.put(id, automaticRule); } } } else if (STATE_TAG.equals(tag)) { rt.areChannelsBypassingDnd = safeBoolean(parser, STATE_ATT_CHANNELS_BYPASSING_DND, DEFAULT_CHANNELS_BYPASSING_DND); Loading @@ -660,13 +694,24 @@ public class ZenModeConfig implements Parcelable { throw new IllegalStateException("Failed to reach END_DOCUMENT"); } /** Generates the map key used for a {@link ZenRule} in {@link #deletedRules}. */ @Nullable public static String deletedRuleKey(ZenRule rule) { if (rule.pkg != null && rule.conditionId != null) { return rule.pkg + "|" + rule.conditionId.toString(); } else { return null; } } /** * Writes XML of current ZenModeConfig * @param out serializer * @param version uses XML_VERSION if version is null * @throws IOException */ public void writeXml(TypedXmlSerializer out, Integer version) throws IOException { public void writeXml(TypedXmlSerializer out, Integer version, boolean forBackup) throws IOException { out.startTag(null, ZEN_TAG); out.attribute(null, ZEN_ATT_VERSION, version == null ? Integer.toString(XML_VERSION) : Integer.toString(version)); Loading Loading @@ -707,6 +752,15 @@ public class ZenModeConfig implements Parcelable { writeRuleXml(automaticRule, out); out.endTag(null, AUTOMATIC_TAG); } if (Flags.modesApi() && !forBackup) { for (int i = 0; i < deletedRules.size(); i++) { final ZenRule deletedRule = deletedRules.valueAt(i); out.startTag(null, AUTOMATIC_DELETED_TAG); out.attribute(null, RULE_ATT_ID, deletedRule.id); writeRuleXml(deletedRule, out); out.endTag(null, AUTOMATIC_DELETED_TAG); } } out.startTag(null, STATE_TAG); out.attributeBoolean(null, STATE_ATT_CHANNELS_BYPASSING_DND, areChannelsBypassingDnd); Loading Loading @@ -752,6 +806,11 @@ public class ZenModeConfig implements Parcelable { rt.triggerDescription = parser.getAttributeValue(null, RULE_ATT_TRIGGER_DESC); rt.type = safeInt(parser, RULE_ATT_TYPE, AutomaticZenRule.TYPE_UNKNOWN); rt.userModifiedFields = safeInt(parser, RULE_ATT_USER_MODIFIED_FIELDS, 0); Long deletionInstant = tryParseLong( parser.getAttributeValue(null, RULE_ATT_DELETION_INSTANT), null); if (deletionInstant != null) { rt.deletionInstant = Instant.ofEpochMilli(deletionInstant); } } return rt; } Loading Loading @@ -799,6 +858,10 @@ public class ZenModeConfig implements Parcelable { } out.attributeInt(null, RULE_ATT_TYPE, rule.type); out.attributeInt(null, RULE_ATT_USER_MODIFIED_FIELDS, rule.userModifiedFields); if (rule.deletionInstant != null) { out.attributeLong(null, RULE_ATT_DELETION_INSTANT, rule.deletionInstant.toEpochMilli()); } } } Loading Loading @@ -1998,6 +2061,7 @@ public class ZenModeConfig implements Parcelable { public String iconResName; public boolean allowManualInvocation; public int userModifiedFields; @Nullable public Instant deletionInstant; // Only set on deleted rules. public ZenRule() { } Loading Loading @@ -2031,6 +2095,9 @@ public class ZenModeConfig implements Parcelable { triggerDescription = source.readString(); type = source.readInt(); userModifiedFields = source.readInt(); if (source.readInt() == 1) { deletionInstant = Instant.ofEpochMilli(source.readLong()); } } } Loading Loading @@ -2091,6 +2158,12 @@ public class ZenModeConfig implements Parcelable { dest.writeString(triggerDescription); dest.writeInt(type); dest.writeInt(userModifiedFields); if (deletionInstant != null) { dest.writeInt(1); dest.writeLong(deletionInstant.toEpochMilli()); } else { dest.writeInt(0); } } } Loading Loading @@ -2121,6 +2194,9 @@ public class ZenModeConfig implements Parcelable { .append(",triggerDescription=").append(triggerDescription) .append(",type=").append(type) .append(",userModifiedFields=").append(userModifiedFields); if (deletionInstant != null) { sb.append(",deletionInstant=").append(deletionInstant); } } return sb.append(']').toString(); Loading Loading @@ -2180,7 +2256,8 @@ public class ZenModeConfig implements Parcelable { && Objects.equals(other.iconResName, iconResName) && Objects.equals(other.triggerDescription, triggerDescription) && other.type == type && other.userModifiedFields == userModifiedFields; && other.userModifiedFields == userModifiedFields && Objects.equals(other.deletionInstant, deletionInstant); } return finalEquals; Loading @@ -2192,7 +2269,7 @@ public class ZenModeConfig implements Parcelable { return Objects.hash(enabled, snoozing, name, zenMode, conditionId, condition, component, configurationActivity, pkg, id, enabler, zenPolicy, zenDeviceEffects, modified, allowManualInvocation, iconResName, triggerDescription, type, userModifiedFields); triggerDescription, type, userModifiedFields, deletionInstant); } return Objects.hash(enabled, snoozing, name, zenMode, conditionId, condition, component, configurationActivity, pkg, id, enabler, zenPolicy, modified); Loading
core/java/android/service/notification/ZenModeDiff.java +5 −5 Original line number Diff line number Diff line Loading @@ -30,6 +30,11 @@ import java.util.Set; /** * ZenModeDiff is a utility class meant to encapsulate the diff between ZenModeConfigs and their * subcomponents (automatic and manual ZenRules). * * <p>Note that this class is intended to detect <em>meaningful</em> differences, so objects that * are not identical (as per their {@code equals()} implementation) can still produce an empty diff * if only "metadata" fields are updated. * * @hide */ public class ZenModeDiff { Loading Loading @@ -467,7 +472,6 @@ public class ZenModeDiff { public static final String FIELD_ICON_RES = "iconResName"; public static final String FIELD_TRIGGER_DESCRIPTION = "triggerDescription"; public static final String FIELD_TYPE = "type"; public static final String FIELD_USER_MODIFIED_FIELDS = "userModifiedFields"; // NOTE: new field strings must match the variable names in ZenModeConfig.ZenRule // Special field to track whether this rule became active or inactive Loading Loading @@ -563,10 +567,6 @@ public class ZenModeDiff { if (!Objects.equals(from.iconResName, to.iconResName)) { addField(FIELD_ICON_RES, new FieldDiff<>(from.iconResName, to.iconResName)); } if (from.userModifiedFields != to.userModifiedFields) { addField(FIELD_USER_MODIFIED_FIELDS, new FieldDiff<>(from.userModifiedFields, to.userModifiedFields)); } } } Loading
services/core/java/com/android/server/notification/NotificationManagerService.java +3 −3 Original line number Diff line number Diff line Loading @@ -215,7 +215,6 @@ import android.content.IntentFilter; import android.content.pm.ApplicationInfo; import android.content.pm.IPackageManager; import android.content.pm.LauncherApps; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.PackageManagerInternal; Loading Loading @@ -373,6 +372,7 @@ import java.io.InputStream; import java.io.OutputStream; import java.io.PrintWriter; import java.nio.charset.StandardCharsets; import java.time.Clock; import java.time.Duration; import java.util.ArrayList; import java.util.Arrays; Loading Loading @@ -2466,8 +2466,8 @@ public class NotificationManagerService extends SystemService { mMetricsLogger = new MetricsLogger(); mRankingHandler = rankingHandler; mConditionProviders = conditionProviders; mZenModeHelper = new ZenModeHelper(getContext(), mHandler.getLooper(), mConditionProviders, flagResolver, new ZenModeEventLogger(mPackageManagerClient)); mZenModeHelper = new ZenModeHelper(getContext(), mHandler.getLooper(), Clock.systemUTC(), mConditionProviders, flagResolver, new ZenModeEventLogger(mPackageManagerClient)); mZenModeHelper.addCallback(new ZenModeHelper.Callback() { @Override public void onConfigChanged() { Loading
services/core/java/com/android/server/notification/ZenModeHelper.java +125 −21 File changed.Preview size limit exceeded, changes collapsed. Show changes
services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java +6 −1 Original line number Diff line number Diff line Loading @@ -60,6 +60,7 @@ import java.io.BufferedOutputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.time.Instant; @SmallTest @RunWith(AndroidJUnit4.class) Loading Loading @@ -407,6 +408,7 @@ public class ZenModeConfigTest extends UiServiceTestCase { rule.userModifiedFields = 16; rule.iconResName = ICON_RES_NAME; rule.triggerDescription = TRIGGER_DESC; rule.deletionInstant = Instant.ofEpochMilli(1701790147000L); Parcel parcel = Parcel.obtain(); rule.writeToParcel(parcel, 0); Loading @@ -432,9 +434,10 @@ public class ZenModeConfigTest extends UiServiceTestCase { assertEquals(rule.userModifiedFields, parceled.userModifiedFields); assertEquals(rule.triggerDescription, parceled.triggerDescription); assertEquals(rule.zenPolicy, parceled.zenPolicy); assertEquals(rule.deletionInstant, parceled.deletionInstant); assertEquals(rule, parceled); assertEquals(rule.hashCode(), parceled.hashCode()); } @Test Loading Loading @@ -510,6 +513,7 @@ public class ZenModeConfigTest extends UiServiceTestCase { rule.userModifiedFields = 4; rule.iconResName = ICON_RES_NAME; rule.triggerDescription = TRIGGER_DESC; rule.deletionInstant = Instant.ofEpochMilli(1701790147000L); ByteArrayOutputStream baos = new ByteArrayOutputStream(); writeRuleXml(rule, baos); Loading Loading @@ -539,6 +543,7 @@ public class ZenModeConfigTest extends UiServiceTestCase { assertEquals(rule.userModifiedFields, fromXml.userModifiedFields); assertEquals(rule.triggerDescription, fromXml.triggerDescription); assertEquals(rule.iconResName, fromXml.iconResName); assertEquals(rule.deletionInstant, fromXml.deletionInstant); } @Test Loading