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

Commit 37ccd192 authored by Matías Hernández's avatar Matías Hernández
Browse files

Verify rule ownership in setAutomaticZenRuleState

Implementation now matches API documentation -- apps can only activate/deactivate their own rules.

Also refactored applyGlobalZenModeAsImplicitZenRule slightly to remove repetition and call setAutomaticZenRuleStateLocked directly (doesn't need the rule ownership check since we already know it's the implicit rule for that package).

Fixes: 326199494
Test: atest ZenModeHelperTest NotificationManagerZenTest
Change-Id: I4efecaafb7798dc72bf0955c1b1604c92c8f27e8
parent 7e118827
Loading
Loading
Loading
Loading
+29 −13
Original line number Diff line number Diff line
@@ -123,6 +123,7 @@ import java.time.Clock;
import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -593,20 +594,20 @@ public class ZenModeHelper {
            if (mConfig == null) {
                return;
            }
            ZenModeConfig newConfig = mConfig.copy();
            ZenRule rule = newConfig.automaticRules.get(implicitRuleId(callingPkg));
            if (zenMode == Global.ZEN_MODE_OFF) {
                // Deactivate implicit rule if it exists and is active; otherwise ignore.
                ZenRule rule = mConfig.automaticRules.get(implicitRuleId(callingPkg));
                if (rule != null) {
                    Condition deactivated = new Condition(rule.conditionId,
                            mContext.getString(R.string.zen_mode_implicit_deactivated),
                            Condition.STATE_FALSE);
                    setAutomaticZenRuleState(rule.id, deactivated, UPDATE_ORIGIN_APP, callingUid);
                    setAutomaticZenRuleStateLocked(newConfig, Collections.singletonList(rule),
                            deactivated, UPDATE_ORIGIN_APP, callingUid);
                }
            } else {
                // Either create a new rule with a default ZenPolicy, or update an existing rule's
                // filter value. In both cases, also activate (and unsnooze) it.
                ZenModeConfig newConfig = mConfig.copy();
                ZenRule rule = newConfig.automaticRules.get(implicitRuleId(callingPkg));
                if (rule == null) {
                    rule = newImplicitZenRule(callingPkg);

@@ -878,11 +879,19 @@ public class ZenModeHelper {
            if (mConfig == null) return;

            newConfig = mConfig.copy();
            ZenRule rule = newConfig.automaticRules.get(id);
            if (Flags.modesApi()) {
                if (rule != null && canManageAutomaticZenRule(rule)) {
                    setAutomaticZenRuleStateLocked(newConfig, Collections.singletonList(rule),
                            condition, origin, callingUid);
                }
            } else {
                ArrayList<ZenRule> rules = new ArrayList<>();
            rules.add(newConfig.automaticRules.get(id));
                rules.add(rule); // rule may be null and throw NPE in the next method.
                setAutomaticZenRuleStateLocked(newConfig, rules, condition, origin, callingUid);
            }
        }
    }

    void setAutomaticZenRuleState(Uri ruleDefinition, Condition condition,
            @ConfigChangeOrigin int origin, int callingUid) {
@@ -892,9 +901,15 @@ public class ZenModeHelper {
            if (mConfig == null) return;
            newConfig = mConfig.copy();

            setAutomaticZenRuleStateLocked(newConfig,
                    findMatchingRules(newConfig, ruleDefinition, condition),
                    condition, origin, callingUid);
            List<ZenRule> matchingRules = findMatchingRules(newConfig, ruleDefinition, condition);
            if (Flags.modesApi()) {
                for (int i = matchingRules.size() - 1; i >= 0; i--) {
                    if (!canManageAutomaticZenRule(matchingRules.get(i))) {
                        matchingRules.remove(i);
                    }
                }
            }
            setAutomaticZenRuleStateLocked(newConfig, matchingRules, condition, origin, callingUid);
        }
    }

@@ -914,7 +929,8 @@ public class ZenModeHelper {
        }
    }

    private List<ZenRule> findMatchingRules(ZenModeConfig config, Uri id, Condition condition) {
    private static List<ZenRule> findMatchingRules(ZenModeConfig config, Uri id,
            Condition condition) {
        List<ZenRule> matchingRules = new ArrayList<>();
        if (ruleMatches(id, condition, config.manualRule)) {
            matchingRules.add(config.manualRule);
@@ -928,7 +944,7 @@ public class ZenModeHelper {
        return matchingRules;
    }

    private boolean ruleMatches(Uri id, Condition condition, ZenRule rule) {
    private static boolean ruleMatches(Uri id, Condition condition, ZenRule rule) {
        if (id == null || rule == null || rule.conditionId == null) return false;
        if (!rule.conditionId.equals(id)) return false;
        if (Objects.equals(condition, rule.condition)) return false;
+58 −15
Original line number Diff line number Diff line
@@ -260,6 +260,7 @@ public class ZenModeHelperTest extends UiServiceTestCase {
    AppOpsManager mAppOps;
    TestableFlagResolver mTestFlagResolver = new TestableFlagResolver();
    ZenModeEventLoggerFake mZenModeEventLogger;
    private String mPkg;

    @Before
    public void setUp() throws PackageManager.NameNotFoundException {
@@ -270,7 +271,7 @@ public class ZenModeHelperTest extends UiServiceTestCase {
        mContentResolver = mContext.getContentResolver();
        mResources = mock(Resources.class, withSettings()
                .spiedInstance(mContext.getResources()));
        String pkg = mContext.getPackageName();
        mPkg = mContext.getPackageName();
        try {
            when(mResources.getXml(R.xml.default_zen_mode_config)).thenReturn(
                    getDefaultConfigParser());
@@ -301,14 +302,14 @@ public class ZenModeHelperTest extends UiServiceTestCase {
        when(mPackageManager.getPackageUidAsUser(eq(CUSTOM_PKG_NAME), anyInt()))
                .thenReturn(CUSTOM_PKG_UID);
        when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(
                new String[]{pkg});
                new String[]{mPkg});

        ApplicationInfo appInfoSpy = spy(new ApplicationInfo());
        appInfoSpy.icon = ICON_RES_ID;
        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()))
        when(mPackageManager.getApplicationInfo(eq(mPkg), anyInt()))
                .thenReturn(appInfoSpy);
        mZenModeHelper.mPm = mPackageManager;

@@ -2512,16 +2513,16 @@ public class ZenModeHelperTest extends UiServiceTestCase {
        scheduleInfo.endHour = 1;
        Uri sharedUri = ZenModeConfig.toScheduleConditionId(scheduleInfo);
        AutomaticZenRule zenRule = new AutomaticZenRule("name",
                new ComponentName("android", "ScheduleConditionProvider"),
                new ComponentName(mPkg, "ScheduleConditionProvider"),
                sharedUri,
                NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
        String id = mZenModeHelper.addAutomaticZenRule("android", zenRule,
        String id = mZenModeHelper.addAutomaticZenRule(mPkg, zenRule,
                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, "test", Process.SYSTEM_UID);
        AutomaticZenRule zenRule2 = new AutomaticZenRule("name2",
                new ComponentName("android", "ScheduleConditionProvider"),
                new ComponentName(mPkg, "ScheduleConditionProvider"),
                sharedUri,
                NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
        String id2 = mZenModeHelper.addAutomaticZenRule("android", zenRule2,
        String id2 = mZenModeHelper.addAutomaticZenRule(mPkg, zenRule2,
                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, "test", Process.SYSTEM_UID);

        Condition condition = new Condition(sharedUri, "", STATE_TRUE);
@@ -2531,11 +2532,11 @@ public class ZenModeHelperTest extends UiServiceTestCase {
        for (ZenModeConfig.ZenRule rule : mZenModeHelper.mConfig.automaticRules.values()) {
            if (rule.id.equals(id)) {
                assertNotNull(rule.condition);
                assertTrue(rule.condition.state == STATE_TRUE);
                assertEquals(STATE_TRUE, rule.condition.state);
            }
            if (rule.id.equals(id2)) {
                assertNotNull(rule.condition);
                assertTrue(rule.condition.state == STATE_TRUE);
                assertEquals(STATE_TRUE, rule.condition.state);
            }
        }

@@ -2546,11 +2547,11 @@ public class ZenModeHelperTest extends UiServiceTestCase {
        for (ZenModeConfig.ZenRule rule : mZenModeHelper.mConfig.automaticRules.values()) {
            if (rule.id.equals(id)) {
                assertNotNull(rule.condition);
                assertTrue(rule.condition.state == STATE_FALSE);
                assertEquals(STATE_FALSE, rule.condition.state);
            }
            if (rule.id.equals(id2)) {
                assertNotNull(rule.condition);
                assertTrue(rule.condition.state == STATE_FALSE);
                assertEquals(STATE_FALSE, rule.condition.state);
            }
        }
    }
@@ -3637,14 +3638,14 @@ public class ZenModeHelperTest extends UiServiceTestCase {
        AutomaticZenRule bedtime = new AutomaticZenRule.Builder("Bedtime Mode (TM)", CONDITION_ID)
                .setType(TYPE_BEDTIME)
                .build();
        String bedtimeRuleId = mZenModeHelper.addAutomaticZenRule("pkg", bedtime, UPDATE_ORIGIN_APP,
        String bedtimeRuleId = mZenModeHelper.addAutomaticZenRule(mPkg, bedtime, UPDATE_ORIGIN_APP,
                "reason", CUSTOM_PKG_UID);

        // Create immersive rule
        AutomaticZenRule immersive = new AutomaticZenRule.Builder("Immersed", CONDITION_ID)
                .setType(TYPE_IMMERSIVE)
                .build();
        String immersiveId = mZenModeHelper.addAutomaticZenRule("pkg", immersive, UPDATE_ORIGIN_APP,
        String immersiveId = mZenModeHelper.addAutomaticZenRule(mPkg, immersive, UPDATE_ORIGIN_APP,
                "reason", CUSTOM_PKG_UID);

        // Event 2: Activate bedtime rule
@@ -5433,6 +5434,48 @@ public class ZenModeHelperTest extends UiServiceTestCase {
                Condition.STATE_UNKNOWN);
    }

    @Test
    @EnableFlags(Flags.FLAG_MODES_API)
    public void setAutomaticZenRuleState_idForNotOwnedRule_ignored() {
        // Assume existence of an other-package-owned rule that is currently ACTIVE.
        assertThat(mZenModeHelper.getZenMode()).isEqualTo(ZEN_MODE_OFF);
        ZenRule otherRule = newZenRule("another.package", Instant.now(), null);
        otherRule.zenMode = ZEN_MODE_ALARMS;
        otherRule.condition = new Condition(otherRule.conditionId, "on", Condition.STATE_TRUE);
        ZenModeConfig config = mZenModeHelper.mConfig.copy();
        config.automaticRules.put("otherRule", otherRule);
        mZenModeHelper.setConfig(config, null, UPDATE_ORIGIN_INIT, "", Process.SYSTEM_UID);
        assertThat(mZenModeHelper.getZenMode()).isEqualTo(ZEN_MODE_ALARMS);

        // Should be ignored.
        mZenModeHelper.setAutomaticZenRuleState("otherRule",
                new Condition(otherRule.conditionId, "off", Condition.STATE_FALSE),
                UPDATE_ORIGIN_APP, CUSTOM_PKG_UID);

        assertThat(mZenModeHelper.getZenMode()).isEqualTo(ZEN_MODE_ALARMS);
    }

    @Test
    @EnableFlags(Flags.FLAG_MODES_API)
    public void setAutomaticZenRuleState_conditionForNotOwnedRule_ignored() {
        // Assume existence of an other-package-owned rule that is currently ACTIVE.
        assertThat(mZenModeHelper.getZenMode()).isEqualTo(ZEN_MODE_OFF);
        ZenRule otherRule = newZenRule("another.package", Instant.now(), null);
        otherRule.zenMode = ZEN_MODE_ALARMS;
        otherRule.condition = new Condition(otherRule.conditionId, "on", Condition.STATE_TRUE);
        ZenModeConfig config = mZenModeHelper.mConfig.copy();
        config.automaticRules.put("otherRule", otherRule);
        mZenModeHelper.setConfig(config, null, UPDATE_ORIGIN_INIT, "", Process.SYSTEM_UID);
        assertThat(mZenModeHelper.getZenMode()).isEqualTo(ZEN_MODE_ALARMS);

        // Should be ignored.
        mZenModeHelper.setAutomaticZenRuleState(otherRule.conditionId,
                new Condition(otherRule.conditionId, "off", Condition.STATE_FALSE),
                UPDATE_ORIGIN_APP, CUSTOM_PKG_UID);

        assertThat(mZenModeHelper.getZenMode()).isEqualTo(ZEN_MODE_ALARMS);
    }

    @Test
    @EnableFlags(android.app.Flags.FLAG_MODES_API)
    public void testCallbacks_policy() throws Exception {
@@ -5583,13 +5626,13 @@ public class ZenModeHelperTest extends UiServiceTestCase {
    public void applyGlobalZenModeAsImplicitZenRule_modeOff_deactivatesImplicitRule() {
        mSetFlagsRule.enableFlags(android.app.Flags.FLAG_MODES_API);
        mZenModeHelper.mConfig.automaticRules.clear();
        mZenModeHelper.applyGlobalZenModeAsImplicitZenRule(CUSTOM_PKG_NAME, CUSTOM_PKG_UID,
        mZenModeHelper.applyGlobalZenModeAsImplicitZenRule(mPkg, CUSTOM_PKG_UID,
                ZEN_MODE_IMPORTANT_INTERRUPTIONS);
        assertThat(mZenModeHelper.mConfig.automaticRules).hasSize(1);
        assertThat(mZenModeHelper.mConfig.automaticRules.valueAt(0).condition.state)
                .isEqualTo(STATE_TRUE);

        mZenModeHelper.applyGlobalZenModeAsImplicitZenRule(CUSTOM_PKG_NAME, CUSTOM_PKG_UID,
        mZenModeHelper.applyGlobalZenModeAsImplicitZenRule(mPkg, CUSTOM_PKG_UID,
                ZEN_MODE_OFF);

        assertThat(mZenModeHelper.mConfig.automaticRules.valueAt(0).condition.state)