diff options
author | 2025-03-24 08:23:42 -0700 | |
---|---|---|
committer | 2025-03-24 08:23:42 -0700 | |
commit | ef03d144d911809568c867af3e75c1e779248c4e (patch) | |
tree | 9a31efe683d94b8973a87081e8febff6500db80e | |
parent | 1e0d2429734b7d0c58a5442574e3abb31f49852c (diff) | |
parent | 6f9d00968b68d7680a41994dd1697afca6b3525b (diff) |
Merge changes If8f56401,I950695c8 into main
* changes:
Add elements to existing mChannelsList instead of overwriting in setChannels
Return copies of notification channels and groups instead of the cached entities.
-rw-r--r-- | core/api/test-current.txt | 2 | ||||
-rw-r--r-- | core/java/android/app/NotificationChannel.java | 1 | ||||
-rw-r--r-- | core/java/android/app/NotificationChannelGroup.java | 9 | ||||
-rw-r--r-- | core/java/android/app/NotificationManager.java | 35 | ||||
-rw-r--r-- | core/tests/coretests/src/android/app/NotificationManagerTest.java | 69 |
5 files changed, 101 insertions, 15 deletions
diff --git a/core/api/test-current.txt b/core/api/test-current.txt index daa1902edf02..1e21991cd380 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -369,7 +369,7 @@ package android.app { } public final class NotificationChannel implements android.os.Parcelable { - method @FlaggedApi("android.service.notification.notification_conversation_channel_management") @NonNull public android.app.NotificationChannel copy(); + method @NonNull public android.app.NotificationChannel copy(); method public int getOriginalImportance(); method public boolean isImportanceLockedByCriticalDeviceFunction(); method public void lockFields(int); diff --git a/core/java/android/app/NotificationChannel.java b/core/java/android/app/NotificationChannel.java index d88395331656..c1d80c93cfd6 100644 --- a/core/java/android/app/NotificationChannel.java +++ b/core/java/android/app/NotificationChannel.java @@ -508,7 +508,6 @@ public final class NotificationChannel implements Parcelable { /** @hide */ @TestApi @NonNull - @FlaggedApi(FLAG_NOTIFICATION_CONVERSATION_CHANNEL_MANAGEMENT) public NotificationChannel copy() { NotificationChannel copy = new NotificationChannel(mId, mName, mImportance); copy.setDescription(mDesc); diff --git a/core/java/android/app/NotificationChannelGroup.java b/core/java/android/app/NotificationChannelGroup.java index 92db8b329045..06b492c417d8 100644 --- a/core/java/android/app/NotificationChannelGroup.java +++ b/core/java/android/app/NotificationChannelGroup.java @@ -221,7 +221,10 @@ public final class NotificationChannelGroup implements Parcelable { * @hide */ public void setChannels(List<NotificationChannel> channels) { - mChannels = channels; + mChannels.clear(); + if (channels != null) { + mChannels.addAll(channels); + } } /** @@ -331,7 +334,9 @@ public final class NotificationChannelGroup implements Parcelable { NotificationChannelGroup cloned = new NotificationChannelGroup(getId(), getName()); cloned.setDescription(getDescription()); cloned.setBlocked(isBlocked()); - cloned.setChannels(getChannels()); + for (NotificationChannel c : mChannels) { + cloned.addChannel(c.copy()); + } cloned.lockFields(mUserLockedFields); return cloned; } diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java index 69e3ef9086d5..f24eb0a63b26 100644 --- a/core/java/android/app/NotificationManager.java +++ b/core/java/android/app/NotificationManager.java @@ -1317,10 +1317,16 @@ public class NotificationManager { */ public List<NotificationChannel> getNotificationChannels() { if (Flags.nmBinderPerfCacheChannels()) { - return mNotificationChannelListCache.query(new NotificationChannelQuery( - mContext.getOpPackageName(), - mContext.getPackageName(), - mContext.getUserId())); + List<NotificationChannel> channelList = mNotificationChannelListCache.query( + new NotificationChannelQuery(mContext.getOpPackageName(), + mContext.getPackageName(), mContext.getUserId())); + List<NotificationChannel> out = new ArrayList(); + if (channelList != null) { + for (NotificationChannel c : channelList) { + out.add(c.copy()); + } + } + return out; } else { INotificationManager service = service(); try { @@ -1343,7 +1349,7 @@ public class NotificationManager { } for (NotificationChannel channel : channels) { if (channelId.equals(channel.getId())) { - return channel; + return channel.copy(); } } return null; @@ -1364,12 +1370,12 @@ public class NotificationManager { for (NotificationChannel channel : channels) { if (conversationId.equals(channel.getConversationId()) && channelId.equals(channel.getParentChannelId())) { - return channel; + return channel.copy(); } else if (channelId.equals(channel.getId())) { parent = channel; } } - return parent; + return parent != null ? parent.copy() : null; } /** @@ -1405,8 +1411,9 @@ public class NotificationManager { new NotificationChannelQuery(pkgName, pkgName, mContext.getUserId())); Map<String, NotificationChannelGroup> groupHeaders = mNotificationChannelGroupsCache.query(pkgName); - return NotificationChannelGroupsHelper.getGroupWithChannels(channelGroupId, channelList, - groupHeaders, /* includeDeleted= */ false); + NotificationChannelGroup ncg = NotificationChannelGroupsHelper.getGroupWithChannels( + channelGroupId, channelList, groupHeaders, /* includeDeleted= */ false); + return ncg != null ? ncg.clone() : null; } else { INotificationManager service = service(); try { @@ -1428,8 +1435,14 @@ public class NotificationManager { new NotificationChannelQuery(pkgName, pkgName, mContext.getUserId())); Map<String, NotificationChannelGroup> groupHeaders = mNotificationChannelGroupsCache.query(pkgName); - return NotificationChannelGroupsHelper.getGroupsWithChannels(channelList, groupHeaders, - NotificationChannelGroupsHelper.Params.forAllGroups()); + List<NotificationChannelGroup> populatedGroupList = + NotificationChannelGroupsHelper.getGroupsWithChannels(channelList, groupHeaders, + NotificationChannelGroupsHelper.Params.forAllGroups()); + List<NotificationChannelGroup> out = new ArrayList<>(); + for (NotificationChannelGroup g : populatedGroupList) { + out.add(g.clone()); + } + return out; } else { INotificationManager service = service(); try { diff --git a/core/tests/coretests/src/android/app/NotificationManagerTest.java b/core/tests/coretests/src/android/app/NotificationManagerTest.java index 250b9ce8d89d..001eb620dd0f 100644 --- a/core/tests/coretests/src/android/app/NotificationManagerTest.java +++ b/core/tests/coretests/src/android/app/NotificationManagerTest.java @@ -442,6 +442,44 @@ public class NotificationManagerTest { @Test @EnableFlags(Flags.FLAG_NM_BINDER_PERF_CACHE_CHANNELS) + public void getNotificationChannel_localModificationDoesNotChangeCache() throws Exception { + NotificationManager.invalidateNotificationChannelCache(); + NotificationChannel original = new NotificationChannel("id", "name", + NotificationManager.IMPORTANCE_DEFAULT); + NotificationChannel originalConv = new NotificationChannel("", "name_conversation", + NotificationManager.IMPORTANCE_DEFAULT); + originalConv.setConversationId("id", "id_conversation"); + when(mNotificationManager.mBackendService.getNotificationChannels(any(), any(), + anyInt())).thenReturn(new ParceledListSlice<>( + List.of(original.copy(), originalConv.copy()))); + + // modify the output channel, but only locally + NotificationChannel out = mNotificationManager.getNotificationChannel("id"); + out.setName("modified"); + + // This should not change the result of getNotificationChannel + assertThat(mNotificationManager.getNotificationChannel("id")).isEqualTo(original); + assertThat(mNotificationManager.getNotificationChannel("id")).isNotEqualTo(out); + + // and also check the conversation channel + NotificationChannel outConv = mNotificationManager.getNotificationChannel("id", + "id_conversation"); + outConv.setName("conversation_modified"); + assertThat(mNotificationManager.getNotificationChannel("id", "id_conversation")).isEqualTo( + originalConv); + assertThat( + mNotificationManager.getNotificationChannel("id", "id_conversation")).isNotEqualTo( + outConv); + + // nonexistent conversation returns the (not modified) parent channel + assertThat(mNotificationManager.getNotificationChannel("id", "nonexistent")).isEqualTo( + original); + assertThat(mNotificationManager.getNotificationChannel("id", "nonexistent")).isNotEqualTo( + out); + } + + @Test + @EnableFlags(Flags.FLAG_NM_BINDER_PERF_CACHE_CHANNELS) public void getNotificationChannelGroup_cachedUntilInvalidated() throws Exception { // Data setup: group has some channels in it NotificationChannelGroup g1 = new NotificationChannelGroup("g1", "group one"); @@ -521,6 +559,37 @@ public class NotificationManagerTest { } @Test + @EnableFlags(Flags.FLAG_NM_BINDER_PERF_CACHE_CHANNELS) + public void getNotificationChannelGroup_localModificationDoesNotChangeCache() throws Exception { + // Group setup + NotificationChannelGroup g1 = new NotificationChannelGroup("g1", "group one"); + NotificationChannel nc1 = new NotificationChannel("nc1", "channel one", + NotificationManager.IMPORTANCE_DEFAULT); + nc1.setGroup("g1"); + NotificationChannel nc2 = new NotificationChannel("nc2", "channel two", + NotificationManager.IMPORTANCE_DEFAULT); + nc2.setGroup("g1"); + + NotificationManager.invalidateNotificationChannelCache(); + NotificationManager.invalidateNotificationChannelGroupCache(); + when(mNotificationManager.mBackendService.getNotificationChannelGroupsWithoutChannels( + any())).thenReturn(new ParceledListSlice<>(List.of(g1.clone()))); + when(mNotificationManager.mBackendService.getNotificationChannels(any(), any(), anyInt())) + .thenReturn(new ParceledListSlice<>(List.of(nc1.copy(), nc2.copy()))); + + NotificationChannelGroup g1result = mNotificationManager.getNotificationChannelGroup("g1"); + g1result.setDescription("something different!"); + for (NotificationChannel c : g1result.getChannels()) { + c.setDescription("also something different"); + } + + // expected output equivalent to original, unchanged + NotificationChannelGroup expectedG1 = g1.clone(); + expectedG1.setChannels(List.of(nc1, nc2)); + assertThat(mNotificationManager.getNotificationChannelGroup("g1")).isEqualTo(expectedG1); + } + + @Test @EnableFlags(Flags.FLAG_MODES_UI) public void areAutomaticZenRulesUserManaged_handheld_isTrue() { PackageManager pm = mock(PackageManager.class); |