diff options
| author | 2024-10-02 20:25:45 +0000 | |
|---|---|---|
| committer | 2024-10-02 20:25:45 +0000 | |
| commit | 7383d91fb09a23c1de0ae26d8ed295c11542e9dd (patch) | |
| tree | 916b8be05e7febb6a3618a1a27edcff86bb5222a | |
| parent | 91e590de1da1f1e6f545c958fe43b6e26ded6a4f (diff) | |
| parent | a6aacbdb97dfa7c1d88ab75785355a39dbbe9893 (diff) | |
Merge "Add DeviceEffectsDiff and PolicyDiff to RuleDiff" into main
| -rw-r--r-- | core/java/android/service/notification/ZenModeDiff.java | 45 | ||||
| -rw-r--r-- | services/tests/uiservicestests/src/com/android/server/notification/ZenModeDiffTest.java | 230 |
2 files changed, 252 insertions, 23 deletions
diff --git a/core/java/android/service/notification/ZenModeDiff.java b/core/java/android/service/notification/ZenModeDiff.java index a9c57909e1c1..c9f464716e72 100644 --- a/core/java/android/service/notification/ZenModeDiff.java +++ b/core/java/android/service/notification/ZenModeDiff.java @@ -25,6 +25,7 @@ import android.util.ArraySet; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.LinkedHashMap; import java.util.Objects; import java.util.Set; @@ -63,6 +64,7 @@ public class ZenModeDiff { public static class FieldDiff<T> { private final T mFrom; private final T mTo; + private final BaseDiff mDetailedDiff; /** * Constructor to create a FieldDiff object with the given values. @@ -72,6 +74,19 @@ public class ZenModeDiff { public FieldDiff(@Nullable T from, @Nullable T to) { mFrom = from; mTo = to; + mDetailedDiff = null; + } + + /** + * Constructor to create a FieldDiff object with the given values, and that has a + * detailed BaseDiff. + * @param from from (old) value + * @param to to (new) value + */ + public FieldDiff(@Nullable T from, @Nullable T to, @Nullable BaseDiff detailedDiff) { + mFrom = from; + mTo = to; + mDetailedDiff = detailedDiff; } /** @@ -93,6 +108,9 @@ public class ZenModeDiff { */ @Override public String toString() { + if (mDetailedDiff != null) { + return mDetailedDiff.toString(); + } return mFrom + "->" + mTo; } @@ -100,6 +118,9 @@ public class ZenModeDiff { * Returns whether this represents an actual diff. */ public boolean hasDiff() { + if (mDetailedDiff != null) { + return mDetailedDiff.hasDiff(); + } // note that Objects.equals handles null values gracefully. return !Objects.equals(mFrom, mTo); } @@ -115,7 +136,8 @@ public class ZenModeDiff { @ExistenceChange private int mExists = NONE; // Map from field name to diffs for any standalone fields in the object. - private ArrayMap<String, FieldDiff> mFields = new ArrayMap<>(); + // LinkedHashMap is specifically chosen here to show insertion order when keys are fetched. + private LinkedHashMap<String, FieldDiff> mFields = new LinkedHashMap<>(); // Functions for actually diffing objects and string representations have to be implemented // by subclasses. @@ -550,8 +572,16 @@ public class ZenModeDiff { if (!Objects.equals(from.enabler, to.enabler)) { addField(FIELD_ENABLER, new FieldDiff<>(from.enabler, to.enabler)); } - if (!Objects.equals(from.zenPolicy, to.zenPolicy)) { - addField(FIELD_ZEN_POLICY, new FieldDiff<>(from.zenPolicy, to.zenPolicy)); + if (android.app.Flags.modesApi()) { + PolicyDiff policyDiff = new PolicyDiff(from.zenPolicy, to.zenPolicy); + if (policyDiff.hasDiff()) { + addField(FIELD_ZEN_POLICY, new FieldDiff<>(from.zenPolicy, to.zenPolicy, + policyDiff)); + } + } else { + if (!Objects.equals(from.zenPolicy, to.zenPolicy)) { + addField(FIELD_ZEN_POLICY, new FieldDiff<>(from.zenPolicy, to.zenPolicy)); + } } if (from.modified != to.modified) { addField(FIELD_MODIFIED, new FieldDiff<>(from.modified, to.modified)); @@ -560,9 +590,12 @@ public class ZenModeDiff { addField(FIELD_PKG, new FieldDiff<>(from.pkg, to.pkg)); } if (android.app.Flags.modesApi()) { - if (!Objects.equals(from.zenDeviceEffects, to.zenDeviceEffects)) { + DeviceEffectsDiff deviceEffectsDiff = new DeviceEffectsDiff(from.zenDeviceEffects, + to.zenDeviceEffects); + if (deviceEffectsDiff.hasDiff()) { addField(FIELD_ZEN_DEVICE_EFFECTS, - new FieldDiff<>(from.zenDeviceEffects, to.zenDeviceEffects)); + new FieldDiff<>(from.zenDeviceEffects, to.zenDeviceEffects, + deviceEffectsDiff)); } if (!Objects.equals(from.triggerDescription, to.triggerDescription)) { addField(FIELD_TRIGGER_DESCRIPTION, @@ -630,7 +663,7 @@ public class ZenModeDiff { sb.append(key); sb.append(":"); - sb.append(diff); + sb.append(diff.toString()); } if (becameActive()) { diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeDiffTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeDiffTest.java index cf58d9b49832..c6cc941ba1cd 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeDiffTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeDiffTest.java @@ -70,6 +70,7 @@ import java.util.Set; import platform.test.runner.parameterized.ParameterizedAndroidJunit4; import platform.test.runner.parameterized.Parameters; + @SmallTest @RunWith(ParameterizedAndroidJunit4.class) @TestableLooper.RunWithLooper @@ -147,6 +148,147 @@ public class ZenModeDiffTest extends UiServiceTestCase { } @Test + @EnableFlags({FLAG_MODES_API, FLAG_MODES_UI}) + public void testRuleDiff_toStringNoChangeAddRemove() throws Exception { + // Start with two identical rules + ZenModeConfig.ZenRule r1 = makeRule(); + ZenModeConfig.ZenRule r2 = makeRule(); + + ZenModeDiff.RuleDiff d = new ZenModeDiff.RuleDiff(r1, r2); + assertThat(d.toString()).isEqualTo("ZenRuleDiff{no changes}"); + + d = new ZenModeDiff.RuleDiff(r1, null); + assertThat(d.toString()).isEqualTo("ZenRuleDiff{removed}"); + + d = new ZenModeDiff.RuleDiff(null, r2); + assertThat(d.toString()).isEqualTo("ZenRuleDiff{added}"); + } + + @Test + @EnableFlags({FLAG_MODES_API, FLAG_MODES_UI}) + public void testRuleDiff_toString() throws Exception { + // Start with two identical rules + ZenModeConfig.ZenRule r1 = makeRule(); + ZenModeConfig.ZenRule r2 = makeRule(); + + ArrayMap<String, Object> expectedFrom = new ArrayMap<>(); + ArrayMap<String, Object> expectedTo = new ArrayMap<>(); + List<Field> fieldsForDiff = getFieldsForDiffCheck( + ZenModeConfig.ZenRule.class, getZenRuleExemptFields(), false); + generateFieldDiffs(r1, r2, fieldsForDiff, expectedFrom, expectedTo); + + ZenModeDiff.RuleDiff d = new ZenModeDiff.RuleDiff(r1, r2); + assertThat(d.toString()).isEqualTo("ZenRuleDiff{" + + "enabled:true->false, " + + "conditionOverride:2->1, " + + "name:string1->string2, " + + "zenMode:2->1, " + + "conditionId:null->, " + + "condition:null->Condition[" + + "state=STATE_TRUE," + + "id=hello:," + + "summary=," + + "line1=," + + "line2=," + + "icon=-1," + + "source=SOURCE_UNKNOWN," + + "flags=2], " + + "component:null->ComponentInfo{b/b}, " + + "configurationActivity:null->ComponentInfo{a/a}, " + + "id:string1->string2, " + + "creationTime:200->100, " + + "enabler:string1->string2, " + + "zenPolicy:ZenPolicyDiff{" + + "mPriorityCategories_Reminders:1->2, " + + "mPriorityCategories_Events:1->2, " + + "mPriorityCategories_Messages:1->2, " + + "mPriorityCategories_Calls:1->2, " + + "mPriorityCategories_RepeatCallers:1->2, " + + "mPriorityCategories_Alarms:1->2, " + + "mPriorityCategories_Media:1->2, " + + "mPriorityCategories_System:1->2, " + + "mPriorityCategories_Conversations:1->2, " + + "mVisualEffects_FullScreenIntent:1->2, " + + "mVisualEffects_Lights:1->2, " + + "mVisualEffects_Peek:1->2, " + + "mVisualEffects_StatusBar:1->2, " + + "mVisualEffects_Badge:1->2, " + + "mVisualEffects_Ambient:1->2, " + + "mVisualEffects_NotificationList:1->2, " + + "mPriorityMessages:2->1, " + + "mPriorityCalls:2->1, " + + "mConversationSenders:2->1, " + + "mAllowChannels:2->1}, " + + "modified:true->false, " + + "pkg:string1->string2, " + + "zenDeviceEffects:ZenDeviceEffectsDiff{" + + "mGrayscale:true->false, " + + "mSuppressAmbientDisplay:true->false, " + + "mDimWallpaper:true->false, " + + "mNightMode:true->false, " + + "mDisableAutoBrightness:true->false, " + + "mDisableTapToWake:true->false, " + + "mDisableTiltToWake:true->false, " + + "mDisableTouch:true->false, " + + "mMinimizeRadioUsage:true->false, " + + "mMaximizeDoze:true->false, " + + "mExtraEffects:[effect1]->[effect2]}, " + + "triggerDescription:string1->string2, " + + "type:2->1, " + + "allowManualInvocation:true->false, " + + "iconResName:string1->string2, " + + "legacySuppressedEffects:2->1}"); + } + + @Test + @EnableFlags({FLAG_MODES_API, FLAG_MODES_UI}) + public void testRuleDiff_toStringNullStartPolicy() throws Exception { + // Start with two identical rules + ZenModeConfig.ZenRule r1 = makeRule(); + ZenModeConfig.ZenRule r2 = makeRule(); + + ArrayMap<String, Object> expectedFrom = new ArrayMap<>(); + ArrayMap<String, Object> expectedTo = new ArrayMap<>(); + List<Field> fieldsForDiff = getFieldsForDiffCheck( + ZenModeConfig.ZenRule.class, getZenRuleExemptFields(), false); + generateFieldDiffs(r1, r2, fieldsForDiff, expectedFrom, expectedTo); + + // Create a ZenRule with ZenDeviceEffects and ZenPolicy as null. + r1.zenPolicy = null; + r1.zenDeviceEffects = null; + ZenModeDiff.RuleDiff d = new ZenModeDiff.RuleDiff(r1, r2); + assertThat(d.toString()).isEqualTo("ZenRuleDiff{" + + "enabled:true->false, " + + "conditionOverride:2->1, " + + "name:string1->string2, " + + "zenMode:2->1, " + + "conditionId:null->, " + + "condition:null->Condition[" + + "state=STATE_TRUE," + + "id=hello:," + + "summary=," + + "line1=," + + "line2=," + + "icon=-1," + + "source=SOURCE_UNKNOWN," + + "flags=2], " + + "component:null->ComponentInfo{b/b}, " + + "configurationActivity:null->ComponentInfo{a/a}, " + + "id:string1->string2, " + + "creationTime:200->100, " + + "enabler:string1->string2, " + + "zenPolicy:ZenPolicyDiff{added}, " + + "modified:true->false, " + + "pkg:string1->string2, " + + "zenDeviceEffects:ZenDeviceEffectsDiff{added}, " + + "triggerDescription:string1->string2, " + + "type:2->1, " + + "allowManualInvocation:true->false, " + + "iconResName:string1->string2, " + + "legacySuppressedEffects:2->1}"); + } + + @Test public void testDeviceEffectsDiff_addRemoveSame() { // Test add, remove, and both sides same ZenDeviceEffects effects = new ZenDeviceEffects.Builder().build(); @@ -216,12 +358,18 @@ public class ZenModeDiffTest extends UiServiceTestCase { generateFieldDiffs(effects1, effects2, fieldsForDiff, expectedFrom, expectedTo); d = new ZenModeDiff.DeviceEffectsDiff(effects1, effects2); - assertThat(d.toString()).isEqualTo("ZenDeviceEffectsDiff{mNightMode:true->false, " - + "mDisableTapToWake:true->false, mDisableAutoBrightness:true->false, " - + "mSuppressAmbientDisplay:true->false, mDisableTiltToWake:true->false, " - + "mGrayscale:true->false, mDisableTouch:true->false, mMaximizeDoze:true->false, " - + "mMinimizeRadioUsage:true->false, mExtraEffects:null->[], " - + "mDimWallpaper:true->false}"); + assertThat(d.toString()).isEqualTo("ZenDeviceEffectsDiff{" + + "mGrayscale:true->false, " + + "mSuppressAmbientDisplay:true->false, " + + "mDimWallpaper:true->false, " + + "mNightMode:true->false, " + + "mDisableAutoBrightness:true->false, " + + "mDisableTapToWake:true->false, " + + "mDisableTiltToWake:true->false, " + + "mDisableTouch:true->false, " + + "mMinimizeRadioUsage:true->false, " + + "mMaximizeDoze:true->false, " + + "mExtraEffects:[effect1]->[effect2]}"); } @@ -307,17 +455,27 @@ public class ZenModeDiffTest extends UiServiceTestCase { generateFieldDiffsForZenPolicy(policy1, policy2, fieldsForDiff, expectedFrom, expectedTo); d = new ZenModeDiff.PolicyDiff(policy1, policy2); - assertThat(d.toString()).isEqualTo("ZenPolicyDiff{mPriorityCalls:2->1, " - + "mVisualEffects_StatusBar:1->2, mPriorityCategories_RepeatCallers:1->2, " - + "mPriorityCategories_Calls:1->2, mPriorityCategories_Media:1->2, " - + "mConversationSenders:2->1, mPriorityCategories_Reminders:1->2, " - + "mVisualEffects_Badge:1->2, mPriorityCategories_Messages:1->2, " - + "mAllowChannels:2->1, mPriorityMessages:2->1, " - + "mVisualEffects_NotificationList:1->2, mVisualEffects_FullScreenIntent:1->2, " - + "mPriorityCategories_Alarms:1->2, mVisualEffects_Lights:1->2, " - + "mPriorityCategories_Events:1->2, mVisualEffects_Ambient:1->2, " - + "mPriorityCategories_System:1->2, mPriorityCategories_Conversations:1->2, " - + "mVisualEffects_Peek:1->2}"); + assertThat(d.toString()).isEqualTo("ZenPolicyDiff{" + + "mPriorityCategories_Reminders:1->2, " + + "mPriorityCategories_Events:1->2, " + + "mPriorityCategories_Messages:1->2, " + + "mPriorityCategories_Calls:1->2, " + + "mPriorityCategories_RepeatCallers:1->2, " + + "mPriorityCategories_Alarms:1->2, " + + "mPriorityCategories_Media:1->2, " + + "mPriorityCategories_System:1->2, " + + "mPriorityCategories_Conversations:1->2, " + + "mVisualEffects_FullScreenIntent:1->2, " + + "mVisualEffects_Lights:1->2, " + + "mVisualEffects_Peek:1->2, " + + "mVisualEffects_StatusBar:1->2, " + + "mVisualEffects_Badge:1->2, " + + "mVisualEffects_Ambient:1->2, " + + "mVisualEffects_NotificationList:1->2, " + + "mPriorityMessages:2->1, " + + "mPriorityCalls:2->1, " + + "mConversationSenders:2->1, " + + "mAllowChannels:2->1}"); } private static Set<String> getZenRuleExemptFields() { @@ -701,6 +859,44 @@ public class ZenModeDiffTest extends UiServiceTestCase { expectedA.put(f.getName(), "string1"); f.set(b, "string2"); expectedB.put(f.getName(), "string2"); + } else if (Set.class.equals(t)) { + Set<String> aSet = Set.of("effect1"); + Set<String> bSet = Set.of("effect2"); + f.set(a, aSet); + expectedA.put(f.getName(), aSet); + f.set(b, bSet); + expectedB.put(f.getName(), bSet); + } else if (ZenDeviceEffects.class.equals(t)) { + // Recurse into generating field diffs for ZenDeviceEffects. + ZenDeviceEffects effects1 = new ZenDeviceEffects.Builder().build(); + ZenDeviceEffects effects2 = new ZenDeviceEffects.Builder().build(); + // maps mapping field name -> expected output value as we set diffs + ArrayMap<String, Object> expectedFrom = new ArrayMap<>(); + ArrayMap<String, Object> expectedTo = new ArrayMap<>(); + + List<Field> fieldsForDiff = getFieldsForDiffCheck( + ZenDeviceEffects.class, Collections.emptySet() /*no exempt fields*/, true); + generateFieldDiffs(effects1, effects2, fieldsForDiff, expectedFrom, expectedTo); + f.set(a, effects1); + expectedA.put(f.getName(), effects1); + f.set(b, effects2); + expectedB.put(f.getName(), effects2); + } else if (ZenPolicy.class.equals(t)) { + // Recurse into generating field diffs for ZenPolicy. + ZenPolicy policy1 = new ZenPolicy.Builder().build(); + ZenPolicy policy2 = new ZenPolicy.Builder().build(); + // maps mapping field name -> expected output value as we set diffs + ArrayMap<String, Object> expectedFrom = new ArrayMap<>(); + ArrayMap<String, Object> expectedTo = new ArrayMap<>(); + + List<Field> fieldsForDiff = getFieldsForDiffCheck(ZenPolicy.class, + Collections.emptySet(), false); + generateFieldDiffsForZenPolicy(policy1, policy2, fieldsForDiff, expectedFrom, + expectedTo); + f.set(a, policy1); + expectedA.put(f.getName(), policy1); + f.set(b, policy2); + expectedB.put(f.getName(), policy2); } else { // catch-all for other types: have the field be "added" f.set(a, null); |