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 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 {
  name: "modes_hsum"
  namespace: "systemui"
+64 −13
Original line number 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_CONDITION_OVERRIDE = "conditionOverride";
    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_SUPPRESS_AMBIENT_DISPLAY =
@@ -1208,6 +1209,10 @@ public class ZenModeConfig implements Parcelable {
            if (Flags.modesCleanupImplicit()) {
                rt.lastActivation = safeInstant(parser, RULE_ATT_LAST_ACTIVATION, null);
            }
            if (Flags.modesUiTileReactivatesLast()) {
                rt.lastManualActivation = safeInstant(parser, RULE_ATT_LAST_MANUAL_ACTIVATION,
                        null);
            }
        }

        return rt;
@@ -1269,6 +1274,10 @@ public class ZenModeConfig implements Parcelable {
            if (Flags.modesCleanupImplicit()) {
                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)
        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(Parcel source) {
@@ -2681,6 +2702,11 @@ public class ZenModeConfig implements Parcelable {
                        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(zenPolicyUserModifiedFields);
            dest.writeInt(zenDeviceEffectsUserModifiedFields);
            if (deletionInstant != null) {
                dest.writeInt(1);
                dest.writeLong(deletionInstant.toEpochMilli());
            } else {
                dest.writeInt(0);
            }
            writeInstantToParcel(dest, deletionInstant);
            if (Flags.modesUi()) {
                dest.writeInt(disabledOrigin);
                dest.writeInt(legacySuppressedEffects);
                dest.writeInt(conditionOverride);
                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.writeLong(lastActivation.toEpochMilli());
                dest.writeLong(instant.toEpochMilli());
            } else {
                dest.writeInt(0);
            }
        }
            }
        }

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

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

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

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

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

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

    public TestModeBuilder makeManualDnd() {
        mIsManualDnd = true;
        // 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() {
        if (mIsManualDnd) {
            return ZenMode.manualDndMode(mRule, mConfigZenRule.condition != null
                    && mConfigZenRule.condition.state == Condition.STATE_TRUE);
                    && mConfigZenRule.condition.state == Condition.STATE_TRUE,
                    mConfigZenRule.lastManualActivation);
        } else {
            return new ZenMode(mId, mRule, mConfigZenRule);
        }
+40 −10
Original line number Diff line number Diff line
@@ -53,6 +53,7 @@ import androidx.annotation.Nullable;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;

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

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

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

    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(
                MANUAL_DND_MODE_ID,
                manualRule,
                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)
                .setManualInvocationAllowed(true)
                .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;
        mRule = rule;
        mKind = kind;
        mStatus = status;
        mLastManualActivation = lastManualActivation;
    }

    /** Creates a deep copy of this object. */
    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
@@ -230,6 +238,19 @@ public class ZenMode implements Parcelable {
        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
    public Owner getOwner() {
        return new Owner(mRule.getPackageName(), mRule.getConfigurationActivity(),
@@ -503,17 +524,19 @@ public class ZenMode implements Parcelable {
                && mId.equals(other.mId)
                && mRule.equals(other.mRule)
                && mKind.equals(other.mKind)
                && mStatus.equals(other.mStatus);
                && mStatus.equals(other.mStatus)
                && Objects.equals(mLastManualActivation, other.mLastManualActivation);
    }

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

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

    @Override
@@ -527,6 +550,12 @@ public class ZenMode implements Parcelable {
        dest.writeParcelable(mRule, 0);
        dest.writeString(mKind.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>() {
@@ -537,7 +566,8 @@ public class ZenMode implements Parcelable {
                    checkNotNull(in.readParcelable(AutomaticZenRule.class.getClassLoader(),
                            AutomaticZenRule.class)),
                    Kind.valueOf(in.readString()),
                    Status.valueOf(in.readString()));
                    Status.valueOf(in.readString()),
                    in.readBoolean() ? Instant.ofEpochMilli(in.readLong()) : null);
        }

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

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

    public void updateMode(ZenMode mode) {
Loading