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

Commit 46d09c61 authored by Matías Hernández's avatar Matías Hernández
Browse files

Track last manual activation of zen rules (and expose in ZenMode)

Bug: 405988332
Flag: android.app.modes_ui_tile_reactivates_last
Test: atest ZenModeHelperTest ZenModesBackendTest
Change-Id: I5f16d755084f805cc7bf6db0a9721d040bebc00c
parent fcfe1263
Loading
Loading
Loading
Loading
+10 −0
Original line number Original line Diff line number Diff line
@@ -72,6 +72,16 @@ flag {
  }
  }
}
}


flag {
  name: "modes_ui_tile_reactivates_last"
  namespace: "systemui"
  description: "The secondary target on the Modes tile activates the last-manually-activated mode, instead of DND"
  bug: "405988332"
  metadata {
    purpose: PURPOSE_BUGFIX
  }
}

flag {
flag {
  name: "modes_hsum"
  name: "modes_hsum"
  namespace: "systemui"
  namespace: "systemui"
+64 −13
Original line number Original line Diff line number Diff line
@@ -311,6 +311,7 @@ public class ZenModeConfig implements Parcelable {
    private static final String RULE_ATT_LEGACY_SUPPRESSED_EFFECTS = "legacySuppressedEffects";
    private static final String RULE_ATT_LEGACY_SUPPRESSED_EFFECTS = "legacySuppressedEffects";
    private static final String RULE_ATT_CONDITION_OVERRIDE = "conditionOverride";
    private static final String RULE_ATT_CONDITION_OVERRIDE = "conditionOverride";
    private static final String RULE_ATT_LAST_ACTIVATION = "lastActivation";
    private static final String RULE_ATT_LAST_ACTIVATION = "lastActivation";
    private static final String RULE_ATT_LAST_MANUAL_ACTIVATION = "lastManualActivation";


    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 =
@@ -1208,6 +1209,10 @@ public class ZenModeConfig implements Parcelable {
            if (Flags.modesCleanupImplicit()) {
            if (Flags.modesCleanupImplicit()) {
                rt.lastActivation = safeInstant(parser, RULE_ATT_LAST_ACTIVATION, null);
                rt.lastActivation = safeInstant(parser, RULE_ATT_LAST_ACTIVATION, null);
            }
            }
            if (Flags.modesUiTileReactivatesLast()) {
                rt.lastManualActivation = safeInstant(parser, RULE_ATT_LAST_MANUAL_ACTIVATION,
                        null);
            }
        }
        }


        return rt;
        return rt;
@@ -1269,6 +1274,10 @@ public class ZenModeConfig implements Parcelable {
            if (Flags.modesCleanupImplicit()) {
            if (Flags.modesCleanupImplicit()) {
                writeXmlAttributeInstant(out, RULE_ATT_LAST_ACTIVATION, rule.lastActivation);
                writeXmlAttributeInstant(out, RULE_ATT_LAST_ACTIVATION, rule.lastActivation);
            }
            }
            if (Flags.modesUiTileReactivatesLast()) {
                writeXmlAttributeInstant(out, RULE_ATT_LAST_MANUAL_ACTIVATION,
                        rule.lastManualActivation);
            }
        }
        }
    }
    }


@@ -2639,6 +2648,18 @@ public class ZenModeConfig implements Parcelable {
        @FlaggedApi(Flags.FLAG_MODES_CLEANUP_IMPLICIT)
        @FlaggedApi(Flags.FLAG_MODES_CLEANUP_IMPLICIT)
        public Instant lastActivation;
        public Instant lastActivation;


        /**
         * Last time at which the rule was manually activated (whether as a user action in
         * Settings or SystemUI, or from the owner package with
         * {@link Condition#SOURCE_USER_ACTION}). If {@code null}, the rule has never been manually
         * activated since its creation.
         *
         * <p>Note that this was previously untracked, so it will also be {@code null} for rules
         * created before we started tracking and never activated since.
         */
        @Nullable
        public Instant lastManualActivation;

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


        public ZenRule(Parcel source) {
        public ZenRule(Parcel source) {
@@ -2681,6 +2702,11 @@ public class ZenModeConfig implements Parcelable {
                        lastActivation = Instant.ofEpochMilli(source.readLong());
                        lastActivation = Instant.ofEpochMilli(source.readLong());
                    }
                    }
                }
                }
                if (Flags.modesUiTileReactivatesLast()) {
                    if (source.readInt() == 1) {
                        lastManualActivation = Instant.ofEpochMilli(source.readLong());
                    }
                }
            }
            }
        }
        }


@@ -2744,26 +2770,28 @@ public class ZenModeConfig implements Parcelable {
            dest.writeInt(userModifiedFields);
            dest.writeInt(userModifiedFields);
            dest.writeInt(zenPolicyUserModifiedFields);
            dest.writeInt(zenPolicyUserModifiedFields);
            dest.writeInt(zenDeviceEffectsUserModifiedFields);
            dest.writeInt(zenDeviceEffectsUserModifiedFields);
            if (deletionInstant != null) {
            writeInstantToParcel(dest, deletionInstant);
                dest.writeInt(1);
                dest.writeLong(deletionInstant.toEpochMilli());
            } else {
                dest.writeInt(0);
            }
            if (Flags.modesUi()) {
            if (Flags.modesUi()) {
                dest.writeInt(disabledOrigin);
                dest.writeInt(disabledOrigin);
                dest.writeInt(legacySuppressedEffects);
                dest.writeInt(legacySuppressedEffects);
                dest.writeInt(conditionOverride);
                dest.writeInt(conditionOverride);
                if (Flags.modesCleanupImplicit()) {
                if (Flags.modesCleanupImplicit()) {
                    if (lastActivation != null) {
                    writeInstantToParcel(dest, lastActivation);
                }
                if (Flags.modesUiTileReactivatesLast()) {
                    writeInstantToParcel(dest, lastManualActivation);
                }
            }
        }

        private static void writeInstantToParcel(Parcel dest, @Nullable Instant instant) {
            if (instant != null) {
                dest.writeInt(1);
                dest.writeInt(1);
                        dest.writeLong(lastActivation.toEpochMilli());
                dest.writeLong(instant.toEpochMilli());
            } else {
            } else {
                dest.writeInt(0);
                dest.writeInt(0);
            }
            }
        }
        }
            }
        }


        @Override
        @Override
        public String toString() {
        public String toString() {
@@ -2817,6 +2845,9 @@ public class ZenModeConfig implements Parcelable {
                if (Flags.modesCleanupImplicit()) {
                if (Flags.modesCleanupImplicit()) {
                    sb.append(",lastActivation=").append(lastActivation);
                    sb.append(",lastActivation=").append(lastActivation);
                }
                }
                if (Flags.modesUiTileReactivatesLast()) {
                    sb.append(",lastManualActivation=").append(lastManualActivation);
                }
            }
            }


            return sb.append(']').toString();
            return sb.append(']').toString();
@@ -2899,6 +2930,10 @@ public class ZenModeConfig implements Parcelable {
                    finalEquals = finalEquals
                    finalEquals = finalEquals
                            && Objects.equals(other.lastActivation, lastActivation);
                            && Objects.equals(other.lastActivation, lastActivation);
                }
                }
                if (Flags.modesUiTileReactivatesLast()) {
                    finalEquals = finalEquals
                            && Objects.equals(other.lastManualActivation, lastManualActivation);
                }
            }
            }


            return finalEquals;
            return finalEquals;
@@ -2907,7 +2942,15 @@ public class ZenModeConfig implements Parcelable {
        @Override
        @Override
        public int hashCode() {
        public int hashCode() {
            if (Flags.modesUi()) {
            if (Flags.modesUi()) {
                if (Flags.modesCleanupImplicit()) {
                if (Flags.modesCleanupImplicit() && Flags.modesUiTileReactivatesLast()) {
                    return Objects.hash(enabled, snoozing, name, zenMode, conditionId, condition,
                            component, configurationActivity, pkg, id, enabler, zenPolicy,
                            zenDeviceEffects, allowManualInvocation, iconResName,
                            triggerDescription, type, userModifiedFields,
                            zenPolicyUserModifiedFields, zenDeviceEffectsUserModifiedFields,
                            deletionInstant, disabledOrigin, legacySuppressedEffects,
                            conditionOverride, lastActivation, lastManualActivation);
                } else if (Flags.modesCleanupImplicit() && !Flags.modesUiTileReactivatesLast()) {
                    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, allowManualInvocation, iconResName,
                            zenDeviceEffects, allowManualInvocation, iconResName,
@@ -2915,6 +2958,14 @@ public class ZenModeConfig implements Parcelable {
                            zenPolicyUserModifiedFields, zenDeviceEffectsUserModifiedFields,
                            zenPolicyUserModifiedFields, zenDeviceEffectsUserModifiedFields,
                            deletionInstant, disabledOrigin, legacySuppressedEffects,
                            deletionInstant, disabledOrigin, legacySuppressedEffects,
                            conditionOverride, lastActivation);
                            conditionOverride, lastActivation);
                } else if (!Flags.modesCleanupImplicit() && Flags.modesUiTileReactivatesLast()) {
                    return Objects.hash(enabled, snoozing, name, zenMode, conditionId, condition,
                            component, configurationActivity, pkg, id, enabler, zenPolicy,
                            zenDeviceEffects, allowManualInvocation, iconResName,
                            triggerDescription, type, userModifiedFields,
                            zenPolicyUserModifiedFields, zenDeviceEffectsUserModifiedFields,
                            deletionInstant, disabledOrigin, legacySuppressedEffects,
                            conditionOverride, lastManualActivation);
                } else {
                } else {
                    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,
+8 −1
Original line number Original line Diff line number Diff line
@@ -33,6 +33,7 @@ import android.service.notification.ZenPolicy;
import androidx.annotation.DrawableRes;
import androidx.annotation.DrawableRes;
import androidx.annotation.Nullable;
import androidx.annotation.Nullable;


import java.time.Instant;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicInteger;


public class TestModeBuilder {
public class TestModeBuilder {
@@ -204,6 +205,11 @@ public class TestModeBuilder {
        return this;
        return this;
    }
    }


    public TestModeBuilder setLastManualActivation(@Nullable Instant lastManualActivation) {
        mConfigZenRule.lastManualActivation = lastManualActivation;
        return this;
    }

    public TestModeBuilder makeManualDnd() {
    public TestModeBuilder makeManualDnd() {
        mIsManualDnd = true;
        mIsManualDnd = true;
        // Set the "fixed" properties of a DND mode. Other things, such as policy/filter may be set
        // Set the "fixed" properties of a DND mode. Other things, such as policy/filter may be set
@@ -220,7 +226,8 @@ public class TestModeBuilder {
    public ZenMode build() {
    public ZenMode build() {
        if (mIsManualDnd) {
        if (mIsManualDnd) {
            return ZenMode.manualDndMode(mRule, mConfigZenRule.condition != null
            return ZenMode.manualDndMode(mRule, mConfigZenRule.condition != null
                    && mConfigZenRule.condition.state == Condition.STATE_TRUE);
                    && mConfigZenRule.condition.state == Condition.STATE_TRUE,
                    mConfigZenRule.lastManualActivation);
        } else {
        } else {
            return new ZenMode(mId, mRule, mConfigZenRule);
            return new ZenMode(mId, mRule, mConfigZenRule);
        }
        }
+40 −10
Original line number Original line Diff line number Diff line
@@ -53,6 +53,7 @@ import androidx.annotation.Nullable;
import com.google.common.base.Strings;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableList;


import java.time.Instant;
import java.util.Comparator;
import java.util.Comparator;
import java.util.Objects;
import java.util.Objects;


@@ -130,6 +131,7 @@ public class ZenMode implements Parcelable {
    private final AutomaticZenRule mRule;
    private final AutomaticZenRule mRule;
    private final Kind mKind;
    private final Kind mKind;
    private final Status mStatus;
    private final Status mStatus;
    private final @Nullable Instant mLastManualActivation;


    /**
    /**
     * Initializes a {@link ZenMode}, mainly based on the information from the
     * Initializes a {@link ZenMode}, mainly based on the information from the
@@ -143,7 +145,8 @@ public class ZenMode implements Parcelable {
            @NonNull ZenModeConfig.ZenRule zenRuleExtraData) {
            @NonNull ZenModeConfig.ZenRule zenRuleExtraData) {
        this(id, rule,
        this(id, rule,
                ZenModeConfig.isImplicitRuleId(id) ? Kind.IMPLICIT : Kind.NORMAL,
                ZenModeConfig.isImplicitRuleId(id) ? Kind.IMPLICIT : Kind.NORMAL,
                computeStatus(zenRuleExtraData));
                computeStatus(zenRuleExtraData),
                zenRuleExtraData.lastManualActivation);
    }
    }


    private static Status computeStatus(@NonNull ZenModeConfig.ZenRule zenRuleExtraData) {
    private static Status computeStatus(@NonNull ZenModeConfig.ZenRule zenRuleExtraData) {
@@ -162,12 +165,14 @@ public class ZenMode implements Parcelable {
        }
        }
    }
    }


    static ZenMode manualDndMode(AutomaticZenRule manualRule, boolean isActive) {
    static ZenMode manualDndMode(AutomaticZenRule manualRule, boolean isActive,
            @Nullable Instant lastManualActivation) {
        return new ZenMode(
        return new ZenMode(
                MANUAL_DND_MODE_ID,
                MANUAL_DND_MODE_ID,
                manualRule,
                manualRule,
                Kind.MANUAL_DND,
                Kind.MANUAL_DND,
                isActive ? Status.ENABLED_AND_ACTIVE : Status.ENABLED);
                isActive ? Status.ENABLED_AND_ACTIVE : Status.ENABLED,
                lastManualActivation);
    }
    }


    /**
    /**
@@ -186,19 +191,22 @@ public class ZenMode implements Parcelable {
                .setIconResId(iconResId)
                .setIconResId(iconResId)
                .setManualInvocationAllowed(true)
                .setManualInvocationAllowed(true)
                .build();
                .build();
        return new ZenMode(TEMP_NEW_MODE_ID, rule, Kind.NORMAL, Status.ENABLED);
        return new ZenMode(TEMP_NEW_MODE_ID, rule, Kind.NORMAL, Status.ENABLED, null);
    }
    }


    private ZenMode(String id, @NonNull AutomaticZenRule rule, Kind kind, Status status) {
    private ZenMode(String id, @NonNull AutomaticZenRule rule, Kind kind, Status status,
            @Nullable Instant lastManualActivation) {
        mId = id;
        mId = id;
        mRule = rule;
        mRule = rule;
        mKind = kind;
        mKind = kind;
        mStatus = status;
        mStatus = status;
        mLastManualActivation = lastManualActivation;
    }
    }


    /** Creates a deep copy of this object. */
    /** Creates a deep copy of this object. */
    public ZenMode copy() {
    public ZenMode copy() {
        return new ZenMode(mId, new AutomaticZenRule.Builder(mRule).build(), mKind, mStatus);
        return new ZenMode(mId, new AutomaticZenRule.Builder(mRule).build(), mKind, mStatus,
                mLastManualActivation);
    }
    }


    @NonNull
    @NonNull
@@ -230,6 +238,19 @@ public class ZenMode implements Parcelable {
        return mStatus;
        return mStatus;
    }
    }


    /**
     * Last time at which the mode was manually activated (whether as a user action in
     * Settings or SystemUI, or from the owner package with {@code Condition.SOURCE_USER_ACTION}).
     * If {@code null}, the rule has never been manually activated since its creation.
     *
     * <p>Note that this was previously untracked, so it will also be {@code null} for rules
     * created before we started tracking and never activated since.
     */
    @Nullable
    public Instant getLastManualActivation() {
        return mLastManualActivation;
    }

    @NonNull
    @NonNull
    public Owner getOwner() {
    public Owner getOwner() {
        return new Owner(mRule.getPackageName(), mRule.getConfigurationActivity(),
        return new Owner(mRule.getPackageName(), mRule.getConfigurationActivity(),
@@ -503,17 +524,19 @@ public class ZenMode implements Parcelable {
                && mId.equals(other.mId)
                && mId.equals(other.mId)
                && mRule.equals(other.mRule)
                && mRule.equals(other.mRule)
                && mKind.equals(other.mKind)
                && mKind.equals(other.mKind)
                && mStatus.equals(other.mStatus);
                && mStatus.equals(other.mStatus)
                && Objects.equals(mLastManualActivation, other.mLastManualActivation);
    }
    }


    @Override
    @Override
    public int hashCode() {
    public int hashCode() {
        return Objects.hash(mId, mRule, mKind, mStatus);
        return Objects.hash(mId, mRule, mKind, mStatus, mLastManualActivation);
    }
    }


    @Override
    @Override
    public String toString() {
    public String toString() {
        return mId + " (" + mKind + ", " + mStatus + ") -> " + mRule;
        return mId + " (" + mKind + ", " + mStatus + ") -> " + mRule
                + " (lastManualActivation=" + mLastManualActivation + ")";
    }
    }


    @Override
    @Override
@@ -527,6 +550,12 @@ public class ZenMode implements Parcelable {
        dest.writeParcelable(mRule, 0);
        dest.writeParcelable(mRule, 0);
        dest.writeString(mKind.name());
        dest.writeString(mKind.name());
        dest.writeString(mStatus.name());
        dest.writeString(mStatus.name());
        if (mLastManualActivation != null) {
            dest.writeBoolean(true);
            dest.writeLong(mLastManualActivation.toEpochMilli());
        } else {
            dest.writeBoolean(false);
        }
    }
    }


    public static final Creator<ZenMode> CREATOR = new Creator<ZenMode>() {
    public static final Creator<ZenMode> CREATOR = new Creator<ZenMode>() {
@@ -537,7 +566,8 @@ public class ZenMode implements Parcelable {
                    checkNotNull(in.readParcelable(AutomaticZenRule.class.getClassLoader(),
                    checkNotNull(in.readParcelable(AutomaticZenRule.class.getClassLoader(),
                            AutomaticZenRule.class)),
                            AutomaticZenRule.class)),
                    Kind.valueOf(in.readString()),
                    Kind.valueOf(in.readString()),
                    Status.valueOf(in.readString()));
                    Status.valueOf(in.readString()),
                    in.readBoolean() ? Instant.ofEpochMilli(in.readLong()) : null);
        }
        }


        @Override
        @Override
+2 −1
Original line number Original line Diff line number Diff line
@@ -135,7 +135,8 @@ public class ZenModesBackend {
                .setInterruptionFilter(dndInterruptionFilter)
                .setInterruptionFilter(dndInterruptionFilter)
                .build();
                .build();


        return ZenMode.manualDndMode(manualDndRule, config.isManualActive());
        return ZenMode.manualDndMode(manualDndRule, config.isManualActive(),
                manualRule.lastManualActivation);
    }
    }


    public void updateMode(ZenMode mode) {
    public void updateMode(ZenMode mode) {
Loading