summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/notification/ZenModeEventLogger.java42
-rw-r--r--services/core/java/com/android/server/notification/ZenModeHelper.java7
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/ZenModeEventLoggerFake.java5
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java100
4 files changed, 145 insertions, 9 deletions
diff --git a/services/core/java/com/android/server/notification/ZenModeEventLogger.java b/services/core/java/com/android/server/notification/ZenModeEventLogger.java
index df570a02eba5..0145577fb945 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.annotation.Nullable;
import android.app.Flags;
import android.app.NotificationManager;
import android.content.pm.PackageManager;
@@ -256,13 +257,21 @@ class ZenModeEventLogger {
return true;
}
+ if (Flags.modesApi() && hasActiveRuleCountDiff()) {
+ // Rules with INTERRUPTION_FILTER_ALL were always possible but before MODES_API
+ // they were completely useless; now they can apply effects, so we want to log
+ // when they become active/inactive, even though DND itself (as in "notification
+ // blocking") is off.
+ return true;
+ }
+
// If zen mode didn't change, did the policy or number of active rules change? We only
// care about changes that take effect while zen mode is on, so make sure the current
// zen mode is not "OFF"
if (mNewZenMode == ZEN_MODE_OFF) {
return false;
}
- return hasPolicyDiff() || hasRuleCountDiff();
+ return hasPolicyDiff() || hasActiveRuleCountDiff();
}
// Does the difference in zen mode go from off to on or vice versa?
@@ -294,6 +303,16 @@ class ZenModeEventLogger {
}
}
+ if (Flags.modesApi() && mNewZenMode == ZEN_MODE_OFF) {
+ // If the mode is OFF -> OFF then there cannot be any *effective* change to policy.
+ // (Note that, in theory, a policy diff is impossible since we don't merge the
+ // policies of INTERRUPTION_FILTER_ALL rules; this is a "just in case" check).
+ if (hasPolicyDiff() || hasChannelsBypassingDiff()) {
+ Log.wtf(TAG, "Detected policy diff even though DND is OFF and not toggled");
+ }
+ return ZenStateChangedEvent.DND_ACTIVE_RULES_CHANGED;
+ }
+
// zen mode didn't change; we must be here because of a policy change or rule change
if (hasPolicyDiff() || hasChannelsBypassingDiff()) {
return ZenStateChangedEvent.DND_POLICY_CHANGED;
@@ -345,7 +364,7 @@ class ZenModeEventLogger {
* Returns whether the previous config and new config have a different number of active
* automatic or manual rules.
*/
- private boolean hasRuleCountDiff() {
+ private boolean hasActiveRuleCountDiff() {
return numActiveRulesInConfig(mPrevConfig) != numActiveRulesInConfig(mNewConfig);
}
@@ -381,9 +400,11 @@ class ZenModeEventLogger {
// Determine the number of (automatic & manual) rules active after the change takes place.
int getNumRulesActive() {
- // If the zen mode has turned off, that means nothing can be active.
- if (mNewZenMode == ZEN_MODE_OFF) {
- return 0;
+ if (!Flags.modesApi()) {
+ // If the zen mode has turned off, that means nothing can be active.
+ if (mNewZenMode == ZEN_MODE_OFF) {
+ return 0;
+ }
}
return numActiveRulesInConfig(mNewConfig);
}
@@ -478,8 +499,19 @@ class ZenModeEventLogger {
/**
* Convert the new policy to a DNDPolicyProto format for output in logs.
+ *
+ * <p>If {@code mNewZenMode} is {@code ZEN_MODE_OFF} (which can mean either no rules
+ * active, or only rules with {@code INTERRUPTION_FILTER_ALL} active) then this returns
+ * {@code null} (which will be mapped to a missing submessage in the proto). Although this
+ * is not the value of {@code NotificationManager#getConsolidatedNotificationPolicy()}, it
+ * makes sense for logging since that policy is not actually influencing anything.
*/
+ @Nullable
byte[] getDNDPolicyProto() {
+ if (Flags.modesApi() && mNewZenMode == ZEN_MODE_OFF) {
+ return null;
+ }
+
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
ProtoOutputStream proto = new ProtoOutputStream(bytes);
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index 0a46901a93d1..b7a203814c94 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -1490,7 +1490,12 @@ public class ZenModeHelper {
for (ZenRule automaticRule : mConfig.automaticRules.values()) {
if (automaticRule.isAutomaticActive()) {
- applyCustomPolicy(policy, automaticRule);
+ // Active rules with INTERRUPTION_FILTER_ALL are not included in consolidated
+ // policy. This is relevant in case some other active rule has a more
+ // restrictive INTERRUPTION_FILTER but a more lenient ZenPolicy!
+ if (!Flags.modesApi() || automaticRule.zenMode != Global.ZEN_MODE_OFF) {
+ applyCustomPolicy(policy, automaticRule);
+ }
if (Flags.modesApi()) {
deviceEffectsBuilder.add(automaticRule.zenDeviceEffects);
}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeEventLoggerFake.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeEventLoggerFake.java
index 1fcee0658afc..5b35e345e46b 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeEventLoggerFake.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeEventLoggerFake.java
@@ -118,10 +118,13 @@ public class ZenModeEventLoggerFake extends ZenModeEventLogger {
public DNDPolicyProto getPolicyProto(int i) throws IllegalArgumentException {
checkInRange(i);
byte[] policyBytes = mChanges.get(i).getDNDPolicyProto();
+ if (policyBytes == null) {
+ return null;
+ }
try {
return DNDPolicyProto.parseFrom(policyBytes);
} catch (InvalidProtocolBufferException e) {
- return null; // couldn't turn it into proto
+ throw new RuntimeException("Couldn't parse DNDPolicyProto!", e);
}
}
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 44f0894f76d7..25c0cd9fae25 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
@@ -2429,7 +2429,11 @@ public class ZenModeHelperTest extends UiServiceTestCase {
assertEquals(0, mZenModeEventLogger.getNumRulesActive(1));
assertFalse(mZenModeEventLogger.getIsUserAction(1));
assertEquals(CUSTOM_PKG_UID, mZenModeEventLogger.getPackageUid(1));
- checkDndProtoMatchesSetupZenConfig(mZenModeEventLogger.getPolicyProto(1));
+ if (Flags.modesApi()) {
+ assertThat(mZenModeEventLogger.getPolicyProto(1)).isNull();
+ } else {
+ checkDndProtoMatchesSetupZenConfig(mZenModeEventLogger.getPolicyProto(1));
+ }
}
@Test
@@ -2511,7 +2515,11 @@ public class ZenModeHelperTest extends UiServiceTestCase {
assertEquals(0, mZenModeEventLogger.getNumRulesActive(1));
assertTrue(mZenModeEventLogger.getIsUserAction(1));
assertEquals(Process.SYSTEM_UID, mZenModeEventLogger.getPackageUid(1));
- checkDndProtoMatchesSetupZenConfig(mZenModeEventLogger.getPolicyProto(1));
+ if (Flags.modesApi()) {
+ assertThat(mZenModeEventLogger.getPolicyProto(1)).isNull();
+ } else {
+ checkDndProtoMatchesSetupZenConfig(mZenModeEventLogger.getPolicyProto(1));
+ }
// When the system rule is enabled, this counts as an automatic action that comes from the
// system and turns on DND
@@ -3016,6 +3024,48 @@ public class ZenModeHelperTest extends UiServiceTestCase {
}
@Test
+ @EnableFlags(Flags.FLAG_MODES_API)
+ public void testZenModeEventLog_ruleWithInterruptionFilterAll_notLoggedAsDndChange() {
+ mTestFlagResolver.setFlagOverride(LOG_DND_STATE_EVENTS, true);
+ setupZenConfig();
+
+ // An app adds an automatic zen rule
+ AutomaticZenRule zenRule = new AutomaticZenRule("name",
+ null,
+ new ComponentName(CUSTOM_PKG_NAME, "cls"),
+ Uri.parse("condition"),
+ null,
+ NotificationManager.INTERRUPTION_FILTER_ALL, true);
+ String id = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(), zenRule,
+ UPDATE_ORIGIN_APP, "test", CUSTOM_PKG_UID);
+
+ // Event 1: App activates the rule automatically.
+ mZenModeHelper.setAutomaticZenRuleState(id,
+ new Condition(zenRule.getConditionId(), "", STATE_TRUE, SOURCE_SCHEDULE),
+ UPDATE_ORIGIN_APP, CUSTOM_PKG_UID);
+
+ // Event 2: App deactivates the rule automatically.
+ mZenModeHelper.setAutomaticZenRuleState(id,
+ new Condition(zenRule.getConditionId(), "", STATE_FALSE, SOURCE_SCHEDULE),
+ UPDATE_ORIGIN_APP, CUSTOM_PKG_UID);
+
+ // In total, this represents 2 events.
+ assertEquals(2, mZenModeEventLogger.numLoggedChanges());
+
+ // However, they are not DND_TURNED_ON/_OFF (no notification filtering is taking place).
+ // Also, no consolidated ZenPolicy is logged (because of the same reason).
+ assertThat(mZenModeEventLogger.getEventId(0)).isEqualTo(
+ ZenModeEventLogger.ZenStateChangedEvent.DND_ACTIVE_RULES_CHANGED.getId());
+ assertThat(mZenModeEventLogger.getNumRulesActive(0)).isEqualTo(1);
+ assertThat(mZenModeEventLogger.getPolicyProto(0)).isNull();
+
+ assertThat(mZenModeEventLogger.getEventId(1)).isEqualTo(
+ ZenModeEventLogger.ZenStateChangedEvent.DND_ACTIVE_RULES_CHANGED.getId());
+ assertThat(mZenModeEventLogger.getNumRulesActive(1)).isEqualTo(0);
+ assertThat(mZenModeEventLogger.getPolicyProto(1)).isNull();
+ }
+
+ @Test
public void testUpdateConsolidatedPolicy_defaultRulesOnly() {
setupZenConfig();
@@ -3203,6 +3253,52 @@ public class ZenModeHelperTest extends UiServiceTestCase {
}
@Test
+ @EnableFlags(Flags.FLAG_MODES_API)
+ public void testUpdateConsolidatedPolicy_ignoresActiveRulesWithInterruptionFilterAll() {
+ setupZenConfig();
+
+ // Rules with INTERRUPTION_FILTER_ALL are skipped when calculating consolidated policy.
+ // Note: rules with filter != PRIORITY should not have a custom policy. However, as of V
+ // this is only validated on rule addition, but not on rule update. :/
+
+ // Rule 1: PRIORITY, custom policy but not very strict (in fact, less strict than default).
+ AutomaticZenRule zenRuleWithPriority = new AutomaticZenRule("Priority",
+ null,
+ new ComponentName(CUSTOM_PKG_NAME, "cls"),
+ Uri.parse("priority"),
+ new ZenPolicy.Builder().allowMedia(true).build(),
+ NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
+ String rule1Id = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(),
+ zenRuleWithPriority, UPDATE_ORIGIN_APP, "test", CUSTOM_PKG_UID);
+ mZenModeHelper.setAutomaticZenRuleState(rule1Id,
+ new Condition(zenRuleWithPriority.getConditionId(), "", STATE_TRUE),
+ UPDATE_ORIGIN_APP, CUSTOM_PKG_UID);
+
+ // Rule 2: ALL, but somehow with a super strict ZenPolicy.
+ AutomaticZenRule zenRuleWithAll = new AutomaticZenRule("All",
+ null,
+ new ComponentName(CUSTOM_PKG_NAME, "cls"),
+ Uri.parse("priority"),
+ new ZenPolicy.Builder().disallowAllSounds().build(),
+ NotificationManager.INTERRUPTION_FILTER_ALL, true);
+ String rule2Id = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(),
+ zenRuleWithAll, UPDATE_ORIGIN_APP, "test", CUSTOM_PKG_UID);
+ mZenModeHelper.setAutomaticZenRuleState(rule2Id,
+ new Condition(zenRuleWithPriority.getConditionId(), "", STATE_TRUE),
+ UPDATE_ORIGIN_APP, CUSTOM_PKG_UID);
+
+ // Consolidated Policy should be default + rule1.
+ assertThat(mZenModeHelper.mConsolidatedPolicy.allowAlarms()).isFalse(); // default
+ assertThat(mZenModeHelper.mConsolidatedPolicy.allowMedia()).isTrue(); // priority rule
+ assertThat(mZenModeHelper.mConsolidatedPolicy.allowSystem()).isFalse(); // default
+ assertThat(mZenModeHelper.mConsolidatedPolicy.allowReminders()).isTrue(); // default
+ assertThat(mZenModeHelper.mConsolidatedPolicy.allowCalls()).isTrue(); // default
+ assertThat(mZenModeHelper.mConsolidatedPolicy.allowMessages()).isTrue(); // default
+ assertThat(mZenModeHelper.mConsolidatedPolicy.allowConversations()).isTrue(); // default
+ assertThat(mZenModeHelper.mConsolidatedPolicy.allowRepeatCallers()).isTrue(); // default
+ }
+
+ @Test
public void zenRuleToAutomaticZenRule_allFields() {
mSetFlagsRule.enableFlags(Flags.FLAG_MODES_API);
when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(