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

Commit 01522013 authored by Yuri Lin's avatar Yuri Lin Committed by Android (Google) Code Review
Browse files

Merge "Log active rule types to DND log output." into main

parents b39512ee fb19b910
Loading
Loading
Loading
Loading
+61 −14
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import static android.service.notification.NotificationServiceProto.RULE_TYPE_UN

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.app.Flags;
import android.app.NotificationManager;
import android.content.pm.PackageManager;
@@ -33,6 +34,7 @@ import android.os.Process;
import android.service.notification.DNDPolicyProto;
import android.service.notification.ZenModeConfig;
import android.service.notification.ZenModeConfig.ConfigChangeOrigin;
import android.service.notification.ZenModeConfig.ZenRule;
import android.service.notification.ZenModeDiff;
import android.service.notification.ZenPolicy;
import android.util.ArrayMap;
@@ -46,6 +48,9 @@ import com.android.internal.logging.UiEventLogger;
import com.android.internal.util.FrameworkStatsLog;

import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

/**
@@ -58,6 +63,9 @@ class ZenModeEventLogger {
    // Placeholder int for unknown zen mode, to distinguish from "off".
    static final int ZEN_MODE_UNKNOWN = -1;

    // Special rule type for manual rule. Keep in sync with ActiveRuleType in dnd_enums.proto.
    protected static final int ACTIVE_RULE_TYPE_MANUAL = 999;

    // Object for tracking config changes and policy changes associated with an overall zen
    // mode change.
    ZenModeEventLogger.ZenStateChanges mChangeState = new ZenModeEventLogger.ZenStateChanges();
@@ -192,7 +200,8 @@ class ZenModeEventLogger {
                /* bool user_action = 6 */ mChangeState.getIsUserAction(),
                /* int32 package_uid = 7 */ mChangeState.getPackageUid(),
                /* DNDPolicyProto current_policy = 8 */ mChangeState.getDNDPolicyProto(),
                /* bool are_channels_bypassing = 9 */ mChangeState.getAreChannelsBypassing());
                /* bool are_channels_bypassing = 9 */ mChangeState.getAreChannelsBypassing(),
                /* ActiveRuleType active_rule_types = 10 */ mChangeState.getActiveRuleTypes());
    }

    /**
@@ -371,35 +380,45 @@ class ZenModeEventLogger {
        }

        /**
         * Get the number of active rules represented in a zen mode config. Because this is based
         * on a config, this does not take into account the zen mode at the time of the config,
         * which means callers need to take the zen mode into account for whether the rules are
         * actually active.
         * Get a list of the active rules in the provided config. This is a helper function for
         * other methods that then use this information to get the number and type of active
         * rules available.
         */
        int numActiveRulesInConfig(ZenModeConfig config) {
            // If the config is null, return early
        @SuppressLint("WrongConstant")  // special case for log-only type on manual rule
        @NonNull List<ZenRule> activeRulesList(ZenModeConfig config) {
            ArrayList<ZenRule> rules = new ArrayList<>();
            if (config == null) {
                return 0;
                return rules;
            }

            int rules = 0;
            // Loop through the config and check:
            //  - does a manual rule exist? (if it's non-null, it's active)
            //  - how many automatic rules are active, as defined by isAutomaticActive()?
            if (config.manualRule != null) {
                rules++;
                // If the manual rule is non-null, then it's active. We make a copy and set the rule
                // type so that the correct value gets logged.
                ZenRule rule = config.manualRule.copy();
                rule.type = ACTIVE_RULE_TYPE_MANUAL;
                rules.add(rule);
            }

            if (config.automaticRules != null) {
                for (ZenModeConfig.ZenRule rule : config.automaticRules.values()) {
                    if (rule != null && rule.isAutomaticActive()) {
                        rules++;
                        rules.add(rule);
                    }
                }
            }
            return rules;
        }

        /**
         * Get the number of active rules represented in a zen mode config. Because this is based
         * on a config, this does not take into account the zen mode at the time of the config,
         * which means callers need to take the zen mode into account for whether the rules are
         * actually active.
         */
        int numActiveRulesInConfig(ZenModeConfig config) {
            return activeRulesList(config).size();
        }

        // Determine the number of (automatic & manual) rules active after the change takes place.
        int getNumRulesActive() {
            if (!Flags.modesApi()) {
@@ -411,6 +430,34 @@ class ZenModeEventLogger {
            return numActiveRulesInConfig(mNewConfig);
        }

        /**
         * Return a list of the types of each of the active rules in the configuration.
         * Only available when {@code MODES_API} is active; otherwise returns an empty list.
         */
        int[] getActiveRuleTypes() {
            if (!Flags.modesApi() || mNewZenMode == ZEN_MODE_OFF) {
                return new int[0];
            }

            ArrayList<Integer> activeTypes = new ArrayList<>();
            List<ZenRule> activeRules = activeRulesList(mNewConfig);
            if (activeRules.size() == 0) {
                return new int[0];
            }

            for (ZenRule rule : activeRules) {
                activeTypes.add(rule.type);
            }

            // Sort the list of active types to have a consistent order in the atom
            Collections.sort(activeTypes);
            int[] out = new int[activeTypes.size()];
            for (int i = 0; i < activeTypes.size(); i++) {
                out[i] = activeTypes.get(i);
            }
            return out;
        }

        /**
         * Return our best guess as to whether the changes observed are due to a user action.
         * Note that this (before {@code MODES_API}) won't be 100% accurate as we can't necessarily
+7 −2
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.server.notification;

import static android.app.AutomaticZenRule.TYPE_UNKNOWN;
import static android.app.NotificationManager.AUTOMATIC_RULE_STATUS_ACTIVATED;
import static android.app.NotificationManager.AUTOMATIC_RULE_STATUS_DEACTIVATED;
import static android.app.NotificationManager.AUTOMATIC_RULE_STATUS_DISABLED;
@@ -2170,7 +2171,8 @@ public class ZenModeHelper {
                        /* optional DNDPolicyProto policy = 7 */ config.toZenPolicy().toProto(),
                        /* optional int32 rule_modified_fields = 8 */ 0,
                        /* optional int32 policy_modified_fields = 9 */ 0,
                        /* optional int32 device_effects_modified_fields = 10 */ 0));
                        /* optional int32 device_effects_modified_fields = 10 */ 0,
                        /* optional ActiveRuleType rule_type = 11 */ TYPE_UNKNOWN));
                if (config.manualRule != null) {
                    ruleToProtoLocked(user, config.manualRule, true, events);
                }
@@ -2196,8 +2198,10 @@ public class ZenModeHelper {
            pkg = rule.enabler;
        }

        int ruleType = rule.type;
        if (isManualRule) {
            id = ZenModeConfig.MANUAL_RULE_ID;
            ruleType = ZenModeEventLogger.ACTIVE_RULE_TYPE_MANUAL;
        }

        SysUiStatsEvent.Builder data;
@@ -2216,7 +2220,8 @@ public class ZenModeHelper {
                /* optional int32 rule_modified_fields = 8 */ rule.userModifiedFields,
                /* optional int32 policy_modified_fields = 9 */ rule.zenPolicyUserModifiedFields,
                /* optional int32 device_effects_modified_fields = 10 */
                rule.zenDeviceEffectsUserModifiedFields));
                rule.zenDeviceEffectsUserModifiedFields,
                /* optional ActiveRuleType rule_type = 11 */ ruleType));
    }

    private int getPackageUid(String pkg, int user) {
+5 −0
Original line number Diff line number Diff line
@@ -132,4 +132,9 @@ public class ZenModeEventLoggerFake extends ZenModeEventLogger {
        checkInRange(i);
        return mChanges.get(i).getAreChannelsBypassing();
    }

    public int[] getActiveRuleTypes(int i) throws IllegalArgumentException {
        checkInRange(i);
        return mChanges.get(i).getActiveRuleTypes();
    }
}
+85 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.server.notification;

import static android.app.AutomaticZenRule.TYPE_BEDTIME;
import static android.app.AutomaticZenRule.TYPE_IMMERSIVE;
import static android.app.NotificationManager.AUTOMATIC_RULE_STATUS_ACTIVATED;
import static android.app.NotificationManager.AUTOMATIC_RULE_STATUS_DEACTIVATED;
import static android.app.NotificationManager.AUTOMATIC_RULE_STATUS_DISABLED;
@@ -68,6 +69,7 @@ import static com.android.os.dnd.DNDProtoEnums.PEOPLE_STARRED;
import static com.android.os.dnd.DNDProtoEnums.ROOT_CONFIG;
import static com.android.os.dnd.DNDProtoEnums.STATE_ALLOW;
import static com.android.os.dnd.DNDProtoEnums.STATE_DISALLOW;
import static com.android.server.notification.ZenModeEventLogger.ACTIVE_RULE_TYPE_MANUAL;
import static com.android.server.notification.ZenModeHelper.RULE_LIMIT_PER_PACKAGE;

import static com.google.common.collect.Iterables.getOnlyElement;
@@ -3553,6 +3555,89 @@ public class ZenModeHelperTest extends UiServiceTestCase {
        assertThat(mZenModeEventLogger.getPolicyProto(1)).isNull();
    }

    @Test
    @EnableFlags(Flags.FLAG_MODES_API)
    public void testZenModeEventLog_activeRuleTypes() {
        mTestFlagResolver.setFlagOverride(LOG_DND_STATE_EVENTS, true);
        setupZenConfig();

        // Event 1: turn on manual zen mode. Manual rule will have ACTIVE_RULE_TYPE_MANUAL
        mZenModeHelper.setManualZenMode(ZEN_MODE_IMPORTANT_INTERRUPTIONS, null,
                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, "", null, Process.SYSTEM_UID);

        // Create bedtime rule
        AutomaticZenRule bedtime = new AutomaticZenRule.Builder("Bedtime Mode (TM)", CONDITION_ID)
                .setType(TYPE_BEDTIME)
                .build();
        String bedtimeRuleId = mZenModeHelper.addAutomaticZenRule("pkg", 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,
                "reason", CUSTOM_PKG_UID);

        // Event 2: Activate bedtime rule
        mZenModeHelper.setAutomaticZenRuleState(bedtimeRuleId,
                new Condition(bedtime.getConditionId(), "", STATE_TRUE, SOURCE_SCHEDULE),
                UPDATE_ORIGIN_APP, CUSTOM_PKG_UID);

        // Event 3: Turn immersive on
        mZenModeHelper.setAutomaticZenRuleState(immersiveId,
                new Condition(immersive.getConditionId(), "", STATE_TRUE, SOURCE_SCHEDULE),
                UPDATE_ORIGIN_APP, CUSTOM_PKG_UID);

        // Event 4: Turn off bedtime mode, leaving just unknown + immersive
        mZenModeHelper.setAutomaticZenRuleState(bedtimeRuleId,
                new Condition(bedtime.getConditionId(), "", STATE_FALSE, SOURCE_SCHEDULE),
                UPDATE_ORIGIN_APP, CUSTOM_PKG_UID);

        // Total of 4 events
        assertEquals(4, mZenModeEventLogger.numLoggedChanges());

        // First event: DND_TURNED_ON; active rules: 1; type is ACTIVE_RULE_TYPE_MANUAL
        assertThat(mZenModeEventLogger.getEventId(0)).isEqualTo(
                ZenModeEventLogger.ZenStateChangedEvent.DND_TURNED_ON.getId());
        assertThat(mZenModeEventLogger.getChangedRuleType(0)).isEqualTo(
                DNDProtoEnums.MANUAL_RULE);
        assertThat(mZenModeEventLogger.getNumRulesActive(0)).isEqualTo(1);
        int[] ruleTypes0 = mZenModeEventLogger.getActiveRuleTypes(0);
        assertThat(ruleTypes0.length).isEqualTo(1);
        assertThat(ruleTypes0[0]).isEqualTo(ACTIVE_RULE_TYPE_MANUAL);

        // Second event: active rules: 2; types are TYPE_MANUAL and TYPE_BEDTIME
        assertThat(mZenModeEventLogger.getChangedRuleType(1)).isEqualTo(
                DNDProtoEnums.AUTOMATIC_RULE);
        assertThat(mZenModeEventLogger.getNumRulesActive(1)).isEqualTo(2);
        int[] ruleTypes1 = mZenModeEventLogger.getActiveRuleTypes(1);
        assertThat(ruleTypes1.length).isEqualTo(2);
        assertThat(ruleTypes1[0]).isEqualTo(TYPE_BEDTIME);
        assertThat(ruleTypes1[1]).isEqualTo(ACTIVE_RULE_TYPE_MANUAL);

        // Third event: active rules: 3
        assertThat(mZenModeEventLogger.getEventId(2)).isEqualTo(
                ZenModeEventLogger.ZenStateChangedEvent.DND_ACTIVE_RULES_CHANGED.getId());
        assertThat(mZenModeEventLogger.getChangedRuleType(2)).isEqualTo(
                DNDProtoEnums.AUTOMATIC_RULE);
        int[] ruleTypes2 = mZenModeEventLogger.getActiveRuleTypes(2);
        assertThat(ruleTypes2.length).isEqualTo(3);
        assertThat(ruleTypes2[0]).isEqualTo(TYPE_BEDTIME);
        assertThat(ruleTypes2[1]).isEqualTo(TYPE_IMMERSIVE);
        assertThat(ruleTypes2[2]).isEqualTo(ACTIVE_RULE_TYPE_MANUAL);

        // Fourth event: active rules 2, types are TYPE_MANUAL and TYPE_IMMERSIVE
        assertThat(mZenModeEventLogger.getEventId(3)).isEqualTo(
                ZenModeEventLogger.ZenStateChangedEvent.DND_ACTIVE_RULES_CHANGED.getId());
        assertThat(mZenModeEventLogger.getChangedRuleType(3)).isEqualTo(
                DNDProtoEnums.AUTOMATIC_RULE);
        int[] ruleTypes3 = mZenModeEventLogger.getActiveRuleTypes(3);
        assertThat(ruleTypes3.length).isEqualTo(2);
        assertThat(ruleTypes3[0]).isEqualTo(TYPE_IMMERSIVE);
        assertThat(ruleTypes3[1]).isEqualTo(ACTIVE_RULE_TYPE_MANUAL);
    }

    @Test
    @DisableFlags(Flags.FLAG_MODES_API)
    public void testUpdateConsolidatedPolicy_preModesApiDefaultRulesOnly_takesGlobalDefault() {