Loading core/java/android/service/notification/ZenPolicy.java +5 −1 Original line number Diff line number Diff line Loading @@ -1241,7 +1241,7 @@ public final class ZenPolicy implements Parcelable { * @hide */ public byte[] toProto() { // TODO: b/308672510 - log new ZenPolicy fields to DNDPolicyProto. // TODO: b/308672510 - log user-customized ZenPolicy fields to DNDPolicyProto. ByteArrayOutputStream bytes = new ByteArrayOutputStream(); ProtoOutputStream proto = new ProtoOutputStream(bytes); Loading @@ -1267,6 +1267,10 @@ public final class ZenPolicy implements Parcelable { proto.write(DNDPolicyProto.ALLOW_MESSAGES_FROM, getPriorityMessageSenders()); proto.write(DNDPolicyProto.ALLOW_CONVERSATIONS_FROM, getPriorityConversationSenders()); if (Flags.modesApi()) { proto.write(DNDPolicyProto.ALLOW_CHANNELS, getAllowedChannels()); } proto.flush(); return bytes.toByteArray(); } Loading core/proto/android/service/notification.proto +10 −0 Original line number Diff line number Diff line Loading @@ -359,6 +359,8 @@ message DNDPolicyProto { optional PeopleType allow_messages_from = 18; optional ConversationType allow_conversations_from = 19; optional ChannelType allow_channels = 20; } // Enum identifying the type of rule that changed; values set to match ones used in the Loading @@ -368,3 +370,11 @@ enum RuleType { RULE_TYPE_MANUAL = 1; RULE_TYPE_AUTOMATIC = 2; } // Enum used in DNDPolicyProto to indicate the type of channels permitted to // break through DND. Mirrors values in ZenPolicy. enum ChannelType { CHANNEL_TYPE_UNSET = 0; CHANNEL_TYPE_PRIORITY = 1; CHANNEL_TYPE_NONE = 2; } services/core/java/com/android/server/notification/ZenModeEventLogger.java +8 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ import static android.service.notification.NotificationServiceProto.RULE_TYPE_MA import static android.service.notification.NotificationServiceProto.RULE_TYPE_UNKNOWN; import android.annotation.NonNull; import android.app.Flags; import android.app.NotificationManager; import android.content.pm.PackageManager; import android.os.Process; Loading Loading @@ -502,6 +503,13 @@ class ZenModeEventLogger { ZenModeConfig.getZenPolicySenders(mNewPolicy.allowMessagesFrom())); proto.write(DNDPolicyProto.ALLOW_CONVERSATIONS_FROM, mNewPolicy.allowConversationsFrom()); if (Flags.modesApi()) { proto.write(DNDPolicyProto.ALLOW_CHANNELS, mNewPolicy.allowPriorityChannels() ? ZenPolicy.CHANNEL_TYPE_PRIORITY : ZenPolicy.CHANNEL_TYPE_NONE); } } else { Log.wtf(TAG, "attempted to write zen mode log event with null policy"); } Loading services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java +132 −0 Original line number Diff line number Diff line Loading @@ -1051,6 +1051,88 @@ public class ZenModeHelperTest extends UiServiceTestCase { assertEquals("default ID(s) not found", 0, ids.size()); } @Test public void testProtoWithAutoRuleCustomPolicy_classic() throws Exception { setupZenConfig(); // clear any automatic rules just to make sure mZenModeHelper.mConfig.automaticRules = new ArrayMap<>(); // Add an automatic rule with a custom policy ZenRule rule = createCustomAutomaticRule(ZEN_MODE_IMPORTANT_INTERRUPTIONS, CUSTOM_RULE_ID); rule.zenPolicy = new ZenPolicy.Builder() .allowAlarms(true) .allowRepeatCallers(false) .allowCalls(PEOPLE_TYPE_STARRED) .build(); mZenModeHelper.mConfig.automaticRules.put(rule.id, rule); List<StatsEvent> events = new LinkedList<>(); mZenModeHelper.pullRules(events); boolean foundCustomEvent = false; for (StatsEvent ev : events) { AtomsProto.Atom atom = StatsEventTestUtils.convertToAtom(ev); assertTrue(atom.hasDndModeRule()); DNDModeProto cfg = atom.getDndModeRule(); if (cfg.getUid() == CUSTOM_PKG_UID) { foundCustomEvent = true; // Check that the pieces of the policy are applied. assertThat(cfg.hasPolicy()).isTrue(); DNDPolicyProto policy = cfg.getPolicy(); assertThat(policy.getAlarms().getNumber()).isEqualTo(DNDProtoEnums.STATE_ALLOW); assertThat(policy.getRepeatCallers().getNumber()) .isEqualTo(DNDProtoEnums.STATE_DISALLOW); assertThat(policy.getCalls().getNumber()).isEqualTo(DNDProtoEnums.STATE_ALLOW); assertThat(policy.getAllowCallsFrom().getNumber()) .isEqualTo(DNDProtoEnums.PEOPLE_STARRED); } } assertTrue("couldn't find custom rule", foundCustomEvent); } @Test public void testProtoWithAutoRuleCustomPolicy() throws Exception { // allowChannels is only valid under modes_api. mSetFlagsRule.enableFlags(Flags.FLAG_MODES_API); setupZenConfig(); // clear any automatic rules just to make sure mZenModeHelper.mConfig.automaticRules = new ArrayMap<>(); // Add an automatic rule with a custom policy ZenRule rule = createCustomAutomaticRule(ZEN_MODE_IMPORTANT_INTERRUPTIONS, CUSTOM_RULE_ID); rule.zenPolicy = new ZenPolicy.Builder() .allowAlarms(true) .allowRepeatCallers(false) .allowCalls(PEOPLE_TYPE_STARRED) .allowChannels(ZenPolicy.CHANNEL_TYPE_NONE) .build(); mZenModeHelper.mConfig.automaticRules.put(rule.id, rule); List<StatsEvent> events = new LinkedList<>(); mZenModeHelper.pullRules(events); boolean foundCustomEvent = false; for (StatsEvent ev : events) { AtomsProto.Atom atom = StatsEventTestUtils.convertToAtom(ev); assertTrue(atom.hasDndModeRule()); DNDModeProto cfg = atom.getDndModeRule(); if (cfg.getUid() == CUSTOM_PKG_UID) { foundCustomEvent = true; // Check that the pieces of the policy are applied. assertThat(cfg.hasPolicy()).isTrue(); DNDPolicyProto policy = cfg.getPolicy(); assertThat(policy.getAlarms().getNumber()).isEqualTo(DNDProtoEnums.STATE_ALLOW); assertThat(policy.getRepeatCallers().getNumber()) .isEqualTo(DNDProtoEnums.STATE_DISALLOW); assertThat(policy.getCalls().getNumber()).isEqualTo(DNDProtoEnums.STATE_ALLOW); assertThat(policy.getAllowCallsFrom().getNumber()) .isEqualTo(DNDProtoEnums.PEOPLE_STARRED); assertThat(policy.getAllowChannels().getNumber()) .isEqualTo(DNDProtoEnums.CHANNEL_TYPE_NONE); } } assertTrue("couldn't find custom rule", foundCustomEvent); } @Test public void ruleUidsCached() throws Exception { setupZenConfig(); Loading Loading @@ -2721,6 +2803,55 @@ public class ZenModeHelperTest extends UiServiceTestCase { assertEquals(12345, mZenModeEventLogger.getPackageUid(4)); } @Test public void testZenModeEventLog_policyAllowChannels() { // when modes_api flag is on, ensure that any change in allow_channels gets logged, // even when there are no other changes. mTestFlagResolver.setFlagOverride(LOG_DND_STATE_EVENTS, true); mSetFlagsRule.enableFlags(Flags.FLAG_MODES_API); // Default zen config has allow channels = priority (aka on) setupZenConfig(); // First just turn zen mode on mZenModeHelper.setManualZenMode(ZEN_MODE_IMPORTANT_INTERRUPTIONS, null, null, "", Process.SYSTEM_UID, true); // Now change only the channels part of the policy; want to confirm that this'll be // reflected in the logs ZenModeConfig newConfig = mZenModeHelper.mConfig.copy(); newConfig.allowPriorityChannels = false; mZenModeHelper.setNotificationPolicy(newConfig.toNotificationPolicy(), Process.SYSTEM_UID, true); // Total events: one for turning on, one for changing policy assertThat(mZenModeEventLogger.numLoggedChanges()).isEqualTo(2); // The first event is just turning DND on; make sure the policy is what we expect there // before it changes in the next stage assertThat(mZenModeEventLogger.getEventId(0)) .isEqualTo(ZenModeEventLogger.ZenStateChangedEvent.DND_TURNED_ON.getId()); DNDPolicyProto origDndProto = mZenModeEventLogger.getPolicyProto(0); checkDndProtoMatchesSetupZenConfig(origDndProto); assertThat(origDndProto.getAllowChannels().getNumber()) .isEqualTo(DNDProtoEnums.CHANNEL_TYPE_PRIORITY); // Second message where we change the policy: // - DND_POLICY_CHANGED (indicates only the policy changed and nothing else) // - rule type: unknown (it's a policy change, not a rule change) // - user action (because it comes from a "system" uid) // - change is in allow channels, and final policy assertThat(mZenModeEventLogger.getEventId(1)) .isEqualTo(ZenModeEventLogger.ZenStateChangedEvent.DND_POLICY_CHANGED.getId()); assertThat(mZenModeEventLogger.getChangedRuleType(1)) .isEqualTo(DNDProtoEnums.UNKNOWN_RULE); assertThat(mZenModeEventLogger.getIsUserAction(1)).isTrue(); assertThat(mZenModeEventLogger.getPackageUid(1)).isEqualTo(Process.SYSTEM_UID); DNDPolicyProto dndProto = mZenModeEventLogger.getPolicyProto(1); assertThat(dndProto.getAllowChannels().getNumber()) .isEqualTo(DNDProtoEnums.CHANNEL_TYPE_NONE); } @Test public void testUpdateConsolidatedPolicy_defaultRulesOnly() { setupZenConfig(); Loading Loading @@ -3416,6 +3547,7 @@ public class ZenModeHelperTest extends UiServiceTestCase { return rule; } // TODO: b/310620812 - Update setup methods to include allowChannels() when MODES_API is inlined private void setupZenConfig() { mZenModeHelper.mZenMode = ZEN_MODE_OFF; mZenModeHelper.mConfig.allowAlarms = false; Loading Loading
core/java/android/service/notification/ZenPolicy.java +5 −1 Original line number Diff line number Diff line Loading @@ -1241,7 +1241,7 @@ public final class ZenPolicy implements Parcelable { * @hide */ public byte[] toProto() { // TODO: b/308672510 - log new ZenPolicy fields to DNDPolicyProto. // TODO: b/308672510 - log user-customized ZenPolicy fields to DNDPolicyProto. ByteArrayOutputStream bytes = new ByteArrayOutputStream(); ProtoOutputStream proto = new ProtoOutputStream(bytes); Loading @@ -1267,6 +1267,10 @@ public final class ZenPolicy implements Parcelable { proto.write(DNDPolicyProto.ALLOW_MESSAGES_FROM, getPriorityMessageSenders()); proto.write(DNDPolicyProto.ALLOW_CONVERSATIONS_FROM, getPriorityConversationSenders()); if (Flags.modesApi()) { proto.write(DNDPolicyProto.ALLOW_CHANNELS, getAllowedChannels()); } proto.flush(); return bytes.toByteArray(); } Loading
core/proto/android/service/notification.proto +10 −0 Original line number Diff line number Diff line Loading @@ -359,6 +359,8 @@ message DNDPolicyProto { optional PeopleType allow_messages_from = 18; optional ConversationType allow_conversations_from = 19; optional ChannelType allow_channels = 20; } // Enum identifying the type of rule that changed; values set to match ones used in the Loading @@ -368,3 +370,11 @@ enum RuleType { RULE_TYPE_MANUAL = 1; RULE_TYPE_AUTOMATIC = 2; } // Enum used in DNDPolicyProto to indicate the type of channels permitted to // break through DND. Mirrors values in ZenPolicy. enum ChannelType { CHANNEL_TYPE_UNSET = 0; CHANNEL_TYPE_PRIORITY = 1; CHANNEL_TYPE_NONE = 2; }
services/core/java/com/android/server/notification/ZenModeEventLogger.java +8 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ import static android.service.notification.NotificationServiceProto.RULE_TYPE_MA import static android.service.notification.NotificationServiceProto.RULE_TYPE_UNKNOWN; import android.annotation.NonNull; import android.app.Flags; import android.app.NotificationManager; import android.content.pm.PackageManager; import android.os.Process; Loading Loading @@ -502,6 +503,13 @@ class ZenModeEventLogger { ZenModeConfig.getZenPolicySenders(mNewPolicy.allowMessagesFrom())); proto.write(DNDPolicyProto.ALLOW_CONVERSATIONS_FROM, mNewPolicy.allowConversationsFrom()); if (Flags.modesApi()) { proto.write(DNDPolicyProto.ALLOW_CHANNELS, mNewPolicy.allowPriorityChannels() ? ZenPolicy.CHANNEL_TYPE_PRIORITY : ZenPolicy.CHANNEL_TYPE_NONE); } } else { Log.wtf(TAG, "attempted to write zen mode log event with null policy"); } Loading
services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java +132 −0 Original line number Diff line number Diff line Loading @@ -1051,6 +1051,88 @@ public class ZenModeHelperTest extends UiServiceTestCase { assertEquals("default ID(s) not found", 0, ids.size()); } @Test public void testProtoWithAutoRuleCustomPolicy_classic() throws Exception { setupZenConfig(); // clear any automatic rules just to make sure mZenModeHelper.mConfig.automaticRules = new ArrayMap<>(); // Add an automatic rule with a custom policy ZenRule rule = createCustomAutomaticRule(ZEN_MODE_IMPORTANT_INTERRUPTIONS, CUSTOM_RULE_ID); rule.zenPolicy = new ZenPolicy.Builder() .allowAlarms(true) .allowRepeatCallers(false) .allowCalls(PEOPLE_TYPE_STARRED) .build(); mZenModeHelper.mConfig.automaticRules.put(rule.id, rule); List<StatsEvent> events = new LinkedList<>(); mZenModeHelper.pullRules(events); boolean foundCustomEvent = false; for (StatsEvent ev : events) { AtomsProto.Atom atom = StatsEventTestUtils.convertToAtom(ev); assertTrue(atom.hasDndModeRule()); DNDModeProto cfg = atom.getDndModeRule(); if (cfg.getUid() == CUSTOM_PKG_UID) { foundCustomEvent = true; // Check that the pieces of the policy are applied. assertThat(cfg.hasPolicy()).isTrue(); DNDPolicyProto policy = cfg.getPolicy(); assertThat(policy.getAlarms().getNumber()).isEqualTo(DNDProtoEnums.STATE_ALLOW); assertThat(policy.getRepeatCallers().getNumber()) .isEqualTo(DNDProtoEnums.STATE_DISALLOW); assertThat(policy.getCalls().getNumber()).isEqualTo(DNDProtoEnums.STATE_ALLOW); assertThat(policy.getAllowCallsFrom().getNumber()) .isEqualTo(DNDProtoEnums.PEOPLE_STARRED); } } assertTrue("couldn't find custom rule", foundCustomEvent); } @Test public void testProtoWithAutoRuleCustomPolicy() throws Exception { // allowChannels is only valid under modes_api. mSetFlagsRule.enableFlags(Flags.FLAG_MODES_API); setupZenConfig(); // clear any automatic rules just to make sure mZenModeHelper.mConfig.automaticRules = new ArrayMap<>(); // Add an automatic rule with a custom policy ZenRule rule = createCustomAutomaticRule(ZEN_MODE_IMPORTANT_INTERRUPTIONS, CUSTOM_RULE_ID); rule.zenPolicy = new ZenPolicy.Builder() .allowAlarms(true) .allowRepeatCallers(false) .allowCalls(PEOPLE_TYPE_STARRED) .allowChannels(ZenPolicy.CHANNEL_TYPE_NONE) .build(); mZenModeHelper.mConfig.automaticRules.put(rule.id, rule); List<StatsEvent> events = new LinkedList<>(); mZenModeHelper.pullRules(events); boolean foundCustomEvent = false; for (StatsEvent ev : events) { AtomsProto.Atom atom = StatsEventTestUtils.convertToAtom(ev); assertTrue(atom.hasDndModeRule()); DNDModeProto cfg = atom.getDndModeRule(); if (cfg.getUid() == CUSTOM_PKG_UID) { foundCustomEvent = true; // Check that the pieces of the policy are applied. assertThat(cfg.hasPolicy()).isTrue(); DNDPolicyProto policy = cfg.getPolicy(); assertThat(policy.getAlarms().getNumber()).isEqualTo(DNDProtoEnums.STATE_ALLOW); assertThat(policy.getRepeatCallers().getNumber()) .isEqualTo(DNDProtoEnums.STATE_DISALLOW); assertThat(policy.getCalls().getNumber()).isEqualTo(DNDProtoEnums.STATE_ALLOW); assertThat(policy.getAllowCallsFrom().getNumber()) .isEqualTo(DNDProtoEnums.PEOPLE_STARRED); assertThat(policy.getAllowChannels().getNumber()) .isEqualTo(DNDProtoEnums.CHANNEL_TYPE_NONE); } } assertTrue("couldn't find custom rule", foundCustomEvent); } @Test public void ruleUidsCached() throws Exception { setupZenConfig(); Loading Loading @@ -2721,6 +2803,55 @@ public class ZenModeHelperTest extends UiServiceTestCase { assertEquals(12345, mZenModeEventLogger.getPackageUid(4)); } @Test public void testZenModeEventLog_policyAllowChannels() { // when modes_api flag is on, ensure that any change in allow_channels gets logged, // even when there are no other changes. mTestFlagResolver.setFlagOverride(LOG_DND_STATE_EVENTS, true); mSetFlagsRule.enableFlags(Flags.FLAG_MODES_API); // Default zen config has allow channels = priority (aka on) setupZenConfig(); // First just turn zen mode on mZenModeHelper.setManualZenMode(ZEN_MODE_IMPORTANT_INTERRUPTIONS, null, null, "", Process.SYSTEM_UID, true); // Now change only the channels part of the policy; want to confirm that this'll be // reflected in the logs ZenModeConfig newConfig = mZenModeHelper.mConfig.copy(); newConfig.allowPriorityChannels = false; mZenModeHelper.setNotificationPolicy(newConfig.toNotificationPolicy(), Process.SYSTEM_UID, true); // Total events: one for turning on, one for changing policy assertThat(mZenModeEventLogger.numLoggedChanges()).isEqualTo(2); // The first event is just turning DND on; make sure the policy is what we expect there // before it changes in the next stage assertThat(mZenModeEventLogger.getEventId(0)) .isEqualTo(ZenModeEventLogger.ZenStateChangedEvent.DND_TURNED_ON.getId()); DNDPolicyProto origDndProto = mZenModeEventLogger.getPolicyProto(0); checkDndProtoMatchesSetupZenConfig(origDndProto); assertThat(origDndProto.getAllowChannels().getNumber()) .isEqualTo(DNDProtoEnums.CHANNEL_TYPE_PRIORITY); // Second message where we change the policy: // - DND_POLICY_CHANGED (indicates only the policy changed and nothing else) // - rule type: unknown (it's a policy change, not a rule change) // - user action (because it comes from a "system" uid) // - change is in allow channels, and final policy assertThat(mZenModeEventLogger.getEventId(1)) .isEqualTo(ZenModeEventLogger.ZenStateChangedEvent.DND_POLICY_CHANGED.getId()); assertThat(mZenModeEventLogger.getChangedRuleType(1)) .isEqualTo(DNDProtoEnums.UNKNOWN_RULE); assertThat(mZenModeEventLogger.getIsUserAction(1)).isTrue(); assertThat(mZenModeEventLogger.getPackageUid(1)).isEqualTo(Process.SYSTEM_UID); DNDPolicyProto dndProto = mZenModeEventLogger.getPolicyProto(1); assertThat(dndProto.getAllowChannels().getNumber()) .isEqualTo(DNDProtoEnums.CHANNEL_TYPE_NONE); } @Test public void testUpdateConsolidatedPolicy_defaultRulesOnly() { setupZenConfig(); Loading Loading @@ -3416,6 +3547,7 @@ public class ZenModeHelperTest extends UiServiceTestCase { return rule; } // TODO: b/310620812 - Update setup methods to include allowChannels() when MODES_API is inlined private void setupZenConfig() { mZenModeHelper.mZenMode = ZEN_MODE_OFF; mZenModeHelper.mConfig.allowAlarms = false; Loading