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

Commit 25cc875a authored by Julia Reynolds's avatar Julia Reynolds
Browse files

Store rule icon res name

Test: NotificationManagerZenTest
Test: ZenModeHelperTest
Test: ZenModeDiffTest
Test: test app that creates rules with icons and shows them,
used directly and to confirm icon state after reboot
Test: make system rules add icons, confirm display in (patched) Settings
Fixes: 308672670

Change-Id: Ib55cda476a1a1e97433694cab3d6f9b4a95f86e2
parent a38f760a
Loading
Loading
Loading
Loading
+10 −9
Original line number Diff line number Diff line
@@ -683,7 +683,7 @@ public class ZenModeConfig implements Parcelable {
        if (Flags.modesApi()) {
            rt.zenDeviceEffects = readZenDeviceEffectsXml(parser);
            rt.allowManualInvocation = safeBoolean(parser, RULE_ATT_ALLOW_MANUAL, false);
            rt.iconResId = safeInt(parser, RULE_ATT_ICON, 0);
            rt.iconResName = parser.getAttributeValue(null, RULE_ATT_ICON);
            rt.triggerDescription = parser.getAttributeValue(null, RULE_ATT_TRIGGER_DESC);
            rt.type = safeInt(parser, RULE_ATT_TYPE, AutomaticZenRule.TYPE_UNKNOWN);
        }
@@ -725,7 +725,9 @@ public class ZenModeConfig implements Parcelable {
        out.attributeBoolean(null, RULE_ATT_MODIFIED, rule.modified);
        if (Flags.modesApi()) {
            out.attributeBoolean(null, RULE_ATT_ALLOW_MANUAL, rule.allowManualInvocation);
            out.attributeInt(null, RULE_ATT_ICON, rule.iconResId);
            if (rule.iconResName != null) {
                out.attribute(null, RULE_ATT_ICON, rule.iconResName);
            }
            if (rule.triggerDescription != null) {
                out.attribute(null, RULE_ATT_TRIGGER_DESC, rule.triggerDescription);
            }
@@ -1918,8 +1920,7 @@ public class ZenModeConfig implements Parcelable {
        public String pkg;
        public int type = AutomaticZenRule.TYPE_UNKNOWN;
        public String triggerDescription;
        // TODO (b/308672670): switch to string res name
        public int iconResId;
        public String iconResName;
        public boolean allowManualInvocation;

        public ZenRule() { }
@@ -1950,7 +1951,7 @@ public class ZenModeConfig implements Parcelable {
            pkg = source.readString();
            if (Flags.modesApi()) {
                allowManualInvocation = source.readBoolean();
                iconResId = source.readInt();
                iconResName = source.readString();
                triggerDescription = source.readString();
                type = source.readInt();
            }
@@ -1997,7 +1998,7 @@ public class ZenModeConfig implements Parcelable {
            dest.writeString(pkg);
            if (Flags.modesApi()) {
                dest.writeBoolean(allowManualInvocation);
                dest.writeInt(iconResId);
                dest.writeString(iconResName);
                dest.writeString(triggerDescription);
                dest.writeInt(type);
            }
@@ -2026,7 +2027,7 @@ public class ZenModeConfig implements Parcelable {
            if (Flags.modesApi()) {
                sb.append(",deviceEffects=").append(zenDeviceEffects)
                        .append(",allowManualInvocation=").append(allowManualInvocation)
                        .append(",iconResId=").append(iconResId)
                        .append(",iconResName=").append(iconResName)
                        .append(",triggerDescription=").append(triggerDescription)
                        .append(",type=").append(type);
            }
@@ -2085,7 +2086,7 @@ public class ZenModeConfig implements Parcelable {
                return finalEquals
                        && Objects.equals(other.zenDeviceEffects, zenDeviceEffects)
                        && other.allowManualInvocation == allowManualInvocation
                        && other.iconResId == iconResId
                        && Objects.equals(other.iconResName, iconResName)
                        && Objects.equals(other.triggerDescription, triggerDescription)
                        && other.type == type;
            }
@@ -2098,7 +2099,7 @@ public class ZenModeConfig implements Parcelable {
            if (Flags.modesApi()) {
                return Objects.hash(enabled, snoozing, name, zenMode, conditionId, condition,
                        component, configurationActivity, pkg, id, enabler, zenPolicy,
                        zenDeviceEffects, modified, allowManualInvocation, iconResId,
                        zenDeviceEffects, modified, allowManualInvocation, iconResName,
                        triggerDescription, type);
            }
            return Objects.hash(enabled, snoozing, name, zenMode, conditionId, condition,
+3 −3
Original line number Diff line number Diff line
@@ -464,7 +464,7 @@ public class ZenModeDiff {
        public static final String FIELD_MODIFIED = "modified";
        public static final String FIELD_PKG = "pkg";
        public static final String FIELD_ALLOW_MANUAL = "allowManualInvocation";
        public static final String FIELD_ICON_RES = "iconResId";
        public static final String FIELD_ICON_RES = "iconResName";
        public static final String FIELD_TRIGGER_DESCRIPTION = "triggerDescription";
        public static final String FIELD_TYPE = "type";
        // NOTE: new field strings must match the variable names in ZenModeConfig.ZenRule
@@ -559,8 +559,8 @@ public class ZenModeDiff {
                    addField(FIELD_ALLOW_MANUAL,
                            new FieldDiff<>(from.allowManualInvocation, to.allowManualInvocation));
                }
                if (!Objects.equals(from.iconResId, to.iconResId)) {
                    addField(FIELD_ICON_RES, new FieldDiff<>(from.iconResId, to.iconResId));
                if (!Objects.equals(from.iconResName, to.iconResName)) {
                    addField(FIELD_ICON_RES, new FieldDiff<>(from.iconResName, to.iconResName));
                }
            }
        }
+43 −10
Original line number Diff line number Diff line
@@ -28,6 +28,8 @@ import static android.service.notification.NotificationServiceProto.ROOT_CONFIG;
import static com.android.internal.util.FrameworkStatsLog.DND_MODE_RULE;

import android.annotation.IntDef;
import android.annotation.DrawableRes;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.annotation.UserIdInt;
@@ -79,6 +81,7 @@ import android.service.notification.ZenModeConfig;
import android.service.notification.ZenModeConfig.ZenRule;
import android.service.notification.ZenModeProto;
import android.service.notification.ZenPolicy;
import android.text.TextUtils;
import android.util.AndroidRuntimeException;
import android.util.ArrayMap;
import android.util.Log;
@@ -868,7 +871,8 @@ public class ZenModeHelper {
        return null;
    }

    private static void populateZenRule(String pkg, AutomaticZenRule automaticZenRule, ZenRule rule,
    @VisibleForTesting
    void populateZenRule(String pkg, AutomaticZenRule automaticZenRule, ZenRule rule,
            boolean isNew, @ChangeOrigin int origin) {
            // TODO: b/308671593,b/311406021 - Handle origins more precisely:
            //  - FROM_USER can override anything and updates bitmask of user-modified fields;
@@ -902,14 +906,14 @@ public class ZenModeHelper {

        if (Flags.modesApi()) {
            rule.allowManualInvocation = automaticZenRule.isManualInvocationAllowed();
            rule.iconResId = automaticZenRule.getIconResId();
            rule.iconResName = drawableResIdToResName(rule.pkg, automaticZenRule.getIconResId());
            rule.triggerDescription = automaticZenRule.getTriggerDescription();
            rule.type = automaticZenRule.getType();
        }
    }

    /** "
     * Fix" {@link ZenDeviceEffects} that are being stored as part of a new or updated ZenRule.
    /**
     * Fix {@link ZenDeviceEffects} that are being stored as part of a new or updated ZenRule.
     *
     * <ul>
     *     <li> Apps cannot turn on hidden effects (those tagged as {@code @hide}) since they are
@@ -952,13 +956,13 @@ public class ZenModeHelper {
        }
    }

    private static AutomaticZenRule zenRuleToAutomaticZenRule(ZenRule rule) {
    private AutomaticZenRule zenRuleToAutomaticZenRule(ZenRule rule) {
        AutomaticZenRule azr;
        if (Flags.modesApi()) {
            azr = new AutomaticZenRule.Builder(rule.name, rule.conditionId)
                    .setManualInvocationAllowed(rule.allowManualInvocation)
                    .setCreationTime(rule.creationTime)
                    .setIconResId(rule.iconResId)
                    .setIconResId(drawableResNameToResId(rule.pkg, rule.iconResName))
                    .setType(rule.type)
                    .setZenPolicy(rule.zenPolicy)
                    .setDeviceEffects(rule.zenDeviceEffects)
@@ -1942,6 +1946,35 @@ public class ZenModeHelper {
                .build();
    }

    private int drawableResNameToResId(String packageName, String resourceName) {
        if (TextUtils.isEmpty(resourceName)) {
            return 0;
        }
        try {
            final Resources res = mPm.getResourcesForApplication(packageName);
            return res.getIdentifier(resourceName, null, null);
        } catch (PackageManager.NameNotFoundException e) {
            Slog.w(TAG, "cannot load rule icon for pkg", e);
        }
        return 0;
    }

    private String drawableResIdToResName(String packageName, @DrawableRes int resId) {
        if (resId == 0) {
            return null;
        }
        try {
            final Resources res = mPm.getResourcesForApplication(packageName);
            final String fullName = res.getResourceName(resId);

            return fullName;
        } catch (PackageManager.NameNotFoundException | Resources.NotFoundException e) {
            Log.e(TAG, "Resource name for ID=" + resId + " not found in package " + packageName
                    + ". Resource IDs may change when the application is upgraded, and the system"
                    + " may not be able to find the correct resource.");
            return null;
        }
    }
    private final class Metrics extends Callback {
        private static final String COUNTER_MODE_PREFIX = "dnd_mode_";
        private static final String COUNTER_TYPE_PREFIX = "dnd_type_";
+5 −5
Original line number Diff line number Diff line
@@ -75,7 +75,7 @@ public class ZenModeConfigTest extends UiServiceTestCase {
    private final String TRIGGER_DESC = "Every Night, 10pm to 6am";
    private final int TYPE = TYPE_BEDTIME;
    private final boolean ALLOW_MANUAL = true;
    private final int ICON_RES_ID = 1234;
    private final String ICON_RES_NAME = "icon_res";
    private final int INTERRUPTION_FILTER = Settings.Global.ZEN_MODE_ALARMS;
    private final boolean ENABLED = true;
    private final int CREATION_TIME = 123;
@@ -347,7 +347,7 @@ public class ZenModeConfigTest extends UiServiceTestCase {

        rule.allowManualInvocation = ALLOW_MANUAL;
        rule.type = TYPE;
        rule.iconResId = ICON_RES_ID;
        rule.iconResName = ICON_RES_NAME;
        rule.triggerDescription = TRIGGER_DESC;

        Parcel parcel = Parcel.obtain();
@@ -369,7 +369,7 @@ public class ZenModeConfigTest extends UiServiceTestCase {
        assertEquals(rule.zenMode, parceled.zenMode);

        assertEquals(rule.allowManualInvocation, parceled.allowManualInvocation);
        assertEquals(rule.iconResId, parceled.iconResId);
        assertEquals(rule.iconResName, parceled.iconResName);
        assertEquals(rule.type, parceled.type);
        assertEquals(rule.triggerDescription, parceled.triggerDescription);
        assertEquals(rule.zenPolicy, parceled.zenPolicy);
@@ -448,7 +448,7 @@ public class ZenModeConfigTest extends UiServiceTestCase {

        rule.allowManualInvocation = ALLOW_MANUAL;
        rule.type = TYPE;
        rule.iconResId = ICON_RES_ID;
        rule.iconResName = ICON_RES_NAME;
        rule.triggerDescription = TRIGGER_DESC;

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
@@ -477,7 +477,7 @@ public class ZenModeConfigTest extends UiServiceTestCase {
        assertEquals(rule.allowManualInvocation, fromXml.allowManualInvocation);
        assertEquals(rule.type, fromXml.type);
        assertEquals(rule.triggerDescription, fromXml.triggerDescription);
        assertEquals(rule.iconResId, fromXml.iconResId);
        assertEquals(rule.iconResName, fromXml.iconResName);
    }

    @Test
+1 −1
Original line number Diff line number Diff line
@@ -299,7 +299,7 @@ public class ZenModeDiffTest extends UiServiceTestCase {
        if (android.app.Flags.modesApi()) {
            rule.allowManualInvocation = true;
            rule.type = AutomaticZenRule.TYPE_SCHEDULE_TIME;
            rule.iconResId = 123;
            rule.iconResName = "res";
            rule.triggerDescription = "At night";
            rule.zenDeviceEffects = new ZenDeviceEffects.Builder()
                    .setShouldDimWallpaper(true)
Loading