diff options
8 files changed, 258 insertions, 32 deletions
diff --git a/core/java/android/app/AutomaticZenRule.java b/core/java/android/app/AutomaticZenRule.java index 62b541261f34..e0a937156906 100644 --- a/core/java/android/app/AutomaticZenRule.java +++ b/core/java/android/app/AutomaticZenRule.java @@ -49,7 +49,7 @@ public final class AutomaticZenRule implements Parcelable { /** * Rule is of an unknown type. This is the default value if not provided by the owning app, - * and the value returned if the true type was added in an API level lower than the calling + * and the value returned if the true type was added in an API level higher than the calling * app's targetSdk. */ @FlaggedApi(Flags.FLAG_MODES_API) @@ -315,7 +315,8 @@ public final class AutomaticZenRule implements Parcelable { } /** - * Gets the zen policy. + * Gets the {@link ZenPolicy} applied if {@link #getInterruptionFilter()} is + * {@link NotificationManager#INTERRUPTION_FILTER_PRIORITY}. */ @Nullable public ZenPolicy getZenPolicy() { @@ -345,6 +346,17 @@ public final class AutomaticZenRule implements Parcelable { /** * Sets the interruption filter that is applied when this rule is active. + * + * <ul> + * <li>When {@link NotificationManager#INTERRUPTION_FILTER_PRIORITY}, the rule will use + * the {@link ZenPolicy} supplied to {@link #setZenPolicy} (or a default one). + * <li>When {@link NotificationManager#INTERRUPTION_FILTER_ALARMS} or + * {@link NotificationManager#INTERRUPTION_FILTER_NONE}, the rule will use a fixed + * {@link ZenPolicy} matching the filter. + * <li>When {@link NotificationManager#INTERRUPTION_FILTER_ALL}, the rule will not block + * notifications, but can still have {@link ZenDeviceEffects}. + * </ul> + * * @param interruptionFilter The do not disturb mode to enter when this rule is active. */ public void setInterruptionFilter(@InterruptionFilter int interruptionFilter) { @@ -374,7 +386,8 @@ public final class AutomaticZenRule implements Parcelable { } /** - * Sets the zen policy. + * Sets the {@link ZenPolicy} applied if {@link #getInterruptionFilter()} is + * {@link NotificationManager#INTERRUPTION_FILTER_PRIORITY}. * * <p>When updating an existing rule via {@link NotificationManager#updateAutomaticZenRule}, * a {@code null} value here means the previous policy is retained. diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java index ba647864a4f1..3d8d933cbbcc 100644 --- a/core/java/android/service/notification/ZenModeConfig.java +++ b/core/java/android/service/notification/ZenModeConfig.java @@ -2932,7 +2932,7 @@ public class ZenModeConfig implements Parcelable { } } - // TODO: b/333527800 - Rename to isActive() + // TODO: b/363193376 - Rename to isActive() public boolean isAutomaticActive() { if (Flags.modesApi() && Flags.modesUi()) { if (!enabled || getPkg() == null) { diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml index 687c72878bdb..4d771c0f8d71 100644 --- a/packages/SettingsLib/res/values/strings.xml +++ b/packages/SettingsLib/res/values/strings.xml @@ -1364,6 +1364,9 @@ <!-- Keywords for setting screen for controlling apps that can schedule alarms [CHAR LIMIT=100] --> <string name="keywords_alarms_and_reminders">schedule, alarm, reminder, clock</string> + <!-- Priority Modes: Name of the "manual" Do Not Disturb mode. [CHAR LIMIT=50] --> + <string name="zen_mode_do_not_disturb_name">Do Not Disturb</string> + <!-- Sound: Title for the Do not Disturb option and associated settings page. [CHAR LIMIT=50]--> <string name="zen_mode_settings_title">Do Not Disturb</string> diff --git a/packages/SettingsLib/src/com/android/settingslib/notification/modes/TestModeBuilder.java b/packages/SettingsLib/src/com/android/settingslib/notification/modes/TestModeBuilder.java index f7492cfc9a72..8e0cdf8109de 100644 --- a/packages/SettingsLib/src/com/android/settingslib/notification/modes/TestModeBuilder.java +++ b/packages/SettingsLib/src/com/android/settingslib/notification/modes/TestModeBuilder.java @@ -16,6 +16,7 @@ package com.android.settingslib.notification.modes; +import static android.app.NotificationManager.INTERRUPTION_FILTER_PRIORITY; import static android.service.notification.ZenModeConfig.ORIGIN_UNKNOWN; import static android.service.notification.ZenModeConfig.ORIGIN_USER_IN_SYSTEMUI; @@ -24,11 +25,13 @@ import android.app.NotificationManager; import android.content.ComponentName; import android.net.Uri; import android.service.notification.Condition; +import android.service.notification.SystemZenRules; import android.service.notification.ZenDeviceEffects; import android.service.notification.ZenModeConfig; import android.service.notification.ZenPolicy; import androidx.annotation.DrawableRes; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; import java.util.Random; @@ -40,13 +43,27 @@ public class TestModeBuilder { private ZenModeConfig.ZenRule mConfigZenRule; public static final ZenMode EXAMPLE = new TestModeBuilder().build(); - public static final ZenMode MANUAL_DND_ACTIVE = manualDnd(Uri.EMPTY, true); - public static final ZenMode MANUAL_DND_INACTIVE = manualDnd(Uri.EMPTY, false); - public static ZenMode manualDnd(Uri conditionId, boolean isActive) { + public static final ZenMode MANUAL_DND_ACTIVE = manualDnd(Uri.EMPTY, + INTERRUPTION_FILTER_PRIORITY, true); + + public static final ZenMode MANUAL_DND_INACTIVE = manualDnd(Uri.EMPTY, + INTERRUPTION_FILTER_PRIORITY, false); + + @NonNull + public static ZenMode manualDnd(@NotificationManager.InterruptionFilter int filter, + boolean isActive) { + return manualDnd(Uri.EMPTY, filter, isActive); + } + + private static ZenMode manualDnd(Uri conditionId, + @NotificationManager.InterruptionFilter int filter, boolean isActive) { return ZenMode.manualDndMode( new AutomaticZenRule.Builder("Do Not Disturb", conditionId) - .setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_PRIORITY) + .setInterruptionFilter(filter) + .setType(AutomaticZenRule.TYPE_OTHER) + .setManualInvocationAllowed(true) + .setPackage(SystemZenRules.PACKAGE_ANDROID) .setZenPolicy(new ZenPolicy.Builder().disallowAllSounds().build()) .build(), isActive); @@ -58,7 +75,7 @@ public class TestModeBuilder { mId = "rule_" + id; mRule = new AutomaticZenRule.Builder("Test Rule #" + id, Uri.parse("rule://" + id)) .setPackage("some_package") - .setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_PRIORITY) + .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY) .setZenPolicy(new ZenPolicy.Builder().disallowAllSounds().build()) .build(); mConfigZenRule = new ZenModeConfig.ZenRule(); @@ -134,7 +151,7 @@ public class TestModeBuilder { @NotificationManager.InterruptionFilter int interruptionFilter) { mRule.setInterruptionFilter(interruptionFilter); mConfigZenRule.zenMode = NotificationManager.zenModeFromInterruptionFilter( - interruptionFilter, NotificationManager.INTERRUPTION_FILTER_PRIORITY); + interruptionFilter, INTERRUPTION_FILTER_PRIORITY); return this; } diff --git a/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenMode.java b/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenMode.java index 36975c7ec4b1..d0661fa4dee4 100644 --- a/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenMode.java +++ b/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenMode.java @@ -18,9 +18,10 @@ package com.android.settingslib.notification.modes; import static android.app.AutomaticZenRule.TYPE_SCHEDULE_CALENDAR; import static android.app.AutomaticZenRule.TYPE_SCHEDULE_TIME; +import static android.app.NotificationManager.INTERRUPTION_FILTER_ALARMS; import static android.app.NotificationManager.INTERRUPTION_FILTER_ALL; +import static android.app.NotificationManager.INTERRUPTION_FILTER_NONE; import static android.app.NotificationManager.INTERRUPTION_FILTER_PRIORITY; -import static android.service.notification.SystemZenRules.PACKAGE_ANDROID; import static android.service.notification.SystemZenRules.getTriggerDescriptionForScheduleEvent; import static android.service.notification.SystemZenRules.getTriggerDescriptionForScheduleTime; import static android.service.notification.ZenModeConfig.tryParseCountdownConditionId; @@ -69,7 +70,7 @@ public class ZenMode implements Parcelable { static final String TEMP_NEW_MODE_ID = "temp_new_mode"; // Must match com.android.server.notification.ZenModeHelper#applyCustomPolicy. - private static final ZenPolicy POLICY_INTERRUPTION_FILTER_ALARMS = + static final ZenPolicy POLICY_INTERRUPTION_FILTER_ALARMS = new ZenPolicy.Builder() .disallowAllSounds() .allowAlarms(true) @@ -78,7 +79,7 @@ public class ZenMode implements Parcelable { .build(); // Must match com.android.server.notification.ZenModeHelper#applyCustomPolicy. - private static final ZenPolicy POLICY_INTERRUPTION_FILTER_NONE = + static final ZenPolicy POLICY_INTERRUPTION_FILTER_NONE = new ZenPolicy.Builder() .disallowAllSounds() .hideAllVisualEffects() @@ -171,13 +172,9 @@ public class ZenMode implements Parcelable { } static ZenMode manualDndMode(AutomaticZenRule manualRule, boolean isActive) { - // Manual rule is owned by the system, so we set it here - AutomaticZenRule manualRuleWithPkg = new AutomaticZenRule.Builder(manualRule) - .setPackage(PACKAGE_ANDROID) - .build(); return new ZenMode( MANUAL_DND_MODE_ID, - manualRuleWithPkg, + manualRule, Kind.MANUAL_DND, isActive ? Status.ENABLED_AND_ACTIVE : Status.ENABLED); } @@ -298,6 +295,23 @@ public class ZenMode implements Parcelable { } } + /** Returns the interruption filter of the mode. */ + @NotificationManager.InterruptionFilter + public int getInterruptionFilter() { + return mRule.getInterruptionFilter(); + } + + /** + * Sets the interruption filter of the mode. This is valid for {@link AutomaticZenRule}-backed + * modes (and not manual DND). + */ + public void setInterruptionFilter(@NotificationManager.InterruptionFilter int filter) { + if (isManualDnd() || !canEditPolicy()) { + throw new IllegalStateException("Cannot update interruption filter for mode " + this); + } + mRule.setInterruptionFilter(filter); + } + @NonNull public ZenPolicy getPolicy() { switch (mRule.getInterruptionFilter()) { @@ -326,6 +340,10 @@ public class ZenMode implements Parcelable { */ @SuppressLint("WrongConstant") public void setPolicy(@NonNull ZenPolicy policy) { + if (!canEditPolicy()) { + throw new IllegalStateException("Cannot update ZenPolicy for mode " + this); + } + ZenPolicy currentPolicy = getPolicy(); if (currentPolicy.equals(policy)) { return; @@ -342,6 +360,12 @@ public class ZenMode implements Parcelable { mRule.setZenPolicy(policy); } + /** + * Returns the {@link ZenDeviceEffects} of the mode. + * + * <p>This is never {@code null}; if the backing AutomaticZenRule doesn't have effects set then + * a default (empty) effects set is returned. + */ @NonNull public ZenDeviceEffects getDeviceEffects() { return mRule.getDeviceEffects() != null @@ -349,6 +373,15 @@ public class ZenMode implements Parcelable { : new ZenDeviceEffects.Builder().build(); } + /** Sets the {@link ZenDeviceEffects} of the mode. */ + public void setDeviceEffects(@NonNull ZenDeviceEffects effects) { + checkNotNull(effects); + if (!canEditPolicy()) { + throw new IllegalStateException("Cannot update device effects for mode " + this); + } + mRule.setDeviceEffects(effects); + } + public void setCustomModeConditionId(Context context, Uri conditionId) { checkState(SystemZenRules.PACKAGE_ANDROID.equals(mRule.getPackageName()), "Trying to change condition of non-system-owned rule %s (to %s)", @@ -391,6 +424,18 @@ public class ZenMode implements Parcelable { return !isManualDnd(); } + /** + * Whether the mode has an editable policy. Calling {@link #setPolicy}, + * {@link #setDeviceEffects}, or {@link #setInterruptionFilter} is not valid for modes with a + * read-only policy. + */ + public boolean canEditPolicy() { + // Cannot edit the policy of a temporarily active non-PRIORITY DND mode. + // Note that it's fine to edit the policy of an *AutomaticZenRule* with non-PRIORITY filter; + // the filter will we set to PRIORITY if you do. + return !isManualDndWithSpecialFilter(); + } + public boolean canBeDeleted() { return !isManualDnd(); } @@ -399,6 +444,12 @@ public class ZenMode implements Parcelable { return mKind == Kind.MANUAL_DND; } + private boolean isManualDndWithSpecialFilter() { + return isManualDnd() + && (mRule.getInterruptionFilter() == INTERRUPTION_FILTER_ALARMS + || mRule.getInterruptionFilter() == INTERRUPTION_FILTER_NONE); + } + /** * A <em>custom manual</em> mode is a mode created by the user, and not yet assigned an * automatic trigger condition (neither time schedule nor a calendar). @@ -414,6 +465,18 @@ public class ZenMode implements Parcelable { return mRule.isEnabled(); } + /** + * Enables or disables the mode. + * + * <p>The DND mode cannot be disabled; trying to do so will fail. + */ + public void setEnabled(boolean enabled) { + if (isManualDnd()) { + throw new IllegalStateException("Cannot update enabled for manual DND mode " + this); + } + mRule.setEnabled(enabled); + } + public boolean isActive() { return mStatus == Status.ENABLED_AND_ACTIVE; } diff --git a/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenModesBackend.java b/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenModesBackend.java index c8a12f481c6e..71e03c1d0ad3 100644 --- a/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenModesBackend.java +++ b/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenModesBackend.java @@ -16,6 +16,11 @@ package com.android.settingslib.notification.modes; +import static android.app.NotificationManager.INTERRUPTION_FILTER_PRIORITY; +import static android.app.NotificationManager.zenModeToInterruptionFilter; +import static android.provider.Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS; +import static android.service.notification.SystemZenRules.PACKAGE_ANDROID; + import android.annotation.Nullable; import android.app.ActivityManager; import android.app.AutomaticZenRule; @@ -112,14 +117,22 @@ public class ZenModesBackend { private ZenMode getManualDndMode(ZenModeConfig config) { ZenModeConfig.ZenRule manualRule = config.manualRule; + + // If DND is currently on with an interruption filter other than PRIORITY, construct the + // rule with that. DND will be *non-editable* while in this state. + int dndInterruptionFilter = config.isManualActive() + ? zenModeToInterruptionFilter(manualRule.zenMode) + : INTERRUPTION_FILTER_PRIORITY; + AutomaticZenRule manualDndRule = new AutomaticZenRule.Builder( - mContext.getString(R.string.zen_mode_settings_title), manualRule.conditionId) - .setType(manualRule.type) + mContext.getString(R.string.zen_mode_do_not_disturb_name), manualRule.conditionId) + .setPackage(PACKAGE_ANDROID) + .setType(AutomaticZenRule.TYPE_OTHER) .setZenPolicy(manualRule.zenPolicy) .setDeviceEffects(manualRule.zenDeviceEffects) - .setManualInvocationAllowed(manualRule.allowManualInvocation) + .setManualInvocationAllowed(true) .setConfigurationActivity(null) // No further settings - .setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_PRIORITY) + .setInterruptionFilter(dndInterruptionFilter) .build(); return ZenMode.manualDndMode(manualDndRule, config.isManualActive()); @@ -150,7 +163,7 @@ public class ZenModesBackend { durationConditionId = ZenModeConfig.toTimeCondition(mContext, (int) forDuration.toMinutes(), ActivityManager.getCurrentUser(), true).id; } - mNotificationManager.setZenMode(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, + mNotificationManager.setZenMode(ZEN_MODE_IMPORTANT_INTERRUPTIONS, durationConditionId, TAG, /* fromUser= */ true); } else { diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/modes/ZenModeTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/modes/ZenModeTest.java index 14b0c252aff5..a30613d6274c 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/modes/ZenModeTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/modes/ZenModeTest.java @@ -24,6 +24,7 @@ import static android.app.AutomaticZenRule.TYPE_SCHEDULE_CALENDAR; import static android.app.AutomaticZenRule.TYPE_THEATER; import static android.app.AutomaticZenRule.TYPE_UNKNOWN; import static android.app.NotificationManager.INTERRUPTION_FILTER_ALARMS; +import static android.app.NotificationManager.INTERRUPTION_FILTER_ALL; import static android.app.NotificationManager.INTERRUPTION_FILTER_NONE; import static android.app.NotificationManager.INTERRUPTION_FILTER_PRIORITY; import static android.service.notification.SystemZenRules.PACKAGE_ANDROID; @@ -31,11 +32,14 @@ import static android.service.notification.SystemZenRules.PACKAGE_ANDROID; import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertWithMessage; +import static org.junit.Assert.assertThrows; + import android.app.AutomaticZenRule; import android.net.Uri; import android.os.Parcel; import android.service.notification.Condition; import android.service.notification.SystemZenRules; +import android.service.notification.ZenDeviceEffects; import android.service.notification.ZenModeConfig; import android.service.notification.ZenPolicy; @@ -69,20 +73,26 @@ public class ZenModeTest { .build(); @Test - public void testBasicMethods() { + public void testBasicMethods_mode() { ZenMode zenMode = new ZenMode("id", ZEN_RULE, zenConfigRuleFor(ZEN_RULE, true)); assertThat(zenMode.getId()).isEqualTo("id"); assertThat(zenMode.getRule()).isEqualTo(ZEN_RULE); assertThat(zenMode.isManualDnd()).isFalse(); assertThat(zenMode.canEditNameAndIcon()).isTrue(); + assertThat(zenMode.canEditPolicy()).isTrue(); assertThat(zenMode.canBeDeleted()).isTrue(); assertThat(zenMode.isActive()).isTrue(); + } + + @Test + public void testBasicMethods_manualDnd() { + ZenMode manualMode = TestModeBuilder.MANUAL_DND_INACTIVE; - ZenMode manualMode = ZenMode.manualDndMode(ZEN_RULE, false); assertThat(manualMode.getId()).isEqualTo(ZenMode.MANUAL_DND_MODE_ID); assertThat(manualMode.isManualDnd()).isTrue(); assertThat(manualMode.canEditNameAndIcon()).isFalse(); + assertThat(manualMode.canEditPolicy()).isTrue(); assertThat(manualMode.canBeDeleted()).isFalse(); assertThat(manualMode.isActive()).isFalse(); assertThat(manualMode.getRule().getPackageName()).isEqualTo(PACKAGE_ANDROID); @@ -243,6 +253,77 @@ public class ZenModeTest { } @Test + public void getInterruptionFilter_returnsFilter() { + ZenMode mode = new TestModeBuilder().setInterruptionFilter( + INTERRUPTION_FILTER_ALARMS).build(); + + assertThat(mode.getInterruptionFilter()).isEqualTo(INTERRUPTION_FILTER_ALARMS); + } + + @Test + public void setInterruptionFilter_setsFilter() { + ZenMode mode = new TestModeBuilder().setInterruptionFilter( + INTERRUPTION_FILTER_ALARMS).build(); + + mode.setInterruptionFilter(INTERRUPTION_FILTER_ALL); + + assertThat(mode.getInterruptionFilter()).isEqualTo(INTERRUPTION_FILTER_ALL); + } + + @Test + public void setInterruptionFilter_manualDnd_throws() { + ZenMode manualDnd = TestModeBuilder.MANUAL_DND_INACTIVE; + + assertThrows(IllegalStateException.class, + () -> manualDnd.setInterruptionFilter(INTERRUPTION_FILTER_ALL)); + } + + @Test + public void canEditPolicy_onlyFalseForSpecialDnd() { + assertThat(TestModeBuilder.EXAMPLE.canEditPolicy()).isTrue(); + assertThat(TestModeBuilder.MANUAL_DND_ACTIVE.canEditPolicy()).isTrue(); + assertThat(TestModeBuilder.MANUAL_DND_INACTIVE.canEditPolicy()).isTrue(); + + ZenMode dndWithAlarms = TestModeBuilder.manualDnd(INTERRUPTION_FILTER_ALARMS, true); + assertThat(dndWithAlarms.canEditPolicy()).isFalse(); + ZenMode dndWithNone = TestModeBuilder.manualDnd(INTERRUPTION_FILTER_NONE, true); + assertThat(dndWithNone.canEditPolicy()).isFalse(); + + // Note: Backend will never return an inactive manual mode with custom filter. + ZenMode badDndWithAlarms = TestModeBuilder.manualDnd(INTERRUPTION_FILTER_ALARMS, false); + assertThat(badDndWithAlarms.canEditPolicy()).isFalse(); + ZenMode badDndWithNone = TestModeBuilder.manualDnd(INTERRUPTION_FILTER_NONE, false); + assertThat(badDndWithNone.canEditPolicy()).isFalse(); + } + + @Test + public void canEditPolicy_whenTrue_allowsSettingPolicyAndEffects() { + ZenMode normalDnd = TestModeBuilder.manualDnd(INTERRUPTION_FILTER_PRIORITY, true); + + assertThat(normalDnd.canEditPolicy()).isTrue(); + + ZenPolicy somePolicy = new ZenPolicy.Builder().showBadges(true).build(); + normalDnd.setPolicy(somePolicy); + assertThat(normalDnd.getPolicy()).isEqualTo(somePolicy); + + ZenDeviceEffects someEffects = new ZenDeviceEffects.Builder() + .setShouldUseNightMode(true).build(); + normalDnd.setDeviceEffects(someEffects); + assertThat(normalDnd.getDeviceEffects()).isEqualTo(someEffects); + } + + @Test + public void canEditPolicy_whenFalse_preventsSettingFilterPolicyOrEffects() { + ZenMode specialDnd = TestModeBuilder.manualDnd(INTERRUPTION_FILTER_ALARMS, true); + + assertThat(specialDnd.canEditPolicy()).isFalse(); + assertThrows(IllegalStateException.class, + () -> specialDnd.setPolicy(ZEN_POLICY)); + assertThrows(IllegalStateException.class, + () -> specialDnd.setDeviceEffects(new ZenDeviceEffects.Builder().build())); + } + + @Test public void comparator_prioritizes() { ZenMode manualDnd = TestModeBuilder.MANUAL_DND_INACTIVE; ZenMode driving1 = new TestModeBuilder().setName("b1").setType(TYPE_DRIVING).build(); diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/modes/ZenModesBackendTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/modes/ZenModesBackendTest.java index 539519b3ec3b..ff028dd6bbdc 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/modes/ZenModesBackendTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/modes/ZenModesBackendTest.java @@ -16,12 +16,14 @@ package com.android.settingslib.notification.modes; +import static android.app.NotificationManager.INTERRUPTION_FILTER_ALARMS; import static android.app.NotificationManager.INTERRUPTION_FILTER_PRIORITY; import static android.provider.Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS; import static android.provider.Settings.Global.ZEN_MODE_OFF; import static android.service.notification.Condition.SOURCE_UNKNOWN; import static android.service.notification.Condition.STATE_FALSE; import static android.service.notification.Condition.STATE_TRUE; +import static android.service.notification.SystemZenRules.PACKAGE_ANDROID; import static android.service.notification.ZenAdapters.notificationPolicyToZenPolicy; import static android.service.notification.ZenPolicy.STATE_ALLOW; @@ -47,8 +49,6 @@ import android.service.notification.ZenDeviceEffects; import android.service.notification.ZenModeConfig; import android.service.notification.ZenPolicy; -import com.android.settingslib.R; - import com.google.common.collect.ImmutableMap; import org.junit.Before; @@ -172,9 +172,8 @@ public class ZenModesBackendTest { // all modes exist, but none of them are currently active assertThat(modes).containsExactly( ZenMode.manualDndMode( - new AutomaticZenRule.Builder( - mContext.getString(R.string.zen_mode_settings_title), - Uri.EMPTY) + new AutomaticZenRule.Builder("Do Not Disturb", Uri.EMPTY) + .setPackage(PACKAGE_ANDROID) .setType(AutomaticZenRule.TYPE_OTHER) .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY) .setZenPolicy(notificationPolicyToZenPolicy(dndPolicy)) @@ -196,15 +195,52 @@ public class ZenModesBackendTest { ZenMode mode = mBackend.getMode(ZenMode.MANUAL_DND_MODE_ID); + assertThat(mode).isNotNull(); assertThat(mode).isEqualTo( ZenMode.manualDndMode( - new AutomaticZenRule.Builder( - mContext.getString(R.string.zen_mode_settings_title), Uri.EMPTY) + new AutomaticZenRule.Builder("Do Not Disturb", Uri.EMPTY) + .setPackage(PACKAGE_ANDROID) .setType(AutomaticZenRule.TYPE_OTHER) .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY) .setZenPolicy(notificationPolicyToZenPolicy(dndPolicy)) .setManualInvocationAllowed(true) .build(), false)); + + assertThat(mode.isManualDnd()).isTrue(); + assertThat(mode.isEnabled()).isTrue(); + assertThat(mode.isActive()).isFalse(); + assertThat(mode.canEditPolicy()).isTrue(); + assertThat(mode.getPolicy()).isEqualTo(notificationPolicyToZenPolicy(dndPolicy)); + } + + @Test + public void getMode_dndWithOtherInterruptionFilter_returnsSpecialDndMode() { + ZenModeConfig config = configWithManualRule(new ZenModeConfig(), true); + config.manualRule.zenMode = Settings.Global.ZEN_MODE_ALARMS; + Policy dndPolicyForPriority = new Policy(Policy.PRIORITY_CATEGORY_ALARMS, + Policy.PRIORITY_SENDERS_CONTACTS, Policy.PRIORITY_SENDERS_CONTACTS); + config.applyNotificationPolicy(dndPolicyForPriority); + when(mNm.getZenModeConfig()).thenReturn(config); + + ZenMode mode = mBackend.getMode(ZenMode.MANUAL_DND_MODE_ID); + + assertThat(mode).isNotNull(); + assertThat(mode).isEqualTo( + ZenMode.manualDndMode( + new AutomaticZenRule.Builder("Do Not Disturb", Uri.EMPTY) + .setPackage(PACKAGE_ANDROID) + .setType(AutomaticZenRule.TYPE_OTHER) + .setInterruptionFilter(INTERRUPTION_FILTER_ALARMS) + .setZenPolicy(notificationPolicyToZenPolicy(dndPolicyForPriority)) + .setManualInvocationAllowed(true) + .build(), true)); + + assertThat(mode.isManualDnd()).isTrue(); + assertThat(mode.isEnabled()).isTrue(); + assertThat(mode.isActive()).isTrue(); + // Mode itself has a special fixed policy, different to the rule. + assertThat(mode.canEditPolicy()).isFalse(); + assertThat(mode.getPolicy()).isEqualTo(ZenMode.POLICY_INTERRUPTION_FILTER_ALARMS); } @Test |