diff --git a/res/drawable/ic_zen_mode_sound_alarms.xml b/res/drawable/ic_zen_mode_sound_alarms.xml
new file mode 100644
index 00000000000..b2761ca3a08
--- /dev/null
+++ b/res/drawable/ic_zen_mode_sound_alarms.xml
@@ -0,0 +1,25 @@
+
+
+
+
\ No newline at end of file
diff --git a/res/drawable/ic_zen_mode_sound_events.xml b/res/drawable/ic_zen_mode_sound_events.xml
new file mode 100644
index 00000000000..15035e4fa2d
--- /dev/null
+++ b/res/drawable/ic_zen_mode_sound_events.xml
@@ -0,0 +1,25 @@
+
+
+
+
\ No newline at end of file
diff --git a/res/drawable/ic_zen_mode_sound_media.xml b/res/drawable/ic_zen_mode_sound_media.xml
new file mode 100644
index 00000000000..f2bedcb9c8e
--- /dev/null
+++ b/res/drawable/ic_zen_mode_sound_media.xml
@@ -0,0 +1,25 @@
+
+
+
+
\ No newline at end of file
diff --git a/res/drawable/ic_zen_mode_sound_reminders.xml b/res/drawable/ic_zen_mode_sound_reminders.xml
new file mode 100644
index 00000000000..cd9490a988f
--- /dev/null
+++ b/res/drawable/ic_zen_mode_sound_reminders.xml
@@ -0,0 +1,25 @@
+
+
+
+
\ No newline at end of file
diff --git a/res/drawable/ic_zen_mode_sound_system.xml b/res/drawable/ic_zen_mode_sound_system.xml
new file mode 100644
index 00000000000..2da05d8f38f
--- /dev/null
+++ b/res/drawable/ic_zen_mode_sound_system.xml
@@ -0,0 +1,25 @@
+
+
+
+
\ No newline at end of file
diff --git a/res/drawable/preference_circular_icons_plus_item_background.xml b/res/drawable/preference_circular_icons_plus_item_background.xml
index 8200a9b12eb..faaa1fd11fe 100644
--- a/res/drawable/preference_circular_icons_plus_item_background.xml
+++ b/res/drawable/preference_circular_icons_plus_item_background.xml
@@ -22,7 +22,4 @@
android:width="@dimen/zen_mode_circular_icon_diameter"
android:height="@dimen/zen_mode_circular_icon_diameter" />
-
\ No newline at end of file
diff --git a/src/com/android/settings/notification/modes/CircularIconSet.java b/src/com/android/settings/notification/modes/CircularIconSet.java
index 18f82d97de0..eb7289aabe1 100644
--- a/src/com/android/settings/notification/modes/CircularIconSet.java
+++ b/src/com/android/settings/notification/modes/CircularIconSet.java
@@ -20,8 +20,10 @@ import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
+import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
+import com.google.common.base.Equivalence;
import com.google.common.base.MoreObjects;
import com.google.common.collect.ImmutableList;
import com.google.common.util.concurrent.ListenableFuture;
@@ -29,6 +31,7 @@ import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
import java.util.List;
+import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@@ -67,8 +70,25 @@ class CircularIconSet {
return MoreObjects.toStringHelper(this).add("items", mItems).toString();
}
- boolean hasSameItemsAs(CircularIconSet> other) {
- return other != null && this.mItems.equals(other.mItems);
+ @SuppressWarnings("unchecked")
+ boolean hasSameItemsAs(CircularIconSet other,
+ @Nullable Equivalence equivalence) {
+ if (other == null) {
+ return false;
+ }
+ if (other == this) {
+ return true;
+ }
+ if (equivalence == null) {
+ return mItems.equals(other.mItems);
+ }
+ // Check that types match before applying equivalence (statically unsafe). :(
+ Optional> thisItemClass = this.mItems.stream().findFirst().map(T::getClass);
+ Optional> otherItemClass = other.mItems.stream().findFirst().map(OtherT::getClass);
+ if (!thisItemClass.equals(otherItemClass)) {
+ return false;
+ }
+ return equivalence.pairwise().equivalent((Iterable) this.mItems, other.mItems);
}
int size() {
diff --git a/src/com/android/settings/notification/modes/CircularIconsPreference.java b/src/com/android/settings/notification/modes/CircularIconsPreference.java
index 5e8f720c83c..1ce34766fdc 100644
--- a/src/com/android/settings/notification/modes/CircularIconsPreference.java
+++ b/src/com/android/settings/notification/modes/CircularIconsPreference.java
@@ -41,6 +41,7 @@ import com.android.settings.R;
import com.android.settingslib.RestrictedPreference;
import com.android.settingslib.Utils;
+import com.google.common.base.Equivalence;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
@@ -105,8 +106,12 @@ public class CircularIconsPreference extends RestrictedPreference {
}
}
- void displayIcons(CircularIconSet> iconSet) {
- if (mIconSet != null && mIconSet.hasSameItemsAs(iconSet)) {
+ void displayIcons(CircularIconSet iconSet) {
+ displayIcons(iconSet, null);
+ }
+
+ void displayIcons(CircularIconSet iconSet, @Nullable Equivalence itemEquivalence) {
+ if (mIconSet != null && mIconSet.hasSameItemsAs(iconSet, itemEquivalence)) {
return;
}
mIconSet = iconSet;
@@ -189,7 +194,6 @@ public class CircularIconsPreference extends RestrictedPreference {
}
// ... plus 0/1 TextViews at the end.
if (extraItems > 0 && !(getLastChild(mIconContainer) instanceof TextView)) {
- // TODO: b/346551087 - Check TODO in preference_circular_icons_plus_item_background
TextView plusView = (TextView) inflater.inflate(
R.layout.preference_circular_icons_plus_item, mIconContainer, false);
mIconContainer.addView(plusView);
diff --git a/src/com/android/settings/notification/modes/ZenModeAppsLinkPreferenceController.java b/src/com/android/settings/notification/modes/ZenModeAppsLinkPreferenceController.java
index 9bff2bbb558..962e0162310 100644
--- a/src/com/android/settings/notification/modes/ZenModeAppsLinkPreferenceController.java
+++ b/src/com/android/settings/notification/modes/ZenModeAppsLinkPreferenceController.java
@@ -40,6 +40,7 @@ import com.android.settingslib.applications.ApplicationsState.AppEntry;
import com.android.settingslib.notification.modes.ZenMode;
import com.android.settingslib.notification.modes.ZenModesBackend;
+import com.google.common.base.Equivalence;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Multimap;
@@ -47,6 +48,7 @@ import com.google.common.collect.Multimap;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
+import java.util.Objects;
/**
* Preference with a link and summary about what apps can break through the mode
@@ -137,7 +139,8 @@ class ZenModeAppsLinkPreferenceController extends AbstractZenModePreferenceContr
mPreference.setSummary(mSummaryHelper.getAppsSummary(mZenMode, apps));
mPreference.displayIcons(new CircularIconSet<>(apps,
- app -> Utils.getBadgedIcon(mContext, app.info)));
+ app -> Utils.getBadgedIcon(mContext, app.info)),
+ APP_ENTRY_EQUIVALENCE);
}
@VisibleForTesting
@@ -158,6 +161,19 @@ class ZenModeAppsLinkPreferenceController extends AbstractZenModePreferenceContr
.toList());
}
+ private static final Equivalence APP_ENTRY_EQUIVALENCE = new Equivalence<>() {
+ @Override
+ protected boolean doEquivalent(@NonNull AppEntry a, @NonNull AppEntry b) {
+ return a.info.uid == b.info.uid
+ && Objects.equals(a.info.packageName, b.info.packageName);
+ }
+
+ @Override
+ protected int doHash(@NonNull AppEntry entry) {
+ return Objects.hash(entry.info.uid, entry.info.packageName);
+ }
+ };
+
@VisibleForTesting
final ApplicationsState.Callbacks mAppSessionCallbacks =
new ApplicationsState.Callbacks() {
diff --git a/src/com/android/settings/notification/modes/ZenModeOtherLinkPreferenceController.java b/src/com/android/settings/notification/modes/ZenModeOtherLinkPreferenceController.java
index 206ad42bc7b..d7bd5177aaf 100644
--- a/src/com/android/settings/notification/modes/ZenModeOtherLinkPreferenceController.java
+++ b/src/com/android/settings/notification/modes/ZenModeOtherLinkPreferenceController.java
@@ -29,6 +29,7 @@ import android.service.notification.ZenPolicy;
import androidx.annotation.NonNull;
import androidx.preference.Preference;
+import com.android.settings.R;
import com.android.settingslib.notification.modes.ZenMode;
import com.google.common.collect.ImmutableList;
@@ -41,19 +42,13 @@ import java.util.Map;
*/
class ZenModeOtherLinkPreferenceController extends AbstractZenModePreferenceController {
- // TODO: b/346551087 - Use proper icons
private static final ImmutableMap* @PriorityCategory */ Integer, /* @DrawableRes */ Integer>
PRIORITIES_TO_ICONS = ImmutableMap.of(
- PRIORITY_CATEGORY_ALARMS,
- com.android.internal.R.drawable.ic_audio_alarm,
- PRIORITY_CATEGORY_MEDIA,
- com.android.settings.R.drawable.ic_media_stream,
- PRIORITY_CATEGORY_SYSTEM,
- com.android.settings.R.drawable.ic_settings_keyboards,
- PRIORITY_CATEGORY_REMINDERS,
- com.android.internal.R.drawable.ic_popup_reminder,
- PRIORITY_CATEGORY_EVENTS,
- com.android.internal.R.drawable.ic_zen_mode_type_schedule_calendar);
+ PRIORITY_CATEGORY_ALARMS, R.drawable.ic_zen_mode_sound_alarms,
+ PRIORITY_CATEGORY_MEDIA, R.drawable.ic_zen_mode_sound_media,
+ PRIORITY_CATEGORY_SYSTEM, R.drawable.ic_zen_mode_sound_system,
+ PRIORITY_CATEGORY_REMINDERS, R.drawable.ic_zen_mode_sound_reminders,
+ PRIORITY_CATEGORY_EVENTS, R.drawable.ic_zen_mode_sound_events);
private final ZenModeSummaryHelper mSummaryHelper;
diff --git a/tests/robotests/src/com/android/settings/notification/modes/CircularIconSetTest.java b/tests/robotests/src/com/android/settings/notification/modes/CircularIconSetTest.java
index 9e8524395e5..826c9df4cee 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/CircularIconSetTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/CircularIconSetTest.java
@@ -27,6 +27,7 @@ import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
+import com.google.common.base.Equivalence;
import com.google.common.collect.ImmutableList;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.MoreExecutors;
@@ -54,33 +55,111 @@ public class CircularIconSetTest {
}
@Test
- public void equals_sameItems_true() {
+ public void hasSameItemsAs_sameItems_true() {
CircularIconSet items1 = new CircularIconSet<>(ImmutableList.of(1, 2),
num -> new ColorDrawable(Color.BLUE));
CircularIconSet items2 = new CircularIconSet<>(ImmutableList.of(1, 2),
num -> new ColorDrawable(Color.GREEN));
- assertThat(items1.hasSameItemsAs(items2)).isTrue();
+ assertThat(items1.hasSameItemsAs(items2, null)).isTrue();
}
@Test
- public void equals_differentTypes_false() {
+ public void hasSameItemsAs_differentTypes_false() {
CircularIconSet items1 = new CircularIconSet<>(ImmutableList.of(1, 2),
num -> new ColorDrawable(Color.BLUE));
CircularIconSet items2 = new CircularIconSet<>(ImmutableList.of("a", "b"),
str -> new ColorDrawable(Color.GREEN));
- assertThat(items1.hasSameItemsAs(items2)).isFalse();
+ assertThat(items1.hasSameItemsAs(items2, null)).isFalse();
}
@Test
- public void equals_differentItems_false() {
+ public void hasSameItemsAs_differentItems_false() {
CircularIconSet items1 = new CircularIconSet<>(ImmutableList.of("a", "b"),
str -> new ColorDrawable(Color.GREEN));
CircularIconSet items2 = new CircularIconSet<>(ImmutableList.of("a", "b", "c"),
str -> new ColorDrawable(Color.GREEN));
- assertThat(items1.hasSameItemsAs(items2)).isFalse();
+ assertThat(items1.hasSameItemsAs(items2, null)).isFalse();
+ }
+
+ private static class WrapperWithoutEquals {
+ private final T mValue;
+ private WrapperWithoutEquals(T value) {
+ mValue = value;
+ }
+ }
+
+ @Test
+ public void hasSameItemsAs_withEquivalence_trueIfEquivalentItems() {
+ CircularIconSet> items1 = new CircularIconSet<>(
+ ImmutableList.of(
+ new WrapperWithoutEquals<>(1),
+ new WrapperWithoutEquals<>(2)),
+ unused -> new ColorDrawable(Color.BLACK));
+ CircularIconSet> items2 = new CircularIconSet<>(
+ ImmutableList.of(
+ new WrapperWithoutEquals<>(1),
+ new WrapperWithoutEquals<>(2)),
+ unused -> new ColorDrawable(Color.BLACK));
+ CircularIconSet> items3 = new CircularIconSet<>(
+ ImmutableList.of(
+ new WrapperWithoutEquals<>(2),
+ new WrapperWithoutEquals<>(3)),
+ unused -> new ColorDrawable(Color.BLACK));
+ // Needs special equivalence, equals is not enough.
+ assertThat(items1.hasSameItemsAs(items2, null)).isFalse();
+
+ Equivalence> equivalence = new Equivalence<>() {
+ @Override
+ protected boolean doEquivalent(WrapperWithoutEquals a,
+ WrapperWithoutEquals b) {
+ return a.mValue.equals(b.mValue);
+ }
+
+ @Override
+ protected int doHash(WrapperWithoutEquals t) {
+ return t.mValue;
+ }
+ };
+
+ assertThat(items1.hasSameItemsAs(items2, equivalence)).isTrue();
+ assertThat(items1.hasSameItemsAs(items3, equivalence)).isFalse();
+ }
+
+ @Test
+ public void hasSameItemsAs_withEquivalenceButDifferentTypes_falseAndNoClassCastExceptions() {
+ CircularIconSet items1 = new CircularIconSet<>(ImmutableList.of(1, 2),
+ num -> new ColorDrawable(Color.BLUE));
+ CircularIconSet items2 = new CircularIconSet<>(ImmutableList.of("one", "two"),
+ num -> new ColorDrawable(Color.GREEN));
+
+ Equivalence stringEquivalence = new Equivalence() {
+ @Override
+ protected boolean doEquivalent(String a, String b) {
+ return a.equals(b);
+ }
+
+ @Override
+ protected int doHash(String t) {
+ return t.hashCode();
+ }
+ };
+ Equivalence integerEquivalence = new Equivalence() {
+ @Override
+ protected boolean doEquivalent(Integer a, Integer b) {
+ return a.equals(b);
+ }
+
+ @Override
+ protected int doHash(Integer t) {
+ return t.hashCode();
+ }
+ };
+
+ assertThat(items1.hasSameItemsAs(items2, stringEquivalence)).isFalse();
+ assertThat(items2.hasSameItemsAs(items1, integerEquivalence)).isFalse();
}
@Test