summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xservices/core/java/com/android/server/notification/NotificationManagerService.java3
-rw-r--r--services/core/java/com/android/server/notification/ZenModeHelper.java23
-rwxr-xr-xservices/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java5
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java161
4 files changed, 168 insertions, 24 deletions
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index c9f45e523e3b..2ae040a69583 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -5931,8 +5931,7 @@ public class NotificationManagerService extends SystemService {
newVisualEffects, policy.priorityConversationSenders);
if (shouldApplyAsImplicitRule) {
- mZenModeHelper.applyGlobalPolicyAsImplicitZenRule(pkg, callingUid, policy,
- origin);
+ mZenModeHelper.applyGlobalPolicyAsImplicitZenRule(pkg, callingUid, policy);
} else {
ZenLog.traceSetNotificationPolicy(pkg, applicationInfo.targetSdkVersion,
policy);
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index 1f3fe3f0fcb9..93ffd974bb80 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -605,7 +605,11 @@ public class ZenModeHelper {
rule = newImplicitZenRule(callingPkg);
newConfig.automaticRules.put(rule.id, rule);
}
- rule.zenMode = zenMode;
+ // If the user has changed the rule's *zenMode*, then don't let app overwrite it.
+ // We allow the update if the user has only changed other aspects of the rule.
+ if ((rule.userModifiedFields & AutomaticZenRule.FIELD_INTERRUPTION_FILTER) == 0) {
+ rule.zenMode = zenMode;
+ }
rule.snoozing = false;
rule.condition = new Condition(rule.conditionId,
mContext.getString(R.string.zen_mode_implicit_activated),
@@ -628,7 +632,7 @@ public class ZenModeHelper {
* {@link Global#ZEN_MODE_IMPORTANT_INTERRUPTIONS}.
*/
void applyGlobalPolicyAsImplicitZenRule(String callingPkg, int callingUid,
- NotificationManager.Policy policy, @ConfigChangeOrigin int origin) {
+ NotificationManager.Policy policy) {
if (!android.app.Flags.modesApi()) {
Log.wtf(TAG, "applyGlobalPolicyAsImplicitZenRule called with flag off!");
return;
@@ -644,10 +648,17 @@ public class ZenModeHelper {
rule.zenMode = Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
newConfig.automaticRules.put(rule.id, rule);
}
- // TODO: b/308673679 - Keep user customization of this rule!
- rule.zenPolicy = ZenAdapters.notificationPolicyToZenPolicy(policy);
- setConfigLocked(newConfig, /* triggeringComponent= */ null, origin,
- "applyGlobalPolicyAsImplicitZenRule", callingUid);
+ // If the user has changed the rule's *ZenPolicy*, then don't let app overwrite it.
+ // We allow the update if the user has only changed other aspects of the rule.
+ if (rule.zenPolicyUserModifiedFields == 0) {
+ updatePolicy(
+ rule,
+ ZenAdapters.notificationPolicyToZenPolicy(policy),
+ /* updateBitmask= */ false);
+
+ setConfigLocked(newConfig, /* triggeringComponent= */ null, UPDATE_ORIGIN_APP,
+ "applyGlobalPolicyAsImplicitZenRule", callingUid);
+ }
}
}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index c1f35ccb69e0..723ac15fb50f 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -13792,8 +13792,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
NotificationManager.Policy policy = new NotificationManager.Policy(0, 0, 0);
mBinderService.setNotificationPolicy("package", policy, false);
- verify(zenHelper).applyGlobalPolicyAsImplicitZenRule(eq("package"), anyInt(), eq(policy),
- eq(ZenModeConfig.UPDATE_ORIGIN_APP));
+ verify(zenHelper).applyGlobalPolicyAsImplicitZenRule(eq("package"), anyInt(), eq(policy));
}
@Test
@@ -13859,7 +13858,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
verify(zenModeHelper).setNotificationPolicy(eq(policy), anyInt(), anyInt());
} else {
verify(zenModeHelper).applyGlobalPolicyAsImplicitZenRule(anyString(), anyInt(),
- eq(policy), anyInt());
+ eq(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 f71c8b41e219..edc876aab388 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
@@ -46,6 +46,7 @@ import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.provider.Settings.Global.ZEN_MODE_ALARMS;
import static android.provider.Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+import static android.provider.Settings.Global.ZEN_MODE_NO_INTERRUPTIONS;
import static android.provider.Settings.Global.ZEN_MODE_OFF;
import static android.service.notification.Condition.SOURCE_SCHEDULE;
import static android.service.notification.Condition.SOURCE_USER_ACTION;
@@ -67,6 +68,7 @@ import static com.android.os.dnd.DNDProtoEnums.STATE_ALLOW;
import static com.android.os.dnd.DNDProtoEnums.STATE_DISALLOW;
import static com.android.server.notification.ZenModeHelper.RULE_LIMIT_PER_PACKAGE;
+import static com.google.common.collect.Iterables.getOnlyElement;
import static com.google.common.truth.Truth.assertThat;
import static junit.framework.Assert.assertEquals;
@@ -295,6 +297,8 @@ public class ZenModeHelperTest extends UiServiceTestCase {
when(appInfoSpy.loadLabel(any())).thenReturn(CUSTOM_APP_LABEL);
when(mPackageManager.getApplicationInfo(eq(CUSTOM_PKG_NAME), anyInt()))
.thenReturn(appInfoSpy);
+ when(mPackageManager.getApplicationInfo(eq(mContext.getPackageName()), anyInt()))
+ .thenReturn(appInfoSpy);
mZenModeHelper.mPm = mPackageManager;
mZenModeEventLogger.reset();
@@ -4578,7 +4582,7 @@ public class ZenModeHelperTest extends UiServiceTestCase {
ZEN_MODE_IMPORTANT_INTERRUPTIONS);
assertThat(mZenModeHelper.mConfig.automaticRules.values())
- .comparingElementsUsing(IGNORE_TIMESTAMPS)
+ .comparingElementsUsing(IGNORE_METADATA)
.containsExactly(
expectedImplicitRule(CUSTOM_PKG_NAME, ZEN_MODE_IMPORTANT_INTERRUPTIONS,
null, true));
@@ -4598,12 +4602,75 @@ public class ZenModeHelperTest extends UiServiceTestCase {
ZEN_MODE_ALARMS);
assertThat(mZenModeHelper.mConfig.automaticRules.values())
- .comparingElementsUsing(IGNORE_TIMESTAMPS)
+ .comparingElementsUsing(IGNORE_METADATA)
.containsExactly(
expectedImplicitRule(CUSTOM_PKG_NAME, ZEN_MODE_ALARMS, null, true));
}
@Test
+ @EnableFlags(android.app.Flags.FLAG_MODES_API)
+ public void applyGlobalZenModeAsImplicitZenRule_ruleCustomized_doesNotUpdateRule() {
+ mZenModeHelper.mConfig.automaticRules.clear();
+ String pkg = mContext.getPackageName();
+
+ // From app, call "setInterruptionFilter" and create and implicit rule.
+ mZenModeHelper.applyGlobalZenModeAsImplicitZenRule(pkg, CUSTOM_PKG_UID,
+ ZEN_MODE_IMPORTANT_INTERRUPTIONS);
+ String ruleId = getOnlyElement(mZenModeHelper.mConfig.automaticRules.keySet());
+ assertThat(getOnlyElement(mZenModeHelper.mConfig.automaticRules.values()).zenMode)
+ .isEqualTo(ZEN_MODE_IMPORTANT_INTERRUPTIONS);
+
+ // From user, update that rule's interruption filter.
+ AutomaticZenRule rule = mZenModeHelper.getAutomaticZenRule(ruleId);
+ AutomaticZenRule userUpdateRule = new AutomaticZenRule.Builder(rule)
+ .setInterruptionFilter(INTERRUPTION_FILTER_ALARMS)
+ .build();
+ mZenModeHelper.updateAutomaticZenRule(ruleId, userUpdateRule, UPDATE_ORIGIN_USER, "reason",
+ Process.SYSTEM_UID);
+
+ // From app, call "setInterruptionFilter" again.
+ mZenModeHelper.applyGlobalZenModeAsImplicitZenRule(pkg, CUSTOM_PKG_UID,
+ ZEN_MODE_NO_INTERRUPTIONS);
+
+ // The app's update was ignored, and the user's update is still current, and the current
+ // mode is the one they chose.
+ assertThat(getOnlyElement(mZenModeHelper.mConfig.automaticRules.values()).zenMode)
+ .isEqualTo(ZEN_MODE_ALARMS);
+ assertThat(mZenModeHelper.getZenMode()).isEqualTo(ZEN_MODE_ALARMS);
+ }
+
+ @Test
+ @EnableFlags(android.app.Flags.FLAG_MODES_API)
+ public void applyGlobalZenModeAsImplicitZenRule_ruleCustomizedButNotFilter_updatesRule() {
+ mZenModeHelper.mConfig.automaticRules.clear();
+ String pkg = mContext.getPackageName();
+
+ // From app, call "setInterruptionFilter" and create and implicit rule.
+ mZenModeHelper.applyGlobalZenModeAsImplicitZenRule(pkg, CUSTOM_PKG_UID,
+ ZEN_MODE_IMPORTANT_INTERRUPTIONS);
+ String ruleId = getOnlyElement(mZenModeHelper.mConfig.automaticRules.keySet());
+ assertThat(getOnlyElement(mZenModeHelper.mConfig.automaticRules.values()).zenMode)
+ .isEqualTo(ZEN_MODE_IMPORTANT_INTERRUPTIONS);
+
+ // From user, update something in that rule, but not the interruption filter.
+ AutomaticZenRule rule = mZenModeHelper.getAutomaticZenRule(ruleId);
+ AutomaticZenRule userUpdateRule = new AutomaticZenRule.Builder(rule)
+ .setName("Renamed")
+ .build();
+ mZenModeHelper.updateAutomaticZenRule(ruleId, userUpdateRule, UPDATE_ORIGIN_USER, "reason",
+ Process.SYSTEM_UID);
+
+ // From app, call "setInterruptionFilter" again.
+ mZenModeHelper.applyGlobalZenModeAsImplicitZenRule(pkg, CUSTOM_PKG_UID,
+ ZEN_MODE_NO_INTERRUPTIONS);
+
+ // The app's update was accepted, and the current mode is the one that they wanted.
+ assertThat(getOnlyElement(mZenModeHelper.mConfig.automaticRules.values()).zenMode)
+ .isEqualTo(ZEN_MODE_NO_INTERRUPTIONS);
+ assertThat(mZenModeHelper.getZenMode()).isEqualTo(ZEN_MODE_NO_INTERRUPTIONS);
+ }
+
+ @Test
public void applyGlobalZenModeAsImplicitZenRule_modeOff_deactivatesImplicitRule() {
mSetFlagsRule.enableFlags(android.app.Flags.FLAG_MODES_API);
mZenModeHelper.mConfig.automaticRules.clear();
@@ -4673,8 +4740,7 @@ public class ZenModeHelperTest extends UiServiceTestCase {
Policy policy = new Policy(PRIORITY_CATEGORY_CALLS | PRIORITY_CATEGORY_CONVERSATIONS,
PRIORITY_SENDERS_CONTACTS, PRIORITY_SENDERS_STARRED,
Policy.getAllSuppressedVisualEffects(), CONVERSATION_SENDERS_IMPORTANT);
- mZenModeHelper.applyGlobalPolicyAsImplicitZenRule(CUSTOM_PKG_NAME, CUSTOM_PKG_UID, policy,
- UPDATE_ORIGIN_APP);
+ mZenModeHelper.applyGlobalPolicyAsImplicitZenRule(CUSTOM_PKG_NAME, CUSTOM_PKG_UID, policy);
ZenPolicy expectedZenPolicy = new ZenPolicy.Builder()
.disallowAllSounds()
@@ -4684,7 +4750,7 @@ public class ZenModeHelperTest extends UiServiceTestCase {
.allowPriorityChannels(true)
.build();
assertThat(mZenModeHelper.mConfig.automaticRules.values())
- .comparingElementsUsing(IGNORE_TIMESTAMPS)
+ .comparingElementsUsing(IGNORE_METADATA)
.containsExactly(
expectedImplicitRule(CUSTOM_PKG_NAME, ZEN_MODE_IMPORTANT_INTERRUPTIONS,
expectedZenPolicy, /* conditionActive= */ null));
@@ -4699,14 +4765,13 @@ public class ZenModeHelperTest extends UiServiceTestCase {
PRIORITY_SENDERS_CONTACTS, PRIORITY_SENDERS_STARRED,
Policy.getAllSuppressedVisualEffects(), CONVERSATION_SENDERS_IMPORTANT);
mZenModeHelper.applyGlobalPolicyAsImplicitZenRule(CUSTOM_PKG_NAME, CUSTOM_PKG_UID,
- original, UPDATE_ORIGIN_APP);
+ original);
// Change priorityCallSenders: contacts -> starred.
Policy updated = new Policy(PRIORITY_CATEGORY_CALLS | PRIORITY_CATEGORY_CONVERSATIONS,
PRIORITY_SENDERS_STARRED, PRIORITY_SENDERS_STARRED,
Policy.getAllSuppressedVisualEffects(), CONVERSATION_SENDERS_IMPORTANT);
- mZenModeHelper.applyGlobalPolicyAsImplicitZenRule(CUSTOM_PKG_NAME, CUSTOM_PKG_UID, updated,
- UPDATE_ORIGIN_APP);
+ mZenModeHelper.applyGlobalPolicyAsImplicitZenRule(CUSTOM_PKG_NAME, CUSTOM_PKG_UID, updated);
ZenPolicy expectedZenPolicy = new ZenPolicy.Builder()
.disallowAllSounds()
@@ -4716,20 +4781,87 @@ public class ZenModeHelperTest extends UiServiceTestCase {
.allowPriorityChannels(true)
.build();
assertThat(mZenModeHelper.mConfig.automaticRules.values())
- .comparingElementsUsing(IGNORE_TIMESTAMPS)
+ .comparingElementsUsing(IGNORE_METADATA)
.containsExactly(
expectedImplicitRule(CUSTOM_PKG_NAME, ZEN_MODE_IMPORTANT_INTERRUPTIONS,
expectedZenPolicy, /* conditionActive= */ null));
}
@Test
+ @EnableFlags(android.app.Flags.FLAG_MODES_API)
+ public void applyGlobalPolicyAsImplicitZenRule_ruleCustomized_doesNotUpdateRule() {
+ mZenModeHelper.mConfig.automaticRules.clear();
+ String pkg = mContext.getPackageName();
+
+ // From app, call "setNotificationPolicy" and create and implicit rule.
+ Policy originalPolicy = new Policy(PRIORITY_CATEGORY_MEDIA, 0, 0);
+ mZenModeHelper.applyGlobalPolicyAsImplicitZenRule(pkg, CUSTOM_PKG_UID, originalPolicy);
+ String ruleId = getOnlyElement(mZenModeHelper.mConfig.automaticRules.keySet());
+
+ // From user, update that rule's policy.
+ AutomaticZenRule rule = mZenModeHelper.getAutomaticZenRule(ruleId);
+ ZenPolicy userUpdateZenPolicy = new ZenPolicy.Builder().disallowAllSounds()
+ .allowAlarms(true).build();
+ AutomaticZenRule userUpdateRule = new AutomaticZenRule.Builder(rule)
+ .setZenPolicy(userUpdateZenPolicy)
+ .build();
+ mZenModeHelper.updateAutomaticZenRule(ruleId, userUpdateRule, UPDATE_ORIGIN_USER, "reason",
+ Process.SYSTEM_UID);
+
+ // From app, call "setNotificationPolicy" again.
+ Policy appUpdatePolicy = new Policy(PRIORITY_CATEGORY_SYSTEM, 0, 0);
+ mZenModeHelper.applyGlobalPolicyAsImplicitZenRule(pkg, CUSTOM_PKG_UID, appUpdatePolicy);
+
+ // The app's update was ignored, and the user's update is still current.
+ assertThat(mZenModeHelper.mConfig.automaticRules.values())
+ .comparingElementsUsing(IGNORE_METADATA)
+ .containsExactly(
+ expectedImplicitRule(pkg, ZEN_MODE_IMPORTANT_INTERRUPTIONS,
+ userUpdateZenPolicy,
+ /* conditionActive= */ null));
+ }
+
+ @Test
+ @EnableFlags(android.app.Flags.FLAG_MODES_API)
+ public void applyGlobalPolicyAsImplicitZenRule_ruleCustomizedButNotZenPolicy_updatesRule() {
+ mZenModeHelper.mConfig.automaticRules.clear();
+ String pkg = mContext.getPackageName();
+
+ // From app, call "setNotificationPolicy" and create and implicit rule.
+ Policy originalPolicy = new Policy(PRIORITY_CATEGORY_MEDIA, 0, 0);
+ mZenModeHelper.applyGlobalPolicyAsImplicitZenRule(pkg, CUSTOM_PKG_UID, originalPolicy);
+ String ruleId = getOnlyElement(mZenModeHelper.mConfig.automaticRules.keySet());
+
+ // From user, update something in that rule, but not the ZenPolicy.
+ AutomaticZenRule rule = mZenModeHelper.getAutomaticZenRule(ruleId);
+ AutomaticZenRule userUpdateRule = new AutomaticZenRule.Builder(rule)
+ .setName("Rule renamed, not touching policy")
+ .build();
+ mZenModeHelper.updateAutomaticZenRule(ruleId, userUpdateRule, UPDATE_ORIGIN_USER, "reason",
+ Process.SYSTEM_UID);
+
+ // From app, call "setNotificationPolicy" again.
+ Policy appUpdatePolicy = new Policy(PRIORITY_CATEGORY_SYSTEM, 0, 0);
+ mZenModeHelper.applyGlobalPolicyAsImplicitZenRule(pkg, CUSTOM_PKG_UID, appUpdatePolicy);
+
+ // The app's update was applied.
+ ZenPolicy appsSecondZenPolicy = new ZenPolicy.Builder()
+ .disallowAllSounds()
+ .allowSystem(true)
+ .allowPriorityChannels(true)
+ .build();
+ assertThat(getOnlyElement(mZenModeHelper.mConfig.automaticRules.values()).zenPolicy)
+ .isEqualTo(appsSecondZenPolicy);
+ }
+
+ @Test
public void applyGlobalPolicyAsImplicitZenRule_flagOff_ignored() {
mSetFlagsRule.disableFlags(android.app.Flags.FLAG_MODES_API);
mZenModeHelper.mConfig.automaticRules.clear();
withoutWtfCrash(
() -> mZenModeHelper.applyGlobalPolicyAsImplicitZenRule(CUSTOM_PKG_NAME,
- CUSTOM_PKG_UID, new Policy(0, 0, 0), UPDATE_ORIGIN_APP));
+ CUSTOM_PKG_UID, new Policy(0, 0, 0)));
assertThat(mZenModeHelper.mConfig.automaticRules).isEmpty();
}
@@ -4742,7 +4874,7 @@ public class ZenModeHelperTest extends UiServiceTestCase {
Policy.getAllSuppressedVisualEffects(), STATE_FALSE,
CONVERSATION_SENDERS_IMPORTANT);
mZenModeHelper.applyGlobalPolicyAsImplicitZenRule(CUSTOM_PKG_NAME, CUSTOM_PKG_UID,
- writtenPolicy, UPDATE_ORIGIN_APP);
+ writtenPolicy);
Policy readPolicy = mZenModeHelper.getNotificationPolicyFromImplicitZenRule(
CUSTOM_PKG_NAME);
@@ -4782,7 +4914,7 @@ public class ZenModeHelperTest extends UiServiceTestCase {
assertThat(readPolicy.allowConversations()).isFalse();
}
- private static final Correspondence<ZenRule, ZenRule> IGNORE_TIMESTAMPS =
+ private static final Correspondence<ZenRule, ZenRule> IGNORE_METADATA =
Correspondence.transforming(zr -> {
Parcel p = Parcel.obtain();
try {
@@ -4790,12 +4922,15 @@ public class ZenModeHelperTest extends UiServiceTestCase {
p.setDataPosition(0);
ZenRule copy = new ZenRule(p);
copy.creationTime = 0;
+ copy.userModifiedFields = 0;
+ copy.zenPolicyUserModifiedFields = 0;
+ copy.zenDeviceEffectsUserModifiedFields = 0;
return copy;
} finally {
p.recycle();
}
},
- "Ignoring timestamps");
+ "Ignoring timestamp and userModifiedFields");
private ZenRule expectedImplicitRule(String ownerPkg, int zenMode, ZenPolicy policy,
@Nullable Boolean conditionActive) {