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

Commit b37f6c1c authored by Matías Hernández's avatar Matías Hernández Committed by Android (Google) Code Review
Browse files

Merge "Preserve user customization when an app deletes and recreates an AutomaticZenRule" into main

parents e9c1bd0c 6480b8b7
Loading
Loading
Loading
Loading
+113 −36
Original line number Original line Diff line number Diff line
@@ -64,6 +64,7 @@ import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.RetentionPolicy;
import java.time.Instant;
import java.util.Arrays;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Calendar;
import java.util.Date;
import java.util.Date;
@@ -233,6 +234,7 @@ public class ZenModeConfig implements Parcelable {


    private static final String MANUAL_TAG = "manual";
    private static final String MANUAL_TAG = "manual";
    private static final String AUTOMATIC_TAG = "automatic";
    private static final String AUTOMATIC_TAG = "automatic";
    private static final String AUTOMATIC_DELETED_TAG = "deleted";


    private static final String RULE_ATT_ID = "ruleId";
    private static final String RULE_ATT_ID = "ruleId";
    private static final String RULE_ATT_ENABLED = "enabled";
    private static final String RULE_ATT_ENABLED = "enabled";
@@ -251,6 +253,7 @@ public class ZenModeConfig implements Parcelable {
    private static final String RULE_ATT_USER_MODIFIED_FIELDS = "userModifiedFields";
    private static final String RULE_ATT_USER_MODIFIED_FIELDS = "userModifiedFields";
    private static final String RULE_ATT_ICON = "rule_icon";
    private static final String RULE_ATT_ICON = "rule_icon";
    private static final String RULE_ATT_TRIGGER_DESC = "triggerDesc";
    private static final String RULE_ATT_TRIGGER_DESC = "triggerDesc";
    private static final String RULE_ATT_DELETION_INSTANT = "deletionInstant";


    private static final String DEVICE_EFFECT_DISPLAY_GRAYSCALE = "zdeDisplayGrayscale";
    private static final String DEVICE_EFFECT_DISPLAY_GRAYSCALE = "zdeDisplayGrayscale";
    private static final String DEVICE_EFFECT_SUPPRESS_AMBIENT_DISPLAY =
    private static final String DEVICE_EFFECT_SUPPRESS_AMBIENT_DISPLAY =
@@ -292,6 +295,10 @@ public class ZenModeConfig implements Parcelable {
    @UnsupportedAppUsage
    @UnsupportedAppUsage
    public ArrayMap<String, ZenRule> automaticRules = new ArrayMap<>();
    public ArrayMap<String, ZenRule> automaticRules = new ArrayMap<>();


    // Note: Map is *pkg|conditionId* (see deletedRuleKey()) -> ZenRule,
    // unlike automaticRules (which is id -> rule).
    public final ArrayMap<String, ZenRule> deletedRules = new ArrayMap<>();

    @UnsupportedAppUsage
    @UnsupportedAppUsage
    public ZenModeConfig() {
    public ZenModeConfig() {
    }
    }
@@ -306,15 +313,9 @@ public class ZenModeConfig implements Parcelable {
        allowMessagesFrom = source.readInt();
        allowMessagesFrom = source.readInt();
        user = source.readInt();
        user = source.readInt();
        manualRule = source.readParcelable(null, ZenRule.class);
        manualRule = source.readParcelable(null, ZenRule.class);
        final int len = source.readInt();
        readRulesFromParcel(automaticRules, source);
        if (len > 0) {
        if (Flags.modesApi()) {
            final String[] ids = new String[len];
            readRulesFromParcel(deletedRules, source);
            final ZenRule[] rules = new ZenRule[len];
            source.readStringArray(ids);
            source.readTypedArray(rules, ZenRule.CREATOR);
            for (int i = 0; i < len; i++) {
                automaticRules.put(ids[i], rules[i]);
            }
        }
        }
        allowAlarms = source.readInt() == 1;
        allowAlarms = source.readInt() == 1;
        allowMedia = source.readInt() == 1;
        allowMedia = source.readInt() == 1;
@@ -328,6 +329,19 @@ public class ZenModeConfig implements Parcelable {
        }
        }
    }
    }


    private static void readRulesFromParcel(ArrayMap<String, ZenRule> ruleMap, Parcel source) {
        final int len = source.readInt();
        if (len > 0) {
            final String[] ids = new String[len];
            final ZenRule[] rules = new ZenRule[len];
            source.readStringArray(ids);
            source.readTypedArray(rules, ZenRule.CREATOR);
            for (int i = 0; i < len; i++) {
                ruleMap.put(ids[i], rules[i]);
            }
        }
    }

    @Override
    @Override
    public void writeToParcel(Parcel dest, int flags) {
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(allowCalls ? 1 : 0);
        dest.writeInt(allowCalls ? 1 : 0);
@@ -339,19 +353,9 @@ public class ZenModeConfig implements Parcelable {
        dest.writeInt(allowMessagesFrom);
        dest.writeInt(allowMessagesFrom);
        dest.writeInt(user);
        dest.writeInt(user);
        dest.writeParcelable(manualRule, 0);
        dest.writeParcelable(manualRule, 0);
        if (!automaticRules.isEmpty()) {
        writeRulesToParcel(automaticRules, dest);
            final int len = automaticRules.size();
        if (Flags.modesApi()) {
            final String[] ids = new String[len];
            writeRulesToParcel(deletedRules, dest);
            final ZenRule[] rules = new ZenRule[len];
            for (int i = 0; i < len; i++) {
                ids[i] = automaticRules.keyAt(i);
                rules[i] = automaticRules.valueAt(i);
            }
            dest.writeInt(len);
            dest.writeStringArray(ids);
            dest.writeTypedArray(rules, 0);
        } else {
            dest.writeInt(0);
        }
        }
        dest.writeInt(allowAlarms ? 1 : 0);
        dest.writeInt(allowAlarms ? 1 : 0);
        dest.writeInt(allowMedia ? 1 : 0);
        dest.writeInt(allowMedia ? 1 : 0);
@@ -365,6 +369,23 @@ public class ZenModeConfig implements Parcelable {
        }
        }
    }
    }


    private static void writeRulesToParcel(ArrayMap<String, ZenRule> ruleMap, Parcel dest) {
        if (!ruleMap.isEmpty()) {
            final int len = ruleMap.size();
            final String[] ids = new String[len];
            final ZenRule[] rules = new ZenRule[len];
            for (int i = 0; i < len; i++) {
                ids[i] = ruleMap.keyAt(i);
                rules[i] = ruleMap.valueAt(i);
            }
            dest.writeInt(len);
            dest.writeStringArray(ids);
            dest.writeTypedArray(rules, 0);
        } else {
            dest.writeInt(0);
        }
    }

    @Override
    @Override
    public String toString() {
    public String toString() {
        StringBuilder sb = new StringBuilder(ZenModeConfig.class.getSimpleName()).append('[')
        StringBuilder sb = new StringBuilder(ZenModeConfig.class.getSimpleName()).append('[')
@@ -389,23 +410,26 @@ public class ZenModeConfig implements Parcelable {
        } else {
        } else {
            sb.append(",areChannelsBypassingDnd=").append(areChannelsBypassingDnd);
            sb.append(",areChannelsBypassingDnd=").append(areChannelsBypassingDnd);
        }
        }
        return sb.append(",\nautomaticRules=").append(rulesToString())
        sb.append(",\nautomaticRules=").append(rulesToString(automaticRules))
                .append(",\nmanualRule=").append(manualRule)
                .append(",\nmanualRule=").append(manualRule);
                .append(']').toString();
        if (Flags.modesApi()) {
            sb.append(",\ndeletedRules=").append(rulesToString(deletedRules));
        }
        return sb.append(']').toString();
    }
    }


    private String rulesToString() {
    private static String rulesToString(ArrayMap<String, ZenRule> ruleList) {
        if (automaticRules.isEmpty()) {
        if (ruleList.isEmpty()) {
            return "{}";
            return "{}";
        }
        }


        StringBuilder buffer = new StringBuilder(automaticRules.size() * 28);
        StringBuilder buffer = new StringBuilder(ruleList.size() * 28);
        buffer.append("{\n");
        buffer.append("{\n");
        for (int i = 0; i < automaticRules.size(); i++) {
        for (int i = 0; i < ruleList.size(); i++) {
            if (i > 0) {
            if (i > 0) {
                buffer.append(",\n");
                buffer.append(",\n");
            }
            }
            Object value = automaticRules.valueAt(i);
            Object value = ruleList.valueAt(i);
            buffer.append(value);
            buffer.append(value);
        }
        }
        buffer.append('}');
        buffer.append('}');
@@ -487,7 +511,9 @@ public class ZenModeConfig implements Parcelable {
                && other.allowConversations == allowConversations
                && other.allowConversations == allowConversations
                && other.allowConversationsFrom == allowConversationsFrom;
                && other.allowConversationsFrom == allowConversationsFrom;
        if (Flags.modesApi()) {
        if (Flags.modesApi()) {
            return eq && other.allowPriorityChannels == allowPriorityChannels;
            return eq
                    && Objects.equals(other.deletedRules, deletedRules)
                    && other.allowPriorityChannels == allowPriorityChannels;
        }
        }
        return eq;
        return eq;
    }
    }
@@ -644,13 +670,21 @@ public class ZenModeConfig implements Parcelable {
                            DEFAULT_SUPPRESSED_VISUAL_EFFECTS);
                            DEFAULT_SUPPRESSED_VISUAL_EFFECTS);
                } else if (MANUAL_TAG.equals(tag)) {
                } else if (MANUAL_TAG.equals(tag)) {
                    rt.manualRule = readRuleXml(parser);
                    rt.manualRule = readRuleXml(parser);
                } else if (AUTOMATIC_TAG.equals(tag)) {
                } else if (AUTOMATIC_TAG.equals(tag)
                        || (Flags.modesApi() && AUTOMATIC_DELETED_TAG.equals(tag))) {
                    final String id = parser.getAttributeValue(null, RULE_ATT_ID);
                    final String id = parser.getAttributeValue(null, RULE_ATT_ID);
                    final ZenRule automaticRule = readRuleXml(parser);
                    final ZenRule automaticRule = readRuleXml(parser);
                    if (id != null && automaticRule != null) {
                    if (id != null && automaticRule != null) {
                        automaticRule.id = id;
                        automaticRule.id = id;
                        if (Flags.modesApi() && AUTOMATIC_DELETED_TAG.equals(tag)) {
                            String deletedRuleKey = deletedRuleKey(automaticRule);
                            if (deletedRuleKey != null) {
                                rt.deletedRules.put(deletedRuleKey, automaticRule);
                            }
                        } else if (AUTOMATIC_TAG.equals(tag)) {
                            rt.automaticRules.put(id, automaticRule);
                            rt.automaticRules.put(id, automaticRule);
                        }
                        }
                    }
                } else if (STATE_TAG.equals(tag)) {
                } else if (STATE_TAG.equals(tag)) {
                    rt.areChannelsBypassingDnd = safeBoolean(parser,
                    rt.areChannelsBypassingDnd = safeBoolean(parser,
                            STATE_ATT_CHANNELS_BYPASSING_DND, DEFAULT_CHANNELS_BYPASSING_DND);
                            STATE_ATT_CHANNELS_BYPASSING_DND, DEFAULT_CHANNELS_BYPASSING_DND);
@@ -660,13 +694,24 @@ public class ZenModeConfig implements Parcelable {
        throw new IllegalStateException("Failed to reach END_DOCUMENT");
        throw new IllegalStateException("Failed to reach END_DOCUMENT");
    }
    }


    /** Generates the map key used for a {@link ZenRule} in {@link #deletedRules}. */
    @Nullable
    public static String deletedRuleKey(ZenRule rule) {
        if (rule.pkg != null && rule.conditionId != null) {
            return rule.pkg + "|" + rule.conditionId.toString();
        } else {
            return null;
        }
    }

    /**
    /**
     * Writes XML of current ZenModeConfig
     * Writes XML of current ZenModeConfig
     * @param out serializer
     * @param out serializer
     * @param version uses XML_VERSION if version is null
     * @param version uses XML_VERSION if version is null
     * @throws IOException
     * @throws IOException
     */
     */
    public void writeXml(TypedXmlSerializer out, Integer version) throws IOException {
    public void writeXml(TypedXmlSerializer out, Integer version, boolean forBackup)
            throws IOException {
        out.startTag(null, ZEN_TAG);
        out.startTag(null, ZEN_TAG);
        out.attribute(null, ZEN_ATT_VERSION, version == null
        out.attribute(null, ZEN_ATT_VERSION, version == null
                ? Integer.toString(XML_VERSION) : Integer.toString(version));
                ? Integer.toString(XML_VERSION) : Integer.toString(version));
@@ -707,6 +752,15 @@ public class ZenModeConfig implements Parcelable {
            writeRuleXml(automaticRule, out);
            writeRuleXml(automaticRule, out);
            out.endTag(null, AUTOMATIC_TAG);
            out.endTag(null, AUTOMATIC_TAG);
        }
        }
        if (Flags.modesApi() && !forBackup) {
            for (int i = 0; i < deletedRules.size(); i++) {
                final ZenRule deletedRule = deletedRules.valueAt(i);
                out.startTag(null, AUTOMATIC_DELETED_TAG);
                out.attribute(null, RULE_ATT_ID, deletedRule.id);
                writeRuleXml(deletedRule, out);
                out.endTag(null, AUTOMATIC_DELETED_TAG);
            }
        }


        out.startTag(null, STATE_TAG);
        out.startTag(null, STATE_TAG);
        out.attributeBoolean(null, STATE_ATT_CHANNELS_BYPASSING_DND, areChannelsBypassingDnd);
        out.attributeBoolean(null, STATE_ATT_CHANNELS_BYPASSING_DND, areChannelsBypassingDnd);
@@ -752,6 +806,11 @@ public class ZenModeConfig implements Parcelable {
            rt.triggerDescription = parser.getAttributeValue(null, RULE_ATT_TRIGGER_DESC);
            rt.triggerDescription = parser.getAttributeValue(null, RULE_ATT_TRIGGER_DESC);
            rt.type = safeInt(parser, RULE_ATT_TYPE, AutomaticZenRule.TYPE_UNKNOWN);
            rt.type = safeInt(parser, RULE_ATT_TYPE, AutomaticZenRule.TYPE_UNKNOWN);
            rt.userModifiedFields = safeInt(parser, RULE_ATT_USER_MODIFIED_FIELDS, 0);
            rt.userModifiedFields = safeInt(parser, RULE_ATT_USER_MODIFIED_FIELDS, 0);
            Long deletionInstant = tryParseLong(
                    parser.getAttributeValue(null, RULE_ATT_DELETION_INSTANT), null);
            if (deletionInstant != null) {
                rt.deletionInstant = Instant.ofEpochMilli(deletionInstant);
            }
        }
        }
        return rt;
        return rt;
    }
    }
@@ -799,6 +858,10 @@ public class ZenModeConfig implements Parcelable {
            }
            }
            out.attributeInt(null, RULE_ATT_TYPE, rule.type);
            out.attributeInt(null, RULE_ATT_TYPE, rule.type);
            out.attributeInt(null, RULE_ATT_USER_MODIFIED_FIELDS, rule.userModifiedFields);
            out.attributeInt(null, RULE_ATT_USER_MODIFIED_FIELDS, rule.userModifiedFields);
            if (rule.deletionInstant != null) {
                out.attributeLong(null, RULE_ATT_DELETION_INSTANT,
                        rule.deletionInstant.toEpochMilli());
            }
        }
        }
    }
    }


@@ -1998,6 +2061,7 @@ public class ZenModeConfig implements Parcelable {
        public String iconResName;
        public String iconResName;
        public boolean allowManualInvocation;
        public boolean allowManualInvocation;
        public int userModifiedFields;
        public int userModifiedFields;
        @Nullable public Instant deletionInstant; // Only set on deleted rules.


        public ZenRule() { }
        public ZenRule() { }


@@ -2031,6 +2095,9 @@ public class ZenModeConfig implements Parcelable {
                triggerDescription = source.readString();
                triggerDescription = source.readString();
                type = source.readInt();
                type = source.readInt();
                userModifiedFields = source.readInt();
                userModifiedFields = source.readInt();
                if (source.readInt() == 1) {
                    deletionInstant = Instant.ofEpochMilli(source.readLong());
                }
            }
            }
        }
        }


@@ -2091,6 +2158,12 @@ public class ZenModeConfig implements Parcelable {
                dest.writeString(triggerDescription);
                dest.writeString(triggerDescription);
                dest.writeInt(type);
                dest.writeInt(type);
                dest.writeInt(userModifiedFields);
                dest.writeInt(userModifiedFields);
                if (deletionInstant != null) {
                    dest.writeInt(1);
                    dest.writeLong(deletionInstant.toEpochMilli());
                } else {
                    dest.writeInt(0);
                }
            }
            }
        }
        }


@@ -2121,6 +2194,9 @@ public class ZenModeConfig implements Parcelable {
                        .append(",triggerDescription=").append(triggerDescription)
                        .append(",triggerDescription=").append(triggerDescription)
                        .append(",type=").append(type)
                        .append(",type=").append(type)
                        .append(",userModifiedFields=").append(userModifiedFields);
                        .append(",userModifiedFields=").append(userModifiedFields);
                if (deletionInstant != null) {
                    sb.append(",deletionInstant=").append(deletionInstant);
                }
            }
            }


            return sb.append(']').toString();
            return sb.append(']').toString();
@@ -2180,7 +2256,8 @@ public class ZenModeConfig implements Parcelable {
                        && Objects.equals(other.iconResName, iconResName)
                        && Objects.equals(other.iconResName, iconResName)
                        && Objects.equals(other.triggerDescription, triggerDescription)
                        && Objects.equals(other.triggerDescription, triggerDescription)
                        && other.type == type
                        && other.type == type
                        && other.userModifiedFields == userModifiedFields;
                        && other.userModifiedFields == userModifiedFields
                        && Objects.equals(other.deletionInstant, deletionInstant);
            }
            }


            return finalEquals;
            return finalEquals;
@@ -2192,7 +2269,7 @@ public class ZenModeConfig implements Parcelable {
                return Objects.hash(enabled, snoozing, name, zenMode, conditionId, condition,
                return Objects.hash(enabled, snoozing, name, zenMode, conditionId, condition,
                        component, configurationActivity, pkg, id, enabler, zenPolicy,
                        component, configurationActivity, pkg, id, enabler, zenPolicy,
                        zenDeviceEffects, modified, allowManualInvocation, iconResName,
                        zenDeviceEffects, modified, allowManualInvocation, iconResName,
                        triggerDescription, type, userModifiedFields);
                        triggerDescription, type, userModifiedFields, deletionInstant);
            }
            }
            return Objects.hash(enabled, snoozing, name, zenMode, conditionId, condition,
            return Objects.hash(enabled, snoozing, name, zenMode, conditionId, condition,
                    component, configurationActivity, pkg, id, enabler, zenPolicy, modified);
                    component, configurationActivity, pkg, id, enabler, zenPolicy, modified);
+5 −5
Original line number Original line Diff line number Diff line
@@ -30,6 +30,11 @@ import java.util.Set;
/**
/**
 * ZenModeDiff is a utility class meant to encapsulate the diff between ZenModeConfigs and their
 * ZenModeDiff is a utility class meant to encapsulate the diff between ZenModeConfigs and their
 * subcomponents (automatic and manual ZenRules).
 * subcomponents (automatic and manual ZenRules).
 *
 * <p>Note that this class is intended to detect <em>meaningful</em> differences, so objects that
 * are not identical (as per their {@code equals()} implementation) can still produce an empty diff
 * if only "metadata" fields are updated.
 *
 * @hide
 * @hide
 */
 */
public class ZenModeDiff {
public class ZenModeDiff {
@@ -467,7 +472,6 @@ public class ZenModeDiff {
        public static final String FIELD_ICON_RES = "iconResName";
        public static final String FIELD_ICON_RES = "iconResName";
        public static final String FIELD_TRIGGER_DESCRIPTION = "triggerDescription";
        public static final String FIELD_TRIGGER_DESCRIPTION = "triggerDescription";
        public static final String FIELD_TYPE = "type";
        public static final String FIELD_TYPE = "type";
        public static final String FIELD_USER_MODIFIED_FIELDS = "userModifiedFields";
        // NOTE: new field strings must match the variable names in ZenModeConfig.ZenRule
        // NOTE: new field strings must match the variable names in ZenModeConfig.ZenRule


        // Special field to track whether this rule became active or inactive
        // Special field to track whether this rule became active or inactive
@@ -563,10 +567,6 @@ public class ZenModeDiff {
                if (!Objects.equals(from.iconResName, to.iconResName)) {
                if (!Objects.equals(from.iconResName, to.iconResName)) {
                    addField(FIELD_ICON_RES, new FieldDiff<>(from.iconResName, to.iconResName));
                    addField(FIELD_ICON_RES, new FieldDiff<>(from.iconResName, to.iconResName));
                }
                }
                if (from.userModifiedFields != to.userModifiedFields) {
                    addField(FIELD_USER_MODIFIED_FIELDS,
                            new FieldDiff<>(from.userModifiedFields, to.userModifiedFields));
                }
            }
            }
        }
        }


+3 −3
Original line number Original line Diff line number Diff line
@@ -215,7 +215,6 @@ import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.IPackageManager;
import android.content.pm.LauncherApps;
import android.content.pm.LauncherApps;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.PackageManagerInternal;
import android.content.pm.PackageManagerInternal;
@@ -373,6 +372,7 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.nio.charset.StandardCharsets;
import java.time.Clock;
import java.time.Duration;
import java.time.Duration;
import java.util.ArrayList;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Arrays;
@@ -2466,8 +2466,8 @@ public class NotificationManagerService extends SystemService {
        mMetricsLogger = new MetricsLogger();
        mMetricsLogger = new MetricsLogger();
        mRankingHandler = rankingHandler;
        mRankingHandler = rankingHandler;
        mConditionProviders = conditionProviders;
        mConditionProviders = conditionProviders;
        mZenModeHelper = new ZenModeHelper(getContext(), mHandler.getLooper(), mConditionProviders,
        mZenModeHelper = new ZenModeHelper(getContext(), mHandler.getLooper(), Clock.systemUTC(),
                flagResolver, new ZenModeEventLogger(mPackageManagerClient));
                mConditionProviders, flagResolver, new ZenModeEventLogger(mPackageManagerClient));
        mZenModeHelper.addCallback(new ZenModeHelper.Callback() {
        mZenModeHelper.addCallback(new ZenModeHelper.Callback() {
            @Override
            @Override
            public void onConfigChanged() {
            public void onConfigChanged() {
+125 −21

File changed.

Preview size limit exceeded, changes collapsed.

+6 −1
Original line number Original line Diff line number Diff line
@@ -60,6 +60,7 @@ import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.IOException;
import java.time.Instant;


@SmallTest
@SmallTest
@RunWith(AndroidJUnit4.class)
@RunWith(AndroidJUnit4.class)
@@ -407,6 +408,7 @@ public class ZenModeConfigTest extends UiServiceTestCase {
        rule.userModifiedFields = 16;
        rule.userModifiedFields = 16;
        rule.iconResName = ICON_RES_NAME;
        rule.iconResName = ICON_RES_NAME;
        rule.triggerDescription = TRIGGER_DESC;
        rule.triggerDescription = TRIGGER_DESC;
        rule.deletionInstant = Instant.ofEpochMilli(1701790147000L);


        Parcel parcel = Parcel.obtain();
        Parcel parcel = Parcel.obtain();
        rule.writeToParcel(parcel, 0);
        rule.writeToParcel(parcel, 0);
@@ -432,9 +434,10 @@ public class ZenModeConfigTest extends UiServiceTestCase {
        assertEquals(rule.userModifiedFields, parceled.userModifiedFields);
        assertEquals(rule.userModifiedFields, parceled.userModifiedFields);
        assertEquals(rule.triggerDescription, parceled.triggerDescription);
        assertEquals(rule.triggerDescription, parceled.triggerDescription);
        assertEquals(rule.zenPolicy, parceled.zenPolicy);
        assertEquals(rule.zenPolicy, parceled.zenPolicy);
        assertEquals(rule.deletionInstant, parceled.deletionInstant);

        assertEquals(rule, parceled);
        assertEquals(rule, parceled);
        assertEquals(rule.hashCode(), parceled.hashCode());
        assertEquals(rule.hashCode(), parceled.hashCode());

    }
    }


    @Test
    @Test
@@ -510,6 +513,7 @@ public class ZenModeConfigTest extends UiServiceTestCase {
        rule.userModifiedFields = 4;
        rule.userModifiedFields = 4;
        rule.iconResName = ICON_RES_NAME;
        rule.iconResName = ICON_RES_NAME;
        rule.triggerDescription = TRIGGER_DESC;
        rule.triggerDescription = TRIGGER_DESC;
        rule.deletionInstant = Instant.ofEpochMilli(1701790147000L);


        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        writeRuleXml(rule, baos);
        writeRuleXml(rule, baos);
@@ -539,6 +543,7 @@ public class ZenModeConfigTest extends UiServiceTestCase {
        assertEquals(rule.userModifiedFields, fromXml.userModifiedFields);
        assertEquals(rule.userModifiedFields, fromXml.userModifiedFields);
        assertEquals(rule.triggerDescription, fromXml.triggerDescription);
        assertEquals(rule.triggerDescription, fromXml.triggerDescription);
        assertEquals(rule.iconResName, fromXml.iconResName);
        assertEquals(rule.iconResName, fromXml.iconResName);
        assertEquals(rule.deletionInstant, fromXml.deletionInstant);
    }
    }


    @Test
    @Test
Loading