Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3a9a268b authored by Matías Hernández's avatar Matías Hernández
Browse files

Ensure restored (deleted+added) rules are neither active nor snoozed

Also tweak the "preserve" step to add a *copy* of the rule to the deleted map, instead of the rule itself. While this shouldn't really affect the outcome (because the rule will be removed from automaticRules shortly) it's better not to mess with its state.

Fixes: 322482703
Test: atest ZenModeHelperTest
Change-Id: I9e14f1ece61946332b8b5883ff7e782f832f47fd
parent dae634e0
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -2297,6 +2297,18 @@ public class ZenModeConfig implements Parcelable {
                    component, configurationActivity, pkg, id, enabler, zenPolicy, modified);
        }

        /** Returns a deep copy of the {@link ZenRule}. */
        public ZenRule copy() {
            final Parcel parcel = Parcel.obtain();
            try {
                writeToParcel(parcel, 0);
                parcel.setDataPosition(0);
                return new ZenRule(parcel);
            } finally {
                parcel.recycle();
            }
        }

        public boolean isAutomaticActive() {
            return enabled && !snoozing && getPkg() != null && isTrueOrUnknown();
        }
+6 −2
Original line number Diff line number Diff line
@@ -840,9 +840,13 @@ public class ZenModeHelper {
                && !PACKAGE_ANDROID.equals(ruleToRemove.pkg)) {
            String deletedKey = ZenModeConfig.deletedRuleKey(ruleToRemove);
            if (deletedKey != null) {
                ruleToRemove.deletionInstant = Instant.now(mClock);
                ZenRule deletedRule = ruleToRemove.copy();
                deletedRule.deletionInstant = Instant.now(mClock);
                // If the rule is restored it shouldn't be active (or snoozed).
                deletedRule.snoozing = false;
                deletedRule.condition = null;
                // Overwrites a previously-deleted rule with the same conditionId, but that's okay.
                config.deletedRules.put(deletedKey, ruleToRemove);
                config.deletedRules.put(deletedKey, deletedRule);
            }
        }
    }
+104 −0
Original line number Diff line number Diff line
@@ -4760,6 +4760,7 @@ public class ZenModeHelperTest extends UiServiceTestCase {
                .setShouldDimWallpaper(true)
                .setShouldUseNightMode(true)
                .build();
        user1Rule.zenPolicy = new ZenPolicy();
        verifyNoMoreInteractions(mDeviceEffectsApplier);

        mZenModeHelper.onUserSwitched(1);
@@ -5039,6 +5040,109 @@ public class ZenModeHelperTest extends UiServiceTestCase {
                .collect(Collectors.toSet())).containsExactly("pkg2");
    }

    @Test
    @EnableFlags(Flags.FLAG_MODES_API)
    public void removeAndAddAutomaticZenRule_wasActive_isRestoredAsInactive() {
        // Start with a rule.
        mZenModeHelper.mConfig.automaticRules.clear();
        AutomaticZenRule rule = new AutomaticZenRule.Builder("Test", CONDITION_ID)
                .setConditionId(CONDITION_ID)
                .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
                .build();
        String ruleId = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(), rule,
                UPDATE_ORIGIN_APP, "add it", CUSTOM_PKG_UID);

        // User customizes it.
        AutomaticZenRule userUpdate = new AutomaticZenRule.Builder(rule)
                .setInterruptionFilter(INTERRUPTION_FILTER_ALARMS)
                .build();
        mZenModeHelper.updateAutomaticZenRule(ruleId, userUpdate, UPDATE_ORIGIN_USER, "userUpdate",
                Process.SYSTEM_UID);
        assertThat(mZenModeHelper.getZenMode()).isEqualTo(ZEN_MODE_OFF);

        // App activates it.
        mZenModeHelper.setAutomaticZenRuleState(ruleId, CONDITION_TRUE, UPDATE_ORIGIN_APP,
                CUSTOM_PKG_UID);
        assertThat(mZenModeHelper.getZenMode()).isEqualTo(ZEN_MODE_ALARMS);

        // App deletes it.
        mZenModeHelper.removeAutomaticZenRule(ruleId, UPDATE_ORIGIN_APP, "delete it",
                CUSTOM_PKG_UID);
        assertThat(mZenModeHelper.mConfig.automaticRules).hasSize(0);
        assertThat(mZenModeHelper.mConfig.deletedRules).hasSize(1);
        assertThat(mZenModeHelper.getZenMode()).isEqualTo(ZEN_MODE_OFF);

        // App adds it again.
        String newRuleId = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(), rule,
                UPDATE_ORIGIN_APP, "add it again", CUSTOM_PKG_UID);

        // The rule is restored...
        assertThat(newRuleId).isEqualTo(ruleId);
        AutomaticZenRule finalRule = mZenModeHelper.getAutomaticZenRule(newRuleId);
        assertThat(finalRule.getInterruptionFilter()).isEqualTo(INTERRUPTION_FILTER_ALARMS);

        // ... but it is NOT active
        ZenRule storedRule = mZenModeHelper.mConfig.automaticRules.get(newRuleId);
        assertThat(storedRule.isAutomaticActive()).isFalse();
        assertThat(storedRule.isTrueOrUnknown()).isFalse();
        assertThat(storedRule.condition).isNull();
        assertThat(mZenModeHelper.getZenMode()).isEqualTo(ZEN_MODE_OFF);
    }

    @Test
    @EnableFlags(Flags.FLAG_MODES_API)
    public void removeAndAddAutomaticZenRule_wasSnoozed_isRestoredAsInactive() {
        // Start with a rule.
        mZenModeHelper.mConfig.automaticRules.clear();
        AutomaticZenRule rule = new AutomaticZenRule.Builder("Test", CONDITION_ID)
                .setConditionId(CONDITION_ID)
                .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
                .build();
        String ruleId = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(), rule,
                UPDATE_ORIGIN_APP, "add it", CUSTOM_PKG_UID);

        // User customizes it.
        AutomaticZenRule userUpdate = new AutomaticZenRule.Builder(rule)
                .setInterruptionFilter(INTERRUPTION_FILTER_ALARMS)
                .build();
        mZenModeHelper.updateAutomaticZenRule(ruleId, userUpdate, UPDATE_ORIGIN_USER, "userUpdate",
                Process.SYSTEM_UID);
        assertThat(mZenModeHelper.getZenMode()).isEqualTo(ZEN_MODE_OFF);

        // App activates it.
        mZenModeHelper.setAutomaticZenRuleState(ruleId, CONDITION_TRUE, UPDATE_ORIGIN_APP,
                CUSTOM_PKG_UID);
        assertThat(mZenModeHelper.getZenMode()).isEqualTo(ZEN_MODE_ALARMS);

        // User snoozes it.
        mZenModeHelper.setManualZenMode(ZEN_MODE_OFF, null, UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI,
                "snoozing", "systemui", Process.SYSTEM_UID);
        assertThat(mZenModeHelper.getZenMode()).isEqualTo(ZEN_MODE_OFF);

        // App deletes it.
        mZenModeHelper.removeAutomaticZenRule(ruleId, UPDATE_ORIGIN_APP, "delete it",
                CUSTOM_PKG_UID);
        assertThat(mZenModeHelper.mConfig.automaticRules).hasSize(0);
        assertThat(mZenModeHelper.mConfig.deletedRules).hasSize(1);

        // App adds it again.
        String newRuleId = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(), rule,
                UPDATE_ORIGIN_APP, "add it again", CUSTOM_PKG_UID);

        // The rule is restored...
        assertThat(newRuleId).isEqualTo(ruleId);
        AutomaticZenRule finalRule = mZenModeHelper.getAutomaticZenRule(newRuleId);
        assertThat(finalRule.getInterruptionFilter()).isEqualTo(INTERRUPTION_FILTER_ALARMS);

        // ... but it is NEITHER active NOR snoozed.
        ZenRule storedRule = mZenModeHelper.mConfig.automaticRules.get(newRuleId);
        assertThat(storedRule.isAutomaticActive()).isFalse();
        assertThat(storedRule.isTrueOrUnknown()).isFalse();
        assertThat(storedRule.condition).isNull();
        assertThat(storedRule.snoozing).isFalse();
        assertThat(mZenModeHelper.getZenMode()).isEqualTo(ZEN_MODE_OFF);
    }

    @Test
    public void testRuleCleanup() throws Exception {
        mSetFlagsRule.enableFlags(android.app.Flags.FLAG_MODES_API);