diff options
| author | 2024-07-01 15:10:10 +0200 | |
|---|---|---|
| committer | 2024-07-01 20:16:46 +0200 | |
| commit | ec7a3088869cd56dbd64b0aeddb07998960e682d (patch) | |
| tree | 1c6ae067d4d3984328fa68663cd9da45255ff0c1 | |
| parent | 799bf765c6c60e96c3fa11075e22fa81c482257f (diff) | |
Support "in-memory" ZenMode
For the "add a mode" flow we need to create and edit a ZenMode instance without writing it to the backend until the user confirms. Therefore, we now support:
* parceling a ZenMode (so it can be restored in onSaveInstanceState/onCreate).
* creating a custom_manual ZenMode instance without interacting with NMS/ZenModeBackend.
Bug: 326442408
Test: atest com.android.settingslib.notification.modes.ZenModeTest
Flag: android.app.modes_ui
Change-Id: Ie502175a91c5148ef156a7236feb6120d42d220d
3 files changed, 84 insertions, 10 deletions
diff --git a/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenMode.java b/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenMode.java index 33d39f000663..2cc911234404 100644 --- a/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenMode.java +++ b/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenMode.java @@ -23,6 +23,7 @@ import static android.service.notification.SystemZenRules.getTriggerDescriptionF import static android.service.notification.ZenModeConfig.tryParseEventConditionId; import static android.service.notification.ZenModeConfig.tryParseScheduleConditionId; +import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; import static java.util.Objects.requireNonNull; @@ -33,12 +34,15 @@ import android.app.NotificationManager; import android.content.Context; import android.graphics.drawable.Drawable; import android.net.Uri; +import android.os.Parcel; +import android.os.Parcelable; import android.service.notification.SystemZenRules; import android.service.notification.ZenDeviceEffects; import android.service.notification.ZenModeConfig; import android.service.notification.ZenPolicy; import android.util.Log; +import androidx.annotation.DrawableRes; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -56,11 +60,12 @@ import java.util.Objects; * <p>It also adapts other rule features that we don't want to expose in the UI, such as * interruption filters other than {@code PRIORITY}, rules without specific icons, etc. */ -public class ZenMode { +public class ZenMode implements Parcelable { private static final String TAG = "ZenMode"; static final String MANUAL_DND_MODE_ID = "manual_dnd"; + static final String TEMP_NEW_MODE_ID = "temp_new_mode"; // Must match com.android.server.notification.ZenModeHelper#applyCustomPolicy. private static final ZenPolicy POLICY_INTERRUPTION_FILTER_ALARMS = @@ -125,6 +130,25 @@ public class ZenMode { isActive ? Status.ENABLED_AND_ACTIVE : Status.ENABLED, true); } + /** + * Returns a new {@link ZenMode} instance that can represent a custom_manual mode that is in the + * process of being created (and not yet saved). + * + * @param name mode name + * @param iconResId resource id of the chosen icon, {code 0} if none. + */ + public static ZenMode newCustomManual(String name, @DrawableRes int iconResId) { + AutomaticZenRule rule = new AutomaticZenRule.Builder(name, + ZenModeConfig.toCustomManualConditionId()) + .setPackage(ZenModeConfig.getCustomManualConditionProvider().getPackageName()) + .setType(AutomaticZenRule.TYPE_OTHER) + .setOwner(ZenModeConfig.getCustomManualConditionProvider()) + .setIconResId(iconResId) + .setManualInvocationAllowed(true) + .build(); + return new ZenMode(TEMP_NEW_MODE_ID, rule, Status.ENABLED, false); + } + private ZenMode(String id, @NonNull AutomaticZenRule rule, Status status, boolean isManualDnd) { mId = id; mRule = rule; @@ -304,4 +328,34 @@ public class ZenMode { public String toString() { return mId + " (" + mStatus + ") -> " + mRule; } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeString(mId); + dest.writeParcelable(mRule, 0); + dest.writeString(mStatus.name()); + dest.writeBoolean(mIsManualDnd); + } + + public static final Creator<ZenMode> CREATOR = new Creator<ZenMode>() { + @Override + public ZenMode createFromParcel(Parcel in) { + return new ZenMode( + in.readString(), + checkNotNull(in.readParcelable(AutomaticZenRule.class.getClassLoader(), + AutomaticZenRule.class)), + Status.valueOf(in.readString()), + in.readBoolean()); + } + + @Override + public ZenMode[] newArray(int size) { + return new ZenMode[size]; + } + }; } diff --git a/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenModesBackend.java b/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenModesBackend.java index 62a5763cbd2c..d36e2fe8cfc3 100644 --- a/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenModesBackend.java +++ b/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenModesBackend.java @@ -192,15 +192,7 @@ public class ZenModesBackend { */ @Nullable public ZenMode addCustomManualMode(String name, @DrawableRes int iconResId) { - AutomaticZenRule rule = new AutomaticZenRule.Builder(name, - ZenModeConfig.toCustomManualConditionId()) - .setPackage(ZenModeConfig.getCustomManualConditionProvider().getPackageName()) - .setType(AutomaticZenRule.TYPE_OTHER) - .setOwner(ZenModeConfig.getCustomManualConditionProvider()) - .setIconResId(iconResId) - .setManualInvocationAllowed(true) - .build(); - + AutomaticZenRule rule = ZenMode.newCustomManual(name, iconResId).getRule(); String ruleId = mNotificationManager.addAutomaticZenRule(rule); return getMode(ruleId); } diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/modes/ZenModeTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/modes/ZenModeTest.java index 32cdb98ddb4c..9e543122e707 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/modes/ZenModeTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/modes/ZenModeTest.java @@ -21,13 +21,17 @@ import static android.app.NotificationManager.INTERRUPTION_FILTER_NONE; import static android.app.NotificationManager.INTERRUPTION_FILTER_PRIORITY; import static com.google.common.truth.Truth.assertThat; +import static com.google.common.truth.Truth.assertWithMessage; import android.app.AutomaticZenRule; import android.net.Uri; +import android.os.Parcel; import android.service.notification.Condition; import android.service.notification.ZenModeConfig; import android.service.notification.ZenPolicy; +import com.android.internal.R; + import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.RobolectricTestRunner; @@ -161,6 +165,30 @@ public class ZenModeTest { assertThat(zenMode.getRule().getZenPolicy()).isEqualTo(ZEN_POLICY); } + @Test + public void writeToParcel_equals() { + assertUnparceledIsEqualToOriginal("example", + new ZenMode("id", ZEN_RULE, zenConfigRuleFor(ZEN_RULE, false))); + + assertUnparceledIsEqualToOriginal("dnd", ZenMode.manualDndMode(ZEN_RULE, true)); + + assertUnparceledIsEqualToOriginal("custom_manual", + ZenMode.newCustomManual("New mode", R.drawable.ic_zen_mode_type_immersive)); + } + + private static void assertUnparceledIsEqualToOriginal(String type, ZenMode original) { + Parcel parcel = Parcel.obtain(); + try { + original.writeToParcel(parcel, 0); + parcel.setDataPosition(0); + ZenMode unparceled = ZenMode.CREATOR.createFromParcel(parcel); + + assertWithMessage("Comparing " + type).that(unparceled).isEqualTo(original); + } finally { + parcel.recycle(); + } + } + private static ZenModeConfig.ZenRule zenConfigRuleFor(AutomaticZenRule azr, boolean isActive) { ZenModeConfig.ZenRule zenRule = new ZenModeConfig.ZenRule(); zenRule.pkg = azr.getPackageName(); |