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

Commit 75fc4f27 authored by Yuri Lin's avatar Yuri Lin
Browse files

Update ZenModeEventLogger to log change origin and rule package UID

This change adds the actual change origin enum to DNDStateChanged output for more specific information than the simple boolean "is user action" (thoug h that boolean also remains available). Also logs the rule owner's package uid rather than the caller in more cases, as the Settings UI now adds more ways in which the user can modify an app-owned mode through Settings.

Flag: android.app.modes_ui
Bug: 316950757
Test: ZenModeHelperTest, manual via statsd_testdrive
Change-Id: Ibad093a69d99c29675703197fd7e757a916b2e7a
parent 41bbda58
Loading
Loading
Loading
Loading
+39 −11
Original line number Diff line number Diff line
@@ -127,6 +127,9 @@ class ZenModeEventLogger {
    /**
     * Reassign callingUid in mChangeState if we have more specific information that warrants it
     * (for instance, if the change is automatic and due to an automatic rule change).
     *
     * <p>When Flags.modesUi() is enabled, we reassign the calling UID to the package UID in all
     * changes whose source is not system or system UI, as long as there is only one rule changed.
     */
    private void maybeReassignCallingUid() {
        int userId = Process.INVALID_UID;
@@ -145,13 +148,24 @@ class ZenModeEventLogger {
            userId = mChangeState.mNewConfig.user;  // mNewConfig must not be null if enabler exists
        }

        // The conditions where we should consider reassigning UID for an automatic rule change:
        // The conditions where we should consider reassigning UID for an automatic rule change
        // (pre-modes_ui):
        //   - we've determined it's not a user action
        //   - our current best guess is that the calling uid is system/sysui
        // When Flags.modesUi() is true, we get the package UID for the changed rule, as long as:
        //   - the change does not originate from the system based on change origin
        //   - there is only one rule changed
        if (mChangeState.getChangedRuleType() == RULE_TYPE_AUTOMATIC) {
            if (Flags.modesUi()) {
                // ignore anything whose origin is system
                if (mChangeState.isFromSystemOrSystemUi()) {
                    return;
                }
            } else {
                if (mChangeState.getIsUserAction() || !mChangeState.isFromSystemOrSystemUi()) {
                    return;
                }
            }

            // Only try to get the package UID if there's exactly one changed automatic rule. If
            // there's more than one that changes simultaneously, this is likely to be a boot and
@@ -202,7 +216,8 @@ class ZenModeEventLogger {
                /* int32 package_uid = 7 */ mChangeState.getPackageUid(),
                /* DNDPolicyProto current_policy = 8 */ mChangeState.getDNDPolicyProto(),
                /* bool are_channels_bypassing = 9 */ mChangeState.getAreChannelsBypassing(),
                /* ActiveRuleType active_rule_types = 10 */ mChangeState.getActiveRuleTypes());
                /* ActiveRuleType active_rule_types = 10 */ mChangeState.getActiveRuleTypes(),
                /* ChangeOrigin change_origin = 11 */ mChangeState.getChangeOrigin());
    }

    /**
@@ -235,7 +250,8 @@ class ZenModeEventLogger {
        ZenModeConfig mPrevConfig, mNewConfig;
        NotificationManager.Policy mPrevPolicy, mNewPolicy;
        int mCallingUid = Process.INVALID_UID;
        @ConfigChangeOrigin int mOrigin = ZenModeConfig.UPDATE_ORIGIN_UNKNOWN;
        @ConfigChangeOrigin
        int mOrigin = ZenModeConfig.UPDATE_ORIGIN_UNKNOWN;

        private void init(ZenModeInfo prevInfo, ZenModeInfo newInfo, int callingUid,
                @ConfigChangeOrigin int origin) {
@@ -388,7 +404,8 @@ class ZenModeEventLogger {
         * rules available.
         */
        @SuppressLint("WrongConstant")  // special case for log-only type on manual rule
        @NonNull List<ZenRule> activeRulesList(ZenModeConfig config) {
        @NonNull
        List<ZenRule> activeRulesList(ZenModeConfig config) {
            ArrayList<ZenRule> rules = new ArrayList<>();
            if (config == null) {
                return rules;
@@ -547,6 +564,17 @@ class ZenModeEventLogger {
            return mCallingUid;
        }

        /**
         * Get the config change origin associated with this change, which is stored in mOrigin.
         * Only useable if modes_ui is true.
         */
        int getChangeOrigin() {
            if (Flags.modesUi()) {
                return mOrigin;
            }
            return 0;
        }

        /**
         * Convert the new policy to a DNDPolicyProto format for output in logs.
         *
+5 −0
Original line number Diff line number Diff line
@@ -137,4 +137,9 @@ public class ZenModeEventLoggerFake extends ZenModeEventLogger {
        checkInRange(i);
        return mChanges.get(i).getActiveRuleTypes();
    }

    public int getChangeOrigin(int i) throws IllegalArgumentException {
        checkInRange(i);
        return mChanges.get(i).getChangeOrigin();
    }
}
+76 −41
Original line number Diff line number Diff line
@@ -1067,7 +1067,8 @@ public class ZenModeHelperTest extends UiServiceTestCase {
        mZenModeHelper.setNotificationPolicy(new Policy(PRIORITY_CATEGORY_EVENTS
                        | PRIORITY_CATEGORY_MESSAGES | PRIORITY_CATEGORY_REPEAT_CALLERS
                        | PRIORITY_CATEGORY_CONVERSATIONS, PRIORITY_SENDERS_STARRED,
                PRIORITY_SENDERS_STARRED, 0, CONVERSATION_SENDERS_ANYONE), UPDATE_ORIGIN_UNKNOWN,
                        PRIORITY_SENDERS_STARRED, 0, CONVERSATION_SENDERS_ANYONE),
                UPDATE_ORIGIN_UNKNOWN,
                1);
        mZenModeHelper.setManualZenRuleDeviceEffects(new ZenDeviceEffects.Builder()
                .setShouldDimWallpaper(true)
@@ -1087,7 +1088,8 @@ public class ZenModeHelperTest extends UiServiceTestCase {
        mZenModeHelper.setNotificationPolicy(new Policy(PRIORITY_CATEGORY_EVENTS
                        | PRIORITY_CATEGORY_MESSAGES | PRIORITY_CATEGORY_REPEAT_CALLERS
                        | PRIORITY_CATEGORY_CONVERSATIONS, PRIORITY_SENDERS_STARRED,
                PRIORITY_SENDERS_STARRED, SUPPRESSED_EFFECT_BADGE, CONVERSATION_SENDERS_ANYONE),
                        PRIORITY_SENDERS_STARRED, SUPPRESSED_EFFECT_BADGE,
                        CONVERSATION_SENDERS_ANYONE),
                UPDATE_ORIGIN_UNKNOWN, 1);
        mZenModeHelper.setManualZenRuleDeviceEffects(new ZenDeviceEffects.Builder()
                .setShouldDimWallpaper(true)
@@ -3060,6 +3062,9 @@ public class ZenModeHelperTest extends UiServiceTestCase {
        assertTrue(mZenModeEventLogger.getIsUserAction(0));
        assertEquals(Process.SYSTEM_UID, mZenModeEventLogger.getPackageUid(0));
        checkDndProtoMatchesSetupZenConfig(mZenModeEventLogger.getPolicyProto(0));
        // change origin should be populated only under modes_ui
        assertThat(mZenModeEventLogger.getChangeOrigin(0)).isEqualTo(
                (Flags.modesApi() && Flags.modesUi()) ? UPDATE_ORIGIN_USER : 0);

        // and from turning zen mode off:
        //   - event ID: DND_TURNED_OFF
@@ -3082,6 +3087,8 @@ public class ZenModeHelperTest extends UiServiceTestCase {
        } else {
            checkDndProtoMatchesSetupZenConfig(mZenModeEventLogger.getPolicyProto(1));
        }
        assertThat(mZenModeEventLogger.getChangeOrigin(1)).isEqualTo(
                Flags.modesUi() ? UPDATE_ORIGIN_APP : 0);
    }

    @Test
@@ -3098,12 +3105,16 @@ public class ZenModeHelperTest extends UiServiceTestCase {
                null,
                NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
        String id = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(), zenRule,
                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, "test", Process.SYSTEM_UID);
                UPDATE_ORIGIN_APP, "test", CUSTOM_PKG_UID);

        // Event 1: Mimic the rule coming on automatically by setting the Condition to STATE_TRUE
        // Note that pre-modes_ui, this event serves as a test that automatic changes to an app's
        // that look like they're coming from the system are attributed to the app, but when
        // modes_ui is true, we opt to trust the provided change origin.
        mZenModeHelper.setAutomaticZenRuleState(id,
                new Condition(zenRule.getConditionId(), "", STATE_TRUE),
                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, Process.SYSTEM_UID);
                Flags.modesUi() ? UPDATE_ORIGIN_APP : UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI,
                CUSTOM_PKG_UID);

        // Event 2: "User" turns off the automatic rule (sets it to not enabled)
        zenRule.setEnabled(false);
@@ -3151,9 +3162,13 @@ public class ZenModeHelperTest extends UiServiceTestCase {
        assertFalse(mZenModeEventLogger.getIsUserAction(0));
        assertEquals(CUSTOM_PKG_UID, mZenModeEventLogger.getPackageUid(0));
        checkDndProtoMatchesDefaultZenConfig(mZenModeEventLogger.getPolicyProto(0));
        assertThat(mZenModeEventLogger.getChangeOrigin(0)).isEqualTo(
                Flags.modesUi() ? UPDATE_ORIGIN_APP : 0);

        // When the automatic rule is disabled, this should turn off zen mode and also count as a
        // user action. We don't care what the consolidated policy is when DND turns off.
        // When modes_ui is true, this event should look like a user action attributed to the
        // specific app.
        assertEquals(ZenModeEventLogger.ZenStateChangedEvent.DND_TURNED_OFF.getId(),
                mZenModeEventLogger.getEventId(1));
        assertEquals(ZEN_MODE_IMPORTANT_INTERRUPTIONS, mZenModeEventLogger.getPrevZenMode(1));
@@ -3161,12 +3176,15 @@ public class ZenModeHelperTest extends UiServiceTestCase {
        assertEquals(DNDProtoEnums.AUTOMATIC_RULE, mZenModeEventLogger.getChangedRuleType(1));
        assertEquals(0, mZenModeEventLogger.getNumRulesActive(1));
        assertTrue(mZenModeEventLogger.getIsUserAction(1));
        assertEquals(Process.SYSTEM_UID, mZenModeEventLogger.getPackageUid(1));
        assertThat(mZenModeEventLogger.getPackageUid(1)).isEqualTo(
                Flags.modesUi() ? CUSTOM_PKG_UID : Process.SYSTEM_UID);
        if (Flags.modesApi()) {
            assertThat(mZenModeEventLogger.getPolicyProto(1)).isNull();
        } else {
            checkDndProtoMatchesSetupZenConfig(mZenModeEventLogger.getPolicyProto(1));
        }
        assertThat(mZenModeEventLogger.getChangeOrigin(1)).isEqualTo(
                Flags.modesUi() ? UPDATE_ORIGIN_USER : 0);

        // When the system rule is enabled, this counts as an automatic action that comes from the
        // system and turns on DND
@@ -3176,6 +3194,8 @@ public class ZenModeHelperTest extends UiServiceTestCase {
        assertEquals(1, mZenModeEventLogger.getNumRulesActive(2));
        assertFalse(mZenModeEventLogger.getIsUserAction(2));
        assertEquals(Process.SYSTEM_UID, mZenModeEventLogger.getPackageUid(2));
        assertThat(mZenModeEventLogger.getChangeOrigin(2)).isEqualTo(
                Flags.modesUi() ? UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI : 0);

        // When the system rule is deleted, we consider this a user action that turns DND off
        // (again)
@@ -3185,6 +3205,8 @@ public class ZenModeHelperTest extends UiServiceTestCase {
        assertEquals(0, mZenModeEventLogger.getNumRulesActive(3));
        assertTrue(mZenModeEventLogger.getIsUserAction(3));
        assertEquals(Process.SYSTEM_UID, mZenModeEventLogger.getPackageUid(3));
        assertThat(mZenModeEventLogger.getChangeOrigin(3)).isEqualTo(
                Flags.modesUi() ? UPDATE_ORIGIN_USER : 0);
    }

    @Test
@@ -3238,6 +3260,8 @@ public class ZenModeHelperTest extends UiServiceTestCase {
        assertEquals(1, mZenModeEventLogger.getNumRulesActive(0));
        assertTrue(mZenModeEventLogger.getIsUserAction(0));
        assertEquals(CUSTOM_PKG_UID, mZenModeEventLogger.getPackageUid(0));
        assertThat(mZenModeEventLogger.getChangeOrigin(0)).isEqualTo(
                Flags.modesUi() ? UPDATE_ORIGIN_USER : 0);

        // Automatic rule turned off automatically by app:
        //   - event ID: DND_TURNED_OFF
@@ -3249,6 +3273,8 @@ public class ZenModeHelperTest extends UiServiceTestCase {
        assertEquals(0, mZenModeEventLogger.getNumRulesActive(1));
        assertFalse(mZenModeEventLogger.getIsUserAction(1));
        assertEquals(CUSTOM_PKG_UID, mZenModeEventLogger.getPackageUid(1));
        assertThat(mZenModeEventLogger.getChangeOrigin(1)).isEqualTo(
                Flags.modesUi() ? UPDATE_ORIGIN_APP : 0);

        // Automatic rule turned on automatically by app:
        //   - event ID: DND_TURNED_ON
@@ -3261,6 +3287,8 @@ public class ZenModeHelperTest extends UiServiceTestCase {
        assertEquals(1, mZenModeEventLogger.getNumRulesActive(2));
        assertFalse(mZenModeEventLogger.getIsUserAction(2));
        assertEquals(CUSTOM_PKG_UID, mZenModeEventLogger.getPackageUid(2));
        assertThat(mZenModeEventLogger.getChangeOrigin(2)).isEqualTo(
                Flags.modesUi() ? UPDATE_ORIGIN_APP : 0);

        // Automatic rule turned off automatically by the user:
        //   - event ID: DND_TURNED_ON
@@ -3272,6 +3300,8 @@ public class ZenModeHelperTest extends UiServiceTestCase {
        assertEquals(0, mZenModeEventLogger.getNumRulesActive(3));
        assertTrue(mZenModeEventLogger.getIsUserAction(3));
        assertEquals(CUSTOM_PKG_UID, mZenModeEventLogger.getPackageUid(3));
        assertThat(mZenModeEventLogger.getChangeOrigin(3)).isEqualTo(
                Flags.modesUi() ? UPDATE_ORIGIN_USER : 0);
    }

    @Test
@@ -3335,7 +3365,7 @@ public class ZenModeHelperTest extends UiServiceTestCase {

        AutomaticZenRule zenRule = new AutomaticZenRule("name",
                null,
                new ComponentName(CUSTOM_PKG_NAME, "ScheduleConditionProvider"),
                new ComponentName("android", "ScheduleConditionProvider"),
                ZenModeConfig.toScheduleConditionId(new ScheduleInfo()),
                null,
                NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
@@ -3345,7 +3375,7 @@ public class ZenModeHelperTest extends UiServiceTestCase {
        // Rule 2, same as rule 1
        AutomaticZenRule zenRule2 = new AutomaticZenRule("name2",
                null,
                new ComponentName(CUSTOM_PKG_NAME, "ScheduleConditionProvider"),
                new ComponentName("android", "ScheduleConditionProvider"),
                ZenModeConfig.toScheduleConditionId(new ScheduleInfo()),
                null,
                NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
@@ -3395,7 +3425,7 @@ public class ZenModeHelperTest extends UiServiceTestCase {
        assertEquals(ZEN_MODE_IMPORTANT_INTERRUPTIONS, mZenModeEventLogger.getNewZenMode(0));
        assertEquals(1, mZenModeEventLogger.getNumRulesActive(0));
        assertFalse(mZenModeEventLogger.getIsUserAction(0));
        assertEquals(CUSTOM_PKG_UID, mZenModeEventLogger.getPackageUid(0));
        assertEquals(Process.SYSTEM_UID, mZenModeEventLogger.getPackageUid(0));
        checkDndProtoMatchesDefaultZenConfig(mZenModeEventLogger.getPolicyProto(0));

        // Event 2: rule 2 turns on. This should not change anything about the policy, so the only
@@ -3404,7 +3434,7 @@ public class ZenModeHelperTest extends UiServiceTestCase {
                mZenModeEventLogger.getEventId(1));
        assertEquals(2, mZenModeEventLogger.getNumRulesActive(1));
        assertFalse(mZenModeEventLogger.getIsUserAction(1));
        assertEquals(CUSTOM_PKG_UID, mZenModeEventLogger.getPackageUid(1));
        assertEquals(Process.SYSTEM_UID, mZenModeEventLogger.getPackageUid(1));
        checkDndProtoMatchesDefaultZenConfig(mZenModeEventLogger.getPolicyProto(1));

        // Event 3: rule 3 turns on. This should trigger a policy change, and be classified as such,
@@ -3482,9 +3512,11 @@ public class ZenModeHelperTest extends UiServiceTestCase {
        // Turn on rule 1; call looks like it's from the system. Because setting a condition is
        // typically an automatic (non-user-initiated) action, expect the calling UID to be
        // re-evaluated to the one associated with CUSTOM_PKG_NAME.
        // When modes_ui is true: we expect the change origin to be the source of truth.
        mZenModeHelper.setAutomaticZenRuleState(id,
                new Condition(zenRule.getConditionId(), "", STATE_TRUE),
                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, Process.SYSTEM_UID);
                Flags.modesUi() ? UPDATE_ORIGIN_APP : UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI,
                Process.SYSTEM_UID);

        // Second: turn on rule 2. This is a system-owned rule and the UID should not be modified
        // (nor even looked up; the mock PackageManager won't handle "android" as input).
@@ -3493,7 +3525,7 @@ public class ZenModeHelperTest extends UiServiceTestCase {
                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, Process.SYSTEM_UID);

        // Disable rule 1. Because this looks like a user action, the UID should not be modified
        // from the system-provided one.
        // from the system-provided one unless modes_ui is true.
        zenRule.setEnabled(false);
        mZenModeHelper.updateAutomaticZenRule(id, zenRule,
                UPDATE_ORIGIN_USER, "", Process.SYSTEM_UID);
@@ -3504,6 +3536,7 @@ public class ZenModeHelperTest extends UiServiceTestCase {

        // Change rule 2's condition, but from some other UID. Since it doesn't look like it's from
        // the system, we keep the UID info.
        // Note that this probably shouldn't be able to occur in real scenarios.
        mZenModeHelper.setAutomaticZenRuleState(id2,
                new Condition(zenRule2.getConditionId(), "", STATE_FALSE),
                UPDATE_ORIGIN_APP, 12345);
@@ -3528,11 +3561,13 @@ public class ZenModeHelperTest extends UiServiceTestCase {
        assertEquals(Process.SYSTEM_UID, mZenModeEventLogger.getPackageUid(1));

        // Third event: disable rule 1. This looks like a user action so UID should be left alone.
        // When modes_ui is true, we assign log this user action with the app that owns the rule.
        assertEquals(ZenModeEventLogger.ZenStateChangedEvent.DND_ACTIVE_RULES_CHANGED.getId(),
                mZenModeEventLogger.getEventId(2));
        assertEquals(DNDProtoEnums.AUTOMATIC_RULE, mZenModeEventLogger.getChangedRuleType(2));
        assertTrue(mZenModeEventLogger.getIsUserAction(2));
        assertEquals(Process.SYSTEM_UID, mZenModeEventLogger.getPackageUid(2));
        assertThat(mZenModeEventLogger.getPackageUid(2)).isEqualTo(
                Flags.modesUi() ? CUSTOM_PKG_UID : Process.SYSTEM_UID);

        // Fourth event: turns on manual mode. Doesn't change effective policy so this is just a
        // change in active rules. Confirm that the package UID is left unchanged.