diff options
4 files changed, 155 insertions, 1 deletions
diff --git a/core/java/android/service/notification/ZenPolicy.java b/core/java/android/service/notification/ZenPolicy.java index 3a4a0c5dcd30..b1680abfadeb 100644 --- a/core/java/android/service/notification/ZenPolicy.java +++ b/core/java/android/service/notification/ZenPolicy.java @@ -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); @@ -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(); } diff --git a/core/proto/android/service/notification.proto b/core/proto/android/service/notification.proto index 17ca7c80707c..a2978bec16b5 100644 --- a/core/proto/android/service/notification.proto +++ b/core/proto/android/service/notification.proto @@ -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 @@ -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; +} diff --git a/services/core/java/com/android/server/notification/ZenModeEventLogger.java b/services/core/java/com/android/server/notification/ZenModeEventLogger.java index 1641d4a6ed46..87158cd6fe29 100644 --- a/services/core/java/com/android/server/notification/ZenModeEventLogger.java +++ b/services/core/java/com/android/server/notification/ZenModeEventLogger.java @@ -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; @@ -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"); } 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 a44986af88a8..4d25eaab1f49 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java @@ -1052,6 +1052,88 @@ public class ZenModeHelperTest extends UiServiceTestCase { } @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(); // one enabled automatic rule @@ -2722,6 +2804,55 @@ public class ZenModeHelperTest extends UiServiceTestCase { } @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(); @@ -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; |