diff --git a/core/java/android/app/NotificationChannelGroup.java b/core/java/android/app/NotificationChannelGroup.java index 68cac27cb7cac..8854adcfbc925 100644 --- a/core/java/android/app/NotificationChannelGroup.java +++ b/core/java/android/app/NotificationChannelGroup.java @@ -169,6 +169,11 @@ public final class NotificationChannelGroup implements Parcelable { } + @Override + public NotificationChannelGroup clone() { + return new NotificationChannelGroup(getId(), getName()); + } + @Override public int hashCode() { int result = getId() != null ? getId().hashCode() : 0; diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java index 4cbeec815c310..46c449bcab8ee 100644 --- a/services/core/java/com/android/server/notification/RankingHelper.java +++ b/services/core/java/com/android/server/notification/RankingHelper.java @@ -674,7 +674,7 @@ public class RankingHelper implements RankingConfig { public ParceledListSlice getNotificationChannelGroups(String pkg, int uid, boolean includeDeleted) { Preconditions.checkNotNull(pkg); - List groups = new ArrayList<>(); + Map groups = new ArrayMap<>(); Record r = getRecord(pkg, uid); if (r == null) { return ParceledListSlice.emptyList(); @@ -685,23 +685,21 @@ public class RankingHelper implements RankingConfig { final NotificationChannel nc = r.channels.valueAt(i); if (includeDeleted || !nc.isDeleted()) { if (nc.getGroup() != null) { - // lazily populate channel list - NotificationChannelGroup ncg = r.groups.get(nc.getGroup()); + NotificationChannelGroup ncg = groups.get(nc.getGroup()); + if (ncg == null ) { + ncg = r.groups.get(nc.getGroup()).clone(); + groups.put(nc.getGroup(), ncg); + } ncg.addChannel(nc); } else { nonGrouped.addChannel(nc); } } } - for (NotificationChannelGroup group : r.groups.values()) { - if (group.getChannels().size() > 0) { - groups.add(group); - } - } if (nonGrouped.getChannels().size() > 0) { - groups.add(nonGrouped); + groups.put(null, nonGrouped); } - return new ParceledListSlice<>(groups); + return new ParceledListSlice<>(new ArrayList<>(groups.values())); } @Override diff --git a/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java b/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java index e20b5715043d5..9ea9ce9e1d2b6 100644 --- a/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java +++ b/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java @@ -15,6 +15,8 @@ */ package com.android.server.notification; +import static android.app.NotificationManager.IMPORTANCE_LOW; + import static junit.framework.Assert.assertNull; import static junit.framework.Assert.fail; @@ -56,6 +58,7 @@ import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -168,7 +171,7 @@ public class RankingHelperTest { private NotificationChannel getDefaultChannel() { return new NotificationChannel(NotificationChannel.DEFAULT_CHANNEL_ID, "name", - NotificationManager.IMPORTANCE_LOW); + IMPORTANCE_LOW); } private ByteArrayOutputStream writeXmlAndPurge(String pkg, int uid, String... channelIds) @@ -260,7 +263,7 @@ public class RankingHelperTest { NotificationChannel channel1 = new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH); NotificationChannel channel2 = - new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW); + new NotificationChannel("id2", "name2", IMPORTANCE_LOW); channel2.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes); channel2.enableLights(true); channel2.setBypassDnd(true); @@ -294,10 +297,26 @@ public class RankingHelperTest { mHelper.getNotificationChannel(pkg, uid, channel2.getId(), false)); assertNotNull(mHelper.getNotificationChannel( pkg, uid, NotificationChannel.DEFAULT_CHANNEL_ID, false)); - assertEquals(ncg.getId(), - mHelper.getNotificationChannelGroups(pkg, uid, false).getList().get(0).getId()); - assertEquals(channel2.getGroup(), mHelper.getNotificationChannelGroups( - pkg, uid, false).getList().get(0).getChannels().get(0).getGroup()); + + List actualGroups = + mHelper.getNotificationChannelGroups(pkg, uid, false).getList(); + boolean foundNcg = false; + for (NotificationChannelGroup actual : actualGroups) { + if (ncg.getId().equals(actual.getId())) { + foundNcg = true; + break; + } + } + assertTrue(foundNcg); + + boolean foundChannel2Group = false; + for (NotificationChannelGroup actual : actualGroups) { + if (channel2.getGroup().equals(actual.getChannels().get(0).getGroup())) { + foundChannel2Group = true; + break; + } + } + assertTrue(foundChannel2Group); } @Test @@ -332,7 +351,7 @@ public class RankingHelperTest { final NotificationChannel defaultChannel = mHelper.getNotificationChannel( pkg, uid, NotificationChannel.DEFAULT_CHANNEL_ID, false); - defaultChannel.setImportance(NotificationManager.IMPORTANCE_LOW); + defaultChannel.setImportance(IMPORTANCE_LOW); mHelper.updateNotificationChannel(pkg, uid, defaultChannel); ByteArrayOutputStream baos = writeXmlAndPurge(pkg, uid, channel1.getId(), @@ -344,7 +363,7 @@ public class RankingHelperTest { parser.nextTag(); mHelper.readXml(parser, false); - assertEquals(NotificationManager.IMPORTANCE_LOW, mHelper.getNotificationChannel( + assertEquals(IMPORTANCE_LOW, mHelper.getNotificationChannel( pkg, uid, NotificationChannel.DEFAULT_CHANNEL_ID, false).getImportance()); } @@ -376,7 +395,7 @@ public class RankingHelperTest { final NotificationChannel updated2 = mHelper.getNotificationChannel( pkg2, uid2, NotificationChannel.DEFAULT_CHANNEL_ID, false); // clamped - assertEquals(NotificationManager.IMPORTANCE_LOW, updated2.getImportance()); + assertEquals(IMPORTANCE_LOW, updated2.getImportance()); assertFalse(updated2.canBypassDnd()); assertEquals(Notification.VISIBILITY_PRIVATE, updated2.getLockscreenVisibility()); assertEquals(NotificationChannel.USER_LOCKED_VISIBILITY, updated2.getUserLockedFields()); @@ -388,7 +407,7 @@ public class RankingHelperTest { try { mHelper.createNotificationChannel(pkg, uid, - new NotificationChannel(pkg, "", NotificationManager.IMPORTANCE_LOW), true); + new NotificationChannel(pkg, "", IMPORTANCE_LOW), true); fail("Channel creation should fail"); } catch (IllegalArgumentException e) { // pass @@ -399,7 +418,7 @@ public class RankingHelperTest { public void testUpdate_userLockedImportance() throws Exception { // all fields locked by user final NotificationChannel channel = - new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW); + new NotificationChannel("id2", "name2", IMPORTANCE_LOW); channel.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE); mHelper.createNotificationChannel(pkg, uid, channel, false); @@ -418,7 +437,7 @@ public class RankingHelperTest { public void testUpdate_userLockedVisibility() throws Exception { // all fields locked by user final NotificationChannel channel = - new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW); + new NotificationChannel("id2", "name2", IMPORTANCE_LOW); channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET); channel.lockFields(NotificationChannel.USER_LOCKED_VISIBILITY); @@ -439,7 +458,7 @@ public class RankingHelperTest { public void testUpdate_userLockedVibration() throws Exception { // all fields locked by user final NotificationChannel channel = - new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW); + new NotificationChannel("id2", "name2", IMPORTANCE_LOW); channel.enableLights(false); channel.lockFields(NotificationChannel.USER_LOCKED_VIBRATION); @@ -461,7 +480,7 @@ public class RankingHelperTest { public void testUpdate_userLockedLights() throws Exception { // all fields locked by user final NotificationChannel channel = - new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW); + new NotificationChannel("id2", "name2", IMPORTANCE_LOW); channel.enableLights(false); channel.lockFields(NotificationChannel.USER_LOCKED_LIGHTS); @@ -482,7 +501,7 @@ public class RankingHelperTest { public void testUpdate_userLockedPriority() throws Exception { // all fields locked by user final NotificationChannel channel = - new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW); + new NotificationChannel("id2", "name2", IMPORTANCE_LOW); channel.setBypassDnd(true); channel.lockFields(NotificationChannel.USER_LOCKED_PRIORITY); @@ -503,7 +522,7 @@ public class RankingHelperTest { public void testUpdate_userLockedRingtone() throws Exception { // all fields locked by user final NotificationChannel channel = - new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW); + new NotificationChannel("id2", "name2", IMPORTANCE_LOW); channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes); channel.lockFields(NotificationChannel.USER_LOCKED_SOUND); @@ -523,7 +542,7 @@ public class RankingHelperTest { @Test public void testUpdate_userLockedBadge() throws Exception { final NotificationChannel channel = - new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW); + new NotificationChannel("id2", "name2", IMPORTANCE_LOW); channel.setShowBadge(true); channel.lockFields(NotificationChannel.USER_LOCKED_SHOW_BADGE); @@ -543,7 +562,7 @@ public class RankingHelperTest { public void testUpdate() throws Exception { // no fields locked by user final NotificationChannel channel = - new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW); + new NotificationChannel("id2", "name2", IMPORTANCE_LOW); channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes); channel.enableLights(true); channel.setBypassDnd(true); @@ -575,7 +594,7 @@ public class RankingHelperTest { @Test public void testCreateChannel_CannotChangeHiddenFields() throws Exception { final NotificationChannel channel = - new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW); + new NotificationChannel("id2", "name2", IMPORTANCE_LOW); channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes); channel.enableLights(true); channel.setBypassDnd(true); @@ -602,7 +621,7 @@ public class RankingHelperTest { @Test public void testCreateChannel_CannotChangeHiddenFieldsAssistant() throws Exception { final NotificationChannel channel = - new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW); + new NotificationChannel("id2", "name2", IMPORTANCE_LOW); channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes); channel.enableLights(true); channel.setBypassDnd(true); @@ -629,7 +648,7 @@ public class RankingHelperTest { @Test public void testGetDeletedChannel() throws Exception { NotificationChannel channel = - new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW); + new NotificationChannel("id2", "name2", IMPORTANCE_LOW); channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes); channel.enableLights(true); channel.setBypassDnd(true); @@ -655,7 +674,7 @@ public class RankingHelperTest { public void testGetDeletedChannels() throws Exception { Map channelMap = new HashMap<>(); NotificationChannel channel = - new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW); + new NotificationChannel("id2", "name2", IMPORTANCE_LOW); channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes); channel.enableLights(true); channel.setBypassDnd(true); @@ -694,7 +713,7 @@ public class RankingHelperTest { @Test public void testUpdateDeletedChannels() throws Exception { NotificationChannel channel = - new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW); + new NotificationChannel("id2", "name2", IMPORTANCE_LOW); mHelper.createNotificationChannel(pkg, uid, channel, true); mHelper.deleteNotificationChannel(pkg, uid, channel.getId()); @@ -719,7 +738,7 @@ public class RankingHelperTest { public void testCreateDeletedChannel() throws Exception { long[] vibration = new long[]{100, 67, 145, 156}; NotificationChannel channel = - new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW); + new NotificationChannel("id2", "name2", IMPORTANCE_LOW); channel.setVibrationPattern(vibration); mHelper.createNotificationChannel(pkg, uid, channel, true); @@ -740,7 +759,7 @@ public class RankingHelperTest { public void testCreateChannel_alreadyExists() throws Exception { long[] vibration = new long[]{100, 67, 145, 156}; NotificationChannel channel = - new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW); + new NotificationChannel("id2", "name2", IMPORTANCE_LOW); channel.setVibrationPattern(vibration); mHelper.createNotificationChannel(pkg, uid, channel, true); @@ -761,7 +780,7 @@ public class RankingHelperTest { NotificationChannel channel1 = new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH); NotificationChannel channel2 = - new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW); + new NotificationChannel("id2", "name2", IMPORTANCE_LOW); mHelper.createNotificationChannel(pkg, uid, channel1, true); mHelper.createNotificationChannel(pkg, uid, channel2, false); @@ -900,4 +919,29 @@ public class RankingHelperTest { } } } + + @Test + public void testGetChannelGroups_noSideEffects() throws Exception { + NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1"); + mHelper.createNotificationChannelGroup(pkg, uid, ncg, true); + + NotificationChannel channel1 = + new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH); + channel1.setGroup(ncg.getId()); + mHelper.createNotificationChannel(pkg, uid, channel1, true); + mHelper.getNotificationChannelGroups(pkg, uid, true).getList(); + + channel1.setImportance(IMPORTANCE_LOW); + mHelper.updateNotificationChannel(pkg, uid, channel1); + + List actual = + mHelper.getNotificationChannelGroups(pkg, uid, true).getList(); + + assertEquals(2, actual.size()); + for (NotificationChannelGroup group : actual) { + if (Objects.equals(group.getId(),ncg.getId())) { + assertEquals(1, group.getChannels().size()); + } + } + } }