summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/service/notification/ZenModeConfig.java49
-rw-r--r--services/core/java/com/android/server/notification/ZenModeHelper.java12
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java12
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/ZenModeDiffTest.java11
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java95
5 files changed, 166 insertions, 13 deletions
diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java
index a3afcce5fe36..863a99adacca 100644
--- a/core/java/android/service/notification/ZenModeConfig.java
+++ b/core/java/android/service/notification/ZenModeConfig.java
@@ -262,15 +262,12 @@ public class ZenModeConfig implements Parcelable {
private static final String CONDITION_ATT_SOURCE = "source";
private static final String CONDITION_ATT_FLAGS = "flags";
- private static final String ZEN_POLICY_TAG = "zen_policy";
-
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";
- 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";
@@ -286,6 +283,7 @@ public class ZenModeConfig implements Parcelable {
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 RULE_ATT_DISABLED_ORIGIN = "disabledOrigin";
private static final String DEVICE_EFFECT_DISPLAY_GRAYSCALE = "zdeDisplayGrayscale";
private static final String DEVICE_EFFECT_SUPPRESS_AMBIENT_DISPLAY =
@@ -1170,6 +1168,10 @@ public class ZenModeConfig implements Parcelable {
if (deletionInstant != null) {
rt.deletionInstant = Instant.ofEpochMilli(deletionInstant);
}
+ if (Flags.modesUi()) {
+ rt.disabledOrigin = safeInt(parser, RULE_ATT_DISABLED_ORIGIN,
+ UPDATE_ORIGIN_UNKNOWN);
+ }
}
return rt;
}
@@ -1224,6 +1226,9 @@ public class ZenModeConfig implements Parcelable {
out.attributeLong(null, RULE_ATT_DELETION_INSTANT,
rule.deletionInstant.toEpochMilli());
}
+ if (Flags.modesUi()) {
+ out.attributeInt(null, RULE_ATT_DISABLED_ORIGIN, rule.disabledOrigin);
+ }
}
}
@@ -2514,6 +2519,8 @@ public class ZenModeConfig implements Parcelable {
@ZenPolicy.ModifiableField public int zenPolicyUserModifiedFields;
@ZenDeviceEffects.ModifiableField public int zenDeviceEffectsUserModifiedFields;
@Nullable public Instant deletionInstant; // Only set on deleted rules.
+ @FlaggedApi(Flags.FLAG_MODES_UI)
+ @ConfigChangeOrigin public int disabledOrigin = UPDATE_ORIGIN_UNKNOWN;
public ZenRule() { }
@@ -2552,6 +2559,9 @@ public class ZenModeConfig implements Parcelable {
if (source.readInt() == 1) {
deletionInstant = Instant.ofEpochMilli(source.readLong());
}
+ if (Flags.modesUi()) {
+ disabledOrigin = source.readInt();
+ }
}
}
@@ -2626,6 +2636,9 @@ public class ZenModeConfig implements Parcelable {
} else {
dest.writeInt(0);
}
+ if (Flags.modesUi()) {
+ dest.writeInt(disabledOrigin);
+ }
}
}
@@ -2671,6 +2684,9 @@ public class ZenModeConfig implements Parcelable {
if (deletionInstant != null) {
sb.append(",deletionInstant=").append(deletionInstant);
}
+ if (Flags.modesUi()) {
+ sb.append(",disabledOrigin=").append(disabledOrigin);
+ }
}
return sb.append(']').toString();
@@ -2724,7 +2740,7 @@ public class ZenModeConfig implements Parcelable {
&& other.modified == modified;
if (Flags.modesApi()) {
- return finalEquals
+ finalEquals = finalEquals
&& Objects.equals(other.zenDeviceEffects, zenDeviceEffects)
&& other.allowManualInvocation == allowManualInvocation
&& Objects.equals(other.iconResName, iconResName)
@@ -2735,6 +2751,11 @@ public class ZenModeConfig implements Parcelable {
&& other.zenDeviceEffectsUserModifiedFields
== zenDeviceEffectsUserModifiedFields
&& Objects.equals(other.deletionInstant, deletionInstant);
+
+ if (Flags.modesUi()) {
+ finalEquals = finalEquals
+ && other.disabledOrigin == disabledOrigin;
+ }
}
return finalEquals;
@@ -2743,11 +2764,21 @@ public class ZenModeConfig implements Parcelable {
@Override
public int hashCode() {
if (Flags.modesApi()) {
- return Objects.hash(enabled, snoozing, name, zenMode, conditionId, condition,
- component, configurationActivity, pkg, id, enabler, zenPolicy,
- zenDeviceEffects, modified, allowManualInvocation, iconResName,
- triggerDescription, type, userModifiedFields, zenPolicyUserModifiedFields,
- zenDeviceEffectsUserModifiedFields, deletionInstant);
+ if (Flags.modesUi()) {
+ return Objects.hash(enabled, snoozing, name, zenMode, conditionId, condition,
+ component, configurationActivity, pkg, id, enabler, zenPolicy,
+ zenDeviceEffects, modified, allowManualInvocation, iconResName,
+ triggerDescription, type, userModifiedFields,
+ zenPolicyUserModifiedFields,
+ zenDeviceEffectsUserModifiedFields, deletionInstant, disabledOrigin);
+ } else {
+ return Objects.hash(enabled, snoozing, name, zenMode, conditionId, condition,
+ component, configurationActivity, pkg, id, enabler, zenPolicy,
+ zenDeviceEffects, modified, allowManualInvocation, iconResName,
+ triggerDescription, type, userModifiedFields,
+ zenPolicyUserModifiedFields,
+ zenDeviceEffectsUserModifiedFields, deletionInstant);
+ }
}
return Objects.hash(enabled, snoozing, name, zenMode, conditionId, condition,
component, configurationActivity, pkg, id, enabler, zenPolicy, modified);
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index 2e7295eca1a2..c078409f468c 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -34,6 +34,7 @@ import static android.service.notification.ZenModeConfig.UPDATE_ORIGIN_INIT;
import static android.service.notification.ZenModeConfig.UPDATE_ORIGIN_INIT_USER;
import static android.service.notification.ZenModeConfig.UPDATE_ORIGIN_RESTORE_BACKUP;
import static android.service.notification.ZenModeConfig.UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI;
+import static android.service.notification.ZenModeConfig.UPDATE_ORIGIN_UNKNOWN;
import static android.service.notification.ZenModeConfig.UPDATE_ORIGIN_USER;
import static com.android.internal.util.FrameworkStatsLog.DND_MODE_RULE;
@@ -1143,6 +1144,17 @@ public class ZenModeHelper {
modified = true;
}
+ if (Flags.modesUi()) {
+ if (!azr.isEnabled() && (isNew || rule.enabled)) {
+ // Creating a rule as disabled, or disabling a previously enabled rule.
+ // Record whodunit.
+ rule.disabledOrigin = origin;
+ } else if (azr.isEnabled()) {
+ // Enabling or previously enabled. Clear disabler.
+ rule.disabledOrigin = UPDATE_ORIGIN_UNKNOWN;
+ }
+ }
+
if (!Objects.equals(rule.conditionId, azr.getConditionId())) {
rule.conditionId = azr.getConditionId();
modified = true;
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 9352c1287ee1..f5ab95c1ab4c 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java
@@ -511,6 +511,9 @@ public class ZenModeConfigTest extends UiServiceTestCase {
rule.iconResName = ICON_RES_NAME;
rule.triggerDescription = TRIGGER_DESC;
rule.deletionInstant = Instant.ofEpochMilli(1701790147000L);
+ if (Flags.modesUi()) {
+ rule.disabledOrigin = ZenModeConfig.UPDATE_ORIGIN_USER;
+ }
Parcel parcel = Parcel.obtain();
rule.writeToParcel(parcel, 0);
@@ -540,6 +543,9 @@ public class ZenModeConfigTest extends UiServiceTestCase {
assertEquals(rule.triggerDescription, parceled.triggerDescription);
assertEquals(rule.zenPolicy, parceled.zenPolicy);
assertEquals(rule.deletionInstant, parceled.deletionInstant);
+ if (Flags.modesUi()) {
+ assertEquals(rule.disabledOrigin, parceled.disabledOrigin);
+ }
assertEquals(rule, parceled);
assertEquals(rule.hashCode(), parceled.hashCode());
@@ -620,6 +626,9 @@ public class ZenModeConfigTest extends UiServiceTestCase {
rule.iconResName = ICON_RES_NAME;
rule.triggerDescription = TRIGGER_DESC;
rule.deletionInstant = Instant.ofEpochMilli(1701790147000L);
+ if (Flags.modesUi()) {
+ rule.disabledOrigin = ZenModeConfig.UPDATE_ORIGIN_APP;
+ }
ByteArrayOutputStream baos = new ByteArrayOutputStream();
writeRuleXml(rule, baos);
@@ -653,6 +662,9 @@ public class ZenModeConfigTest extends UiServiceTestCase {
assertEquals(rule.triggerDescription, fromXml.triggerDescription);
assertEquals(rule.iconResName, fromXml.iconResName);
assertEquals(rule.deletionInstant, fromXml.deletionInstant);
+ if (Flags.modesUi()) {
+ assertEquals(rule.disabledOrigin, fromXml.disabledOrigin);
+ }
}
@Test
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeDiffTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeDiffTest.java
index 26a13cb47563..57587f7dc38a 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeDiffTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeDiffTest.java
@@ -16,6 +16,7 @@
package com.android.server.notification;
+import static android.app.Flags.FLAG_MODES_API;
import static android.app.Flags.FLAG_MODES_UI;
import static com.google.common.truth.Truth.assertThat;
@@ -32,6 +33,7 @@ import android.app.Flags;
import android.app.NotificationManager;
import android.content.ComponentName;
import android.net.Uri;
+import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.FlagsParameterization;
import android.platform.test.flag.junit.SetFlagsRule;
import android.provider.Settings;
@@ -79,16 +81,17 @@ public class ZenModeDiffTest extends UiServiceTestCase {
: Set.of("version", "manualRule", "automaticRules");
// Differences for flagged fields are only generated if the flag is enabled.
- // "Metadata" fields (userModifiedFields & co, deletionInstant) are not compared.
+ // "Metadata" fields (userModifiedFields, deletionInstant, disabledOrigin) are not compared.
private static final Set<String> ZEN_RULE_EXEMPT_FIELDS =
android.app.Flags.modesApi()
? Set.of("userModifiedFields", "zenPolicyUserModifiedFields",
- "zenDeviceEffectsUserModifiedFields", "deletionInstant")
+ "zenDeviceEffectsUserModifiedFields", "deletionInstant",
+ "disabledOrigin")
: Set.of(RuleDiff.FIELD_TYPE, RuleDiff.FIELD_TRIGGER_DESCRIPTION,
RuleDiff.FIELD_ICON_RES, RuleDiff.FIELD_ALLOW_MANUAL,
RuleDiff.FIELD_ZEN_DEVICE_EFFECTS, "userModifiedFields",
"zenPolicyUserModifiedFields", "zenDeviceEffectsUserModifiedFields",
- "deletionInstant");
+ "deletionInstant", "disabledOrigin");
// allowPriorityChannels is flagged by android.app.modes_api
public static final Set<String> ZEN_MODE_CONFIG_FLAGGED_FIELDS =
@@ -201,8 +204,8 @@ public class ZenModeDiffTest extends UiServiceTestCase {
}
@Test
+ @EnableFlags(FLAG_MODES_API)
public void testConfigDiff_fieldDiffs_flagOn() throws Exception {
- mSetFlagsRule.enableFlags(Flags.FLAG_MODES_API);
// these two start the same
ZenModeConfig c1 = new ZenModeConfig();
ZenModeConfig c2 = new ZenModeConfig();
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 40b0d78f0640..7bb633e6e1e0 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
@@ -6226,6 +6226,101 @@ public class ZenModeHelperTest extends UiServiceTestCase {
assertThat(mZenModeHelper.getConfig().manualRule.zenDeviceEffects).isEqualTo(effects);
}
+ @Test
+ @EnableFlags({FLAG_MODES_API, FLAG_MODES_UI})
+ public void addAutomaticZenRule_startsDisabled_recordsDisabledOrigin() {
+ AutomaticZenRule startsDisabled = new AutomaticZenRule.Builder("Rule", Uri.EMPTY)
+ .setOwner(new ComponentName(mPkg, "SomeProvider"))
+ .setEnabled(false)
+ .build();
+
+ String ruleId = mZenModeHelper.addAutomaticZenRule(mPkg, startsDisabled, UPDATE_ORIGIN_APP,
+ "new", CUSTOM_PKG_UID);
+
+ assertThat(mZenModeHelper.mConfig.automaticRules.get(ruleId).disabledOrigin).isEqualTo(
+ UPDATE_ORIGIN_APP);
+ }
+
+ @Test
+ @EnableFlags({FLAG_MODES_API, FLAG_MODES_UI})
+ public void updateAutomaticZenRule_disabling_recordsDisabledOrigin() {
+ AutomaticZenRule startsEnabled = new AutomaticZenRule.Builder("Rule", Uri.EMPTY)
+ .setOwner(new ComponentName(mPkg, "SomeProvider"))
+ .setEnabled(true)
+ .build();
+ String ruleId = mZenModeHelper.addAutomaticZenRule(mPkg, startsEnabled, UPDATE_ORIGIN_APP,
+ "new", CUSTOM_PKG_UID);
+ assertThat(mZenModeHelper.mConfig.automaticRules.get(ruleId).disabledOrigin).isEqualTo(
+ UPDATE_ORIGIN_UNKNOWN);
+
+ AutomaticZenRule nowDisabled = new AutomaticZenRule.Builder(startsEnabled)
+ .setEnabled(false)
+ .build();
+ mZenModeHelper.updateAutomaticZenRule(ruleId, nowDisabled, UPDATE_ORIGIN_USER, "off",
+ Process.SYSTEM_UID);
+
+ assertThat(mZenModeHelper.mConfig.automaticRules.get(ruleId).disabledOrigin).isEqualTo(
+ UPDATE_ORIGIN_USER);
+ }
+
+ @Test
+ @EnableFlags({FLAG_MODES_API, FLAG_MODES_UI})
+ public void updateAutomaticZenRule_keepingDisabled_preservesPreviousDisabledOrigin() {
+ AutomaticZenRule startsEnabled = new AutomaticZenRule.Builder("Rule", Uri.EMPTY)
+ .setOwner(new ComponentName(mPkg, "SomeProvider"))
+ .setEnabled(true)
+ .build();
+ String ruleId = mZenModeHelper.addAutomaticZenRule(mPkg, startsEnabled, UPDATE_ORIGIN_APP,
+ "new", CUSTOM_PKG_UID);
+ AutomaticZenRule nowDisabled = new AutomaticZenRule.Builder(startsEnabled)
+ .setEnabled(false)
+ .build();
+ mZenModeHelper.updateAutomaticZenRule(ruleId, nowDisabled, UPDATE_ORIGIN_USER, "off",
+ Process.SYSTEM_UID);
+ assertThat(mZenModeHelper.mConfig.automaticRules.get(ruleId).disabledOrigin).isEqualTo(
+ UPDATE_ORIGIN_USER);
+
+ // Now update it again, for an unrelated reason with a different origin.
+ AutomaticZenRule nowRenamed = new AutomaticZenRule.Builder(nowDisabled)
+ .setName("Fancy pants rule")
+ .build();
+ mZenModeHelper.updateAutomaticZenRule(ruleId, nowRenamed, UPDATE_ORIGIN_APP, "update",
+ CUSTOM_PKG_UID);
+
+ // Identity of the disabler is preserved.
+ assertThat(mZenModeHelper.mConfig.automaticRules.get(ruleId).disabledOrigin).isEqualTo(
+ UPDATE_ORIGIN_USER);
+ }
+
+ @Test
+ @EnableFlags({FLAG_MODES_API, FLAG_MODES_UI})
+ public void updateAutomaticZenRule_enabling_clearsDisabledOrigin() {
+ AutomaticZenRule startsEnabled = new AutomaticZenRule.Builder("Rule", Uri.EMPTY)
+ .setOwner(new ComponentName(mPkg, "SomeProvider"))
+ .setEnabled(true)
+ .build();
+ String ruleId = mZenModeHelper.addAutomaticZenRule(mPkg, startsEnabled, UPDATE_ORIGIN_APP,
+ "new", CUSTOM_PKG_UID);
+ AutomaticZenRule nowDisabled = new AutomaticZenRule.Builder(startsEnabled)
+ .setEnabled(false)
+ .build();
+ mZenModeHelper.updateAutomaticZenRule(ruleId, nowDisabled, UPDATE_ORIGIN_USER, "off",
+ Process.SYSTEM_UID);
+ assertThat(mZenModeHelper.mConfig.automaticRules.get(ruleId).disabledOrigin).isEqualTo(
+ UPDATE_ORIGIN_USER);
+
+ // Now enable it again
+ AutomaticZenRule nowEnabled = new AutomaticZenRule.Builder(nowDisabled)
+ .setEnabled(true)
+ .build();
+ mZenModeHelper.updateAutomaticZenRule(ruleId, nowEnabled, UPDATE_ORIGIN_APP, "on",
+ CUSTOM_PKG_UID);
+
+ // Identity of the disabler was cleared.
+ assertThat(mZenModeHelper.mConfig.automaticRules.get(ruleId).disabledOrigin).isEqualTo(
+ UPDATE_ORIGIN_UNKNOWN);
+ }
+
private static void addZenRule(ZenModeConfig config, String id, String ownerPkg, int zenMode,
@Nullable ZenPolicy zenPolicy) {
ZenRule rule = new ZenRule();