summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Yuri Lin <yurilin@google.com> 2024-08-05 17:10:18 -0400
committer Yuri Lin <yurilin@google.com> 2024-08-06 14:46:35 -0400
commit0bd31d305a94847007f3b8ea309750d44632b71c (patch)
tree4f0bfc4a1635c391d30c9c25a1ffe4fab4dcddb9
parentdbb483a3a40b998a7672aaefedd851be617e59be (diff)
Fix manual rule on upgrade to modes_ui if DND was on
If the manual rule is present in the XML, we don't do any of the stuff to make the manual rule set up like a proper rule, with a non-null zenPolicy, etc, but that's incorrect if the manual rule only existed prior to Also does not restore the manual rule condition when restoring from a backup, which matches previous behavior. Fixes: 357161279 Test: ZenModeHelperTest, ZenModeConfigTest, manual by turning modes_ui off and then on both with DND on and DND on for a duration Flag: android.app.modes_ui Change-Id: I12e9d1713313aa0a3b626e79c66525b3db21056f
-rw-r--r--core/java/android/service/notification/ZenModeConfig.java41
-rw-r--r--services/core/java/com/android/server/notification/ZenModeHelper.java6
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java79
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java24
4 files changed, 137 insertions, 13 deletions
diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java
index 5e15e0160be4..224379b4fd98 100644
--- a/core/java/android/service/notification/ZenModeConfig.java
+++ b/core/java/android/service/notification/ZenModeConfig.java
@@ -25,6 +25,8 @@ import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_LIGHTS;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_OFF;
import static android.provider.Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+import static android.service.notification.Condition.STATE_TRUE;
+import static android.service.notification.SystemZenRules.PACKAGE_ANDROID;
import static android.service.notification.ZenAdapters.peopleTypeToPrioritySenders;
import static android.service.notification.ZenAdapters.prioritySendersToPeopleType;
import static android.service.notification.ZenAdapters.zenPolicyConversationSendersToNotificationPolicy;
@@ -454,7 +456,7 @@ public class ZenModeConfig implements Parcelable {
newRule.conditionId = Uri.EMPTY;
newRule.allowManualInvocation = true;
newRule.zenPolicy = getDefaultZenPolicy();
- newRule.pkg = "android";
+ newRule.pkg = PACKAGE_ANDROID;
manualRule = newRule;
}
}
@@ -957,15 +959,9 @@ public class ZenModeConfig implements Parcelable {
rt.user = safeInt(parser, ZEN_ATT_USER, rt.user);
boolean readSuppressedEffects = false;
boolean readManualRule = false;
+ boolean readManualRuleWithoutPolicy = false;
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
tag = parser.getName();
- if (type == XmlPullParser.END_TAG && ZEN_TAG.equals(tag)) {
- if (Flags.modesUi() && !readManualRule) {
- // migrate from fields on config into manual rule
- rt.manualRule.zenPolicy = rt.toZenPolicy();
- }
- return rt;
- }
if (type == XmlPullParser.START_TAG) {
if (ALLOW_TAG.equals(tag)) {
rt.allowCalls = safeBoolean(parser, ALLOW_ATT_CALLS,
@@ -1034,9 +1030,17 @@ public class ZenModeConfig implements Parcelable {
rt.suppressedVisualEffects = safeInt(parser, DISALLOW_ATT_VISUAL_EFFECTS,
DEFAULT_SUPPRESSED_VISUAL_EFFECTS);
} else if (MANUAL_TAG.equals(tag)) {
- rt.manualRule = readRuleXml(parser);
- if (rt.manualRule != null) {
+ ZenRule manualRule = readRuleXml(parser);
+ if (manualRule != null) {
+ rt.manualRule = manualRule;
+
+ // Manual rule may be present prior to modes_ui if it were on, but in that
+ // case it would not have a set policy, so make note of the need to set
+ // it up later.
readManualRule = true;
+ if (rt.manualRule.zenPolicy == null) {
+ readManualRuleWithoutPolicy = true;
+ }
}
} else if (AUTOMATIC_TAG.equals(tag)
|| (Flags.modesApi() && AUTOMATIC_DELETED_TAG.equals(tag))) {
@@ -1058,6 +1062,23 @@ public class ZenModeConfig implements Parcelable {
STATE_ATT_CHANNELS_BYPASSING_DND, DEFAULT_CHANNELS_BYPASSING_DND);
}
}
+ if (type == XmlPullParser.END_TAG && ZEN_TAG.equals(tag)) {
+ if (Flags.modesUi() && (!readManualRule || readManualRuleWithoutPolicy)) {
+ // migrate from fields on config into manual rule
+ rt.manualRule.zenPolicy = rt.toZenPolicy();
+ if (readManualRuleWithoutPolicy) {
+ // indicates that the xml represents a pre-modes_ui XML with an enabled
+ // manual rule; set rule active, and fill in other fields as would be done
+ // in ensureManualZenRule() and setManualZenMode().
+ rt.manualRule.pkg = PACKAGE_ANDROID;
+ rt.manualRule.type = AutomaticZenRule.TYPE_OTHER;
+ rt.manualRule.condition = new Condition(
+ rt.manualRule.conditionId != null ? rt.manualRule.conditionId
+ : Uri.EMPTY, "", STATE_TRUE);
+ }
+ }
+ return rt;
+ }
}
throw new IllegalStateException("Failed to reach END_DOCUMENT");
}
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index b164a52ff5d7..8c280edf03c0 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -1676,7 +1676,11 @@ public class ZenModeHelper {
if (config != null) {
if (forRestore) {
config.user = userId;
- if (!Flags.modesUi()) {
+ if (Flags.modesUi()) {
+ if (config.manualRule != null) {
+ config.manualRule.condition = null; // don't restore transient state
+ }
+ } else {
config.manualRule = null; // don't restore the manual rule
}
}
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 b955a795e94a..60c4ac777906 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java
@@ -31,6 +31,8 @@ import static android.service.notification.Condition.SOURCE_USER_ACTION;
import static android.service.notification.Condition.STATE_FALSE;
import static android.service.notification.Condition.STATE_TRUE;
import static android.service.notification.NotificationListenerService.SUPPRESSED_EFFECT_SCREEN_ON;
+import static android.service.notification.ZenModeConfig.XML_VERSION_MODES_API;
+import static android.service.notification.ZenModeConfig.ZEN_TAG;
import static android.service.notification.ZenPolicy.CONVERSATION_SENDERS_IMPORTANT;
import static android.service.notification.ZenPolicy.CONVERSATION_SENDERS_NONE;
import static android.service.notification.ZenPolicy.PEOPLE_TYPE_ANYONE;
@@ -283,8 +285,8 @@ public class ZenModeConfigTest extends UiServiceTestCase {
// the default value from the zen mode config.
Policy policy = config.toNotificationPolicy(zenPolicy);
assertEquals(Flags.modesUi()
- ? config.manualRule.zenPolicy.getPriorityChannelsAllowed() == STATE_ALLOW
- : config.isAllowPriorityChannels(),
+ ? config.manualRule.zenPolicy.getPriorityChannelsAllowed() == STATE_ALLOW
+ : config.isAllowPriorityChannels(),
policy.allowPriorityChannels());
}
@@ -991,6 +993,58 @@ public class ZenModeConfigTest extends UiServiceTestCase {
}
@Test
+ @EnableFlags(Flags.FLAG_MODES_UI)
+ public void testConfigXml_manualRule_upgradeWhenExisting() throws Exception {
+ // prior to modes_ui, it's possible to have a non-null manual rule that doesn't have much
+ // data on it because it's meant to indicate that the manual rule is on by merely existing.
+ ZenModeConfig config = new ZenModeConfig();
+ config.manualRule = new ZenModeConfig.ZenRule();
+ config.manualRule.enabled = true;
+ config.manualRule.pkg = "android";
+ config.manualRule.zenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+ config.manualRule.conditionId = ZenModeConfig.toTimeCondition(mContext, 200, mUserId).id;
+ config.manualRule.enabler = "test";
+
+ // write out entire config xml
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ writeConfigXml(config, XML_VERSION_MODES_API, /* forBackup= */ false, baos);
+ ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+ ZenModeConfig fromXml = readConfigXml(bais);
+
+ // The result should have a manual rule; it should have a non-null ZenPolicy and a condition
+ // whose state is true. The conditionId and enabler data should also be preserved.
+ assertThat(fromXml.manualRule).isNotNull();
+ assertThat(fromXml.manualRule.zenPolicy).isNotNull();
+ assertThat(fromXml.manualRule.condition).isNotNull();
+ assertThat(fromXml.manualRule.condition.state).isEqualTo(STATE_TRUE);
+ assertThat(fromXml.manualRule.conditionId).isEqualTo(config.manualRule.conditionId);
+ assertThat(fromXml.manualRule.enabler).isEqualTo("test");
+ assertThat(fromXml.isManualActive()).isTrue();
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_MODES_UI)
+ public void testConfigXml_manualRule_doesNotTurnOnIfNotUpgrade() throws Exception {
+ // confirm that if the manual rule is already properly set up for modes_ui, it does not get
+ // turned on (set to condition with STATE_TRUE) when reading xml.
+
+ // getMutedAllConfig sets up the manual rule with a policy muting everything
+ ZenModeConfig config = getMutedAllConfig();
+ config.manualRule.condition = new Condition(Uri.EMPTY, "", STATE_FALSE, SOURCE_USER_ACTION);
+ assertThat(config.isManualActive()).isFalse();
+
+ // write out entire config xml
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ writeConfigXml(config, XML_VERSION_MODES_API, /* forBackup= */ false, baos);
+ ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+ ZenModeConfig fromXml = readConfigXml(bais);
+
+ // The result should have a manual rule; it should not be changed from the previous rule.
+ assertThat(fromXml.manualRule).isEqualTo(config.manualRule);
+ assertThat(fromXml.isManualActive()).isFalse();
+ }
+
+ @Test
public void testGetDescription_off() {
ZenModeConfig config = new ZenModeConfig();
if (!modesUi()) {
@@ -1238,4 +1292,25 @@ public class ZenModeConfigTest extends UiServiceTestCase {
parser.nextTag();
return ZenModeConfig.readZenPolicyXml(parser);
}
+
+ private void writeConfigXml(ZenModeConfig config, Integer version, boolean forBackup,
+ ByteArrayOutputStream os) throws IOException {
+ String tag = ZEN_TAG;
+
+ TypedXmlSerializer out = Xml.newFastSerializer();
+ out.setOutput(new BufferedOutputStream(os), "utf-8");
+ out.startDocument(null, true);
+ out.startTag(null, tag);
+ config.writeXml(out, version, forBackup);
+ out.endTag(null, tag);
+ out.endDocument();
+ }
+
+ private ZenModeConfig readConfigXml(ByteArrayInputStream is)
+ throws XmlPullParserException, IOException {
+ TypedXmlPullParser parser = Xml.newFastPullParser();
+ parser.setInput(new BufferedInputStream(is), null);
+ parser.nextTag();
+ return ZenModeConfig.readXml(parser);
+ }
}
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 63cf1068f51e..776a840466c8 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
@@ -1495,6 +1495,30 @@ public class ZenModeHelperTest extends UiServiceTestCase {
}
@Test
+ public void testReadXmlRestore_doesNotEnableManualRule() throws Exception {
+ setupZenConfig();
+
+ // Turn on manual zen mode
+ mZenModeHelper.setManualZenMode(ZEN_MODE_IMPORTANT_INTERRUPTIONS, null,
+ ORIGIN_USER_IN_SYSTEMUI, "", "someCaller", SYSTEM_UID);
+ ZenModeConfig original = mZenModeHelper.mConfig.copy();
+ assertThat(original.isManualActive()).isTrue();
+
+ ByteArrayOutputStream baos = writeXmlAndPurge(null);
+ TypedXmlPullParser parser = getParserForByteStream(baos);
+ mZenModeHelper.readXml(parser, true, UserHandle.USER_ALL);
+
+ ZenModeConfig result = mZenModeHelper.getConfig();
+ assertThat(result.isManualActive()).isFalse();
+
+ // confirm that we do still keep policy information, modes_ui only; prior to modes_ui the
+ // entire rule is intentionally cleared
+ if (Flags.modesUi()) {
+ assertThat(result.manualRule.zenPolicy).isNotNull();
+ }
+ }
+
+ @Test
public void testWriteXmlWithZenPolicy() throws Exception {
final String ruleId = "customRule";
setupZenConfig();