Loading services/core/java/com/android/server/notification/NotificationManagerService.java +31 −3 Original line number Diff line number Diff line Loading @@ -7042,9 +7042,8 @@ public class NotificationManagerService extends SystemService { channelId = (new Notification.TvExtender(notification)).getChannelId(); } String shortcutId = n.getShortcutId(); final NotificationChannel channel = mPreferencesHelper.getConversationNotificationChannel( pkg, notificationUid, channelId, shortcutId, true /* parent ok */, false /* includeDeleted */); final NotificationChannel channel = getNotificationChannelRestoreDeleted(pkg, callingUid, notificationUid, channelId, shortcutId); if (channel == null) { final String noChannelStr = "No Channel found for " + "pkg=" + pkg Loading Loading @@ -7162,6 +7161,35 @@ public class NotificationManagerService extends SystemService { return true; } /** * Returns a channel, if exists, and restores deleted conversation channels. */ @Nullable private NotificationChannel getNotificationChannelRestoreDeleted(String pkg, int callingUid, int notificationUid, String channelId, String conversationId) { // Restore a deleted conversation channel, if exists. Otherwise use the parent channel. NotificationChannel channel = mPreferencesHelper.getConversationNotificationChannel( pkg, notificationUid, channelId, conversationId, true /* parent ok */, !TextUtils.isEmpty(conversationId) /* includeDeleted */); // Restore deleted conversation channel if (channel != null && channel.isDeleted()) { if (Objects.equals(conversationId, channel.getConversationId())) { boolean needsPolicyFileChange = mPreferencesHelper.createNotificationChannel( pkg, notificationUid, channel, true /* fromTargetApp */, mConditionProviders.isPackageOrComponentAllowed(pkg, UserHandle.getUserId(notificationUid)), callingUid, true); // Update policy file if the conversation channel was restored if (needsPolicyFileChange) { handleSavePolicyFile(); } } else { // Do not restore parent channel channel = null; } } return channel; } private void onConversationRemovedInternal(String pkg, int uid, Set<String> shortcuts) { checkCallerIsSystem(); Preconditions.checkStringNotEmpty(pkg); Loading services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +169 −1 Original line number Diff line number Diff line Loading @@ -9926,6 +9926,174 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { assertEquals(PRIORITY_CATEGORY_CALLS, actual); } @Test public void testRestoreConversationChannel_deleted() throws Exception { // Create parent channel when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false); final NotificationChannel originalChannel = new NotificationChannel("id", "name", IMPORTANCE_DEFAULT); NotificationChannel parentChannel = parcelAndUnparcel(originalChannel, NotificationChannel.CREATOR); assertEquals(originalChannel, parentChannel); mBinderService.createNotificationChannels(PKG, new ParceledListSlice(Arrays.asList(parentChannel))); //Create deleted conversation channel mBinderService.createConversationNotificationChannelForPackage( PKG, mUid, parentChannel, VALID_CONVO_SHORTCUT_ID); final NotificationChannel conversationChannel = mBinderService.getConversationNotificationChannel( PKG, mUserId, PKG, originalChannel.getId(), false, VALID_CONVO_SHORTCUT_ID); conversationChannel.setDeleted(true); //Create notification record Notification.Builder nb = getMessageStyleNotifBuilder(false /* addDefaultMetadata */, null /* groupKey */, false /* isSummary */); nb.setShortcutId(VALID_CONVO_SHORTCUT_ID); nb.setChannelId(originalChannel.getId()); StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, "tag", mUid, 0, nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); NotificationRecord nr = new NotificationRecord(mContext, sbn, originalChannel); assertThat(nr.getChannel()).isEqualTo(originalChannel); mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); waitForIdle(); // Verify that the channel was changed to the conversation channel and restored assertThat(mService.getNotificationRecord(nr.getKey()).isConversation()).isTrue(); assertThat(mService.getNotificationRecord(nr.getKey()).getChannel()).isEqualTo( conversationChannel); assertThat(mService.getNotificationRecord(nr.getKey()).getChannel().isDeleted()).isFalse(); assertThat(mService.getNotificationRecord(nr.getKey()).getChannel().getDeletedTimeMs()) .isEqualTo(-1); } @Test public void testDoNotRestoreParentChannel_deleted() throws Exception { // Create parent channel and set as deleted when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false); final NotificationChannel originalChannel = new NotificationChannel("id", "name", IMPORTANCE_DEFAULT); NotificationChannel parentChannel = parcelAndUnparcel(originalChannel, NotificationChannel.CREATOR); assertEquals(originalChannel, parentChannel); mBinderService.createNotificationChannels(PKG, new ParceledListSlice(Arrays.asList(parentChannel))); parentChannel.setDeleted(true); //Create notification record Notification.Builder nb = getMessageStyleNotifBuilder(false /* addDefaultMetadata */, null /* groupKey */, false /* isSummary */); nb.setShortcutId(VALID_CONVO_SHORTCUT_ID); nb.setChannelId(originalChannel.getId()); StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, "tag", mUid, 0, nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); NotificationRecord nr = new NotificationRecord(mContext, sbn, originalChannel); assertThat(nr.getChannel()).isEqualTo(originalChannel); when(mPermissionHelper.hasPermission(mUid)).thenReturn(true); mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); waitForIdle(); // Verify that the channel was not restored and the notification was not posted assertThat(mService.mChannelToastsSent).contains(mUid); assertThat(mService.getNotificationRecord(nr.getKey())).isNull(); assertThat(parentChannel.isDeleted()).isTrue(); } @Test public void testEnqueueToConversationChannel_notDeleted_doesNotRestore() throws Exception { TestableNotificationManagerService service = spy(mService); PreferencesHelper preferencesHelper = spy(mService.mPreferencesHelper); service.setPreferencesHelper(preferencesHelper); // Create parent channel when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false); final NotificationChannel originalChannel = new NotificationChannel("id", "name", IMPORTANCE_DEFAULT); NotificationChannel parentChannel = parcelAndUnparcel(originalChannel, NotificationChannel.CREATOR); assertEquals(originalChannel, parentChannel); mBinderService.createNotificationChannels(PKG, new ParceledListSlice(Arrays.asList(parentChannel))); //Create conversation channel mBinderService.createConversationNotificationChannelForPackage( PKG, mUid, parentChannel, VALID_CONVO_SHORTCUT_ID); final NotificationChannel conversationChannel = mBinderService.getConversationNotificationChannel( PKG, mUserId, PKG, originalChannel.getId(), false, VALID_CONVO_SHORTCUT_ID); //Create notification record Notification.Builder nb = getMessageStyleNotifBuilder(false /* addDefaultMetadata */, null /* groupKey */, false /* isSummary */); nb.setShortcutId(VALID_CONVO_SHORTCUT_ID); nb.setChannelId(originalChannel.getId()); StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, "tag", mUid, 0, nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); NotificationRecord nr = new NotificationRecord(mContext, sbn, originalChannel); assertThat(nr.getChannel()).isEqualTo(originalChannel); mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); waitForIdle(); // Verify that the channel was changed to the conversation channel and not restored assertThat(service.getNotificationRecord(nr.getKey()).isConversation()).isTrue(); assertThat(service.getNotificationRecord(nr.getKey()).getChannel()).isEqualTo( conversationChannel); verify(service, never()).handleSavePolicyFile(); verify(preferencesHelper, never()).createNotificationChannel(anyString(), anyInt(), any(), anyBoolean(), anyBoolean(), anyInt(), anyBoolean()); } @Test public void testEnqueueToParentChannel_notDeleted_doesNotRestore() throws Exception { TestableNotificationManagerService service = spy(mService); PreferencesHelper preferencesHelper = spy(mService.mPreferencesHelper); service.setPreferencesHelper(preferencesHelper); // Create parent channel when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false); final NotificationChannel originalChannel = new NotificationChannel("id", "name", IMPORTANCE_DEFAULT); NotificationChannel parentChannel = parcelAndUnparcel(originalChannel, NotificationChannel.CREATOR); assertEquals(originalChannel, parentChannel); mBinderService.createNotificationChannels(PKG, new ParceledListSlice(Arrays.asList(parentChannel))); //Create deleted conversation channel mBinderService.createConversationNotificationChannelForPackage( PKG, mUid, parentChannel, VALID_CONVO_SHORTCUT_ID); final NotificationChannel conversationChannel = mBinderService.getConversationNotificationChannel( PKG, mUserId, PKG, originalChannel.getId(), false, VALID_CONVO_SHORTCUT_ID); //Create notification record without a shortcutId Notification.Builder nb = getMessageStyleNotifBuilder(false /* addDefaultMetadata */, null /* groupKey */, false /* isSummary */); nb.setShortcutId(null); nb.setChannelId(originalChannel.getId()); StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, "tag", mUid, 0, nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); NotificationRecord nr = new NotificationRecord(mContext, sbn, originalChannel); assertThat(nr.getChannel()).isEqualTo(originalChannel); mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); waitForIdle(); // Verify that the channel is the parent channel and no channel was restored //assertThat(service.getNotificationRecord(nr.getKey()).isConversation()).isFalse(); assertThat(service.getNotificationRecord(nr.getKey()).getChannel()).isEqualTo( parentChannel); verify(service, never()).handleSavePolicyFile(); verify(preferencesHelper, never()).createNotificationChannel(anyString(), anyInt(), any(), anyBoolean(), anyBoolean(), anyInt(), anyBoolean()); } @Test public void testGetConversationsForPackage_hasShortcut() throws Exception { mService.setPreferencesHelper(mPreferencesHelper); Loading Loading
services/core/java/com/android/server/notification/NotificationManagerService.java +31 −3 Original line number Diff line number Diff line Loading @@ -7042,9 +7042,8 @@ public class NotificationManagerService extends SystemService { channelId = (new Notification.TvExtender(notification)).getChannelId(); } String shortcutId = n.getShortcutId(); final NotificationChannel channel = mPreferencesHelper.getConversationNotificationChannel( pkg, notificationUid, channelId, shortcutId, true /* parent ok */, false /* includeDeleted */); final NotificationChannel channel = getNotificationChannelRestoreDeleted(pkg, callingUid, notificationUid, channelId, shortcutId); if (channel == null) { final String noChannelStr = "No Channel found for " + "pkg=" + pkg Loading Loading @@ -7162,6 +7161,35 @@ public class NotificationManagerService extends SystemService { return true; } /** * Returns a channel, if exists, and restores deleted conversation channels. */ @Nullable private NotificationChannel getNotificationChannelRestoreDeleted(String pkg, int callingUid, int notificationUid, String channelId, String conversationId) { // Restore a deleted conversation channel, if exists. Otherwise use the parent channel. NotificationChannel channel = mPreferencesHelper.getConversationNotificationChannel( pkg, notificationUid, channelId, conversationId, true /* parent ok */, !TextUtils.isEmpty(conversationId) /* includeDeleted */); // Restore deleted conversation channel if (channel != null && channel.isDeleted()) { if (Objects.equals(conversationId, channel.getConversationId())) { boolean needsPolicyFileChange = mPreferencesHelper.createNotificationChannel( pkg, notificationUid, channel, true /* fromTargetApp */, mConditionProviders.isPackageOrComponentAllowed(pkg, UserHandle.getUserId(notificationUid)), callingUid, true); // Update policy file if the conversation channel was restored if (needsPolicyFileChange) { handleSavePolicyFile(); } } else { // Do not restore parent channel channel = null; } } return channel; } private void onConversationRemovedInternal(String pkg, int uid, Set<String> shortcuts) { checkCallerIsSystem(); Preconditions.checkStringNotEmpty(pkg); Loading
services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +169 −1 Original line number Diff line number Diff line Loading @@ -9926,6 +9926,174 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { assertEquals(PRIORITY_CATEGORY_CALLS, actual); } @Test public void testRestoreConversationChannel_deleted() throws Exception { // Create parent channel when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false); final NotificationChannel originalChannel = new NotificationChannel("id", "name", IMPORTANCE_DEFAULT); NotificationChannel parentChannel = parcelAndUnparcel(originalChannel, NotificationChannel.CREATOR); assertEquals(originalChannel, parentChannel); mBinderService.createNotificationChannels(PKG, new ParceledListSlice(Arrays.asList(parentChannel))); //Create deleted conversation channel mBinderService.createConversationNotificationChannelForPackage( PKG, mUid, parentChannel, VALID_CONVO_SHORTCUT_ID); final NotificationChannel conversationChannel = mBinderService.getConversationNotificationChannel( PKG, mUserId, PKG, originalChannel.getId(), false, VALID_CONVO_SHORTCUT_ID); conversationChannel.setDeleted(true); //Create notification record Notification.Builder nb = getMessageStyleNotifBuilder(false /* addDefaultMetadata */, null /* groupKey */, false /* isSummary */); nb.setShortcutId(VALID_CONVO_SHORTCUT_ID); nb.setChannelId(originalChannel.getId()); StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, "tag", mUid, 0, nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); NotificationRecord nr = new NotificationRecord(mContext, sbn, originalChannel); assertThat(nr.getChannel()).isEqualTo(originalChannel); mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); waitForIdle(); // Verify that the channel was changed to the conversation channel and restored assertThat(mService.getNotificationRecord(nr.getKey()).isConversation()).isTrue(); assertThat(mService.getNotificationRecord(nr.getKey()).getChannel()).isEqualTo( conversationChannel); assertThat(mService.getNotificationRecord(nr.getKey()).getChannel().isDeleted()).isFalse(); assertThat(mService.getNotificationRecord(nr.getKey()).getChannel().getDeletedTimeMs()) .isEqualTo(-1); } @Test public void testDoNotRestoreParentChannel_deleted() throws Exception { // Create parent channel and set as deleted when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false); final NotificationChannel originalChannel = new NotificationChannel("id", "name", IMPORTANCE_DEFAULT); NotificationChannel parentChannel = parcelAndUnparcel(originalChannel, NotificationChannel.CREATOR); assertEquals(originalChannel, parentChannel); mBinderService.createNotificationChannels(PKG, new ParceledListSlice(Arrays.asList(parentChannel))); parentChannel.setDeleted(true); //Create notification record Notification.Builder nb = getMessageStyleNotifBuilder(false /* addDefaultMetadata */, null /* groupKey */, false /* isSummary */); nb.setShortcutId(VALID_CONVO_SHORTCUT_ID); nb.setChannelId(originalChannel.getId()); StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, "tag", mUid, 0, nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); NotificationRecord nr = new NotificationRecord(mContext, sbn, originalChannel); assertThat(nr.getChannel()).isEqualTo(originalChannel); when(mPermissionHelper.hasPermission(mUid)).thenReturn(true); mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); waitForIdle(); // Verify that the channel was not restored and the notification was not posted assertThat(mService.mChannelToastsSent).contains(mUid); assertThat(mService.getNotificationRecord(nr.getKey())).isNull(); assertThat(parentChannel.isDeleted()).isTrue(); } @Test public void testEnqueueToConversationChannel_notDeleted_doesNotRestore() throws Exception { TestableNotificationManagerService service = spy(mService); PreferencesHelper preferencesHelper = spy(mService.mPreferencesHelper); service.setPreferencesHelper(preferencesHelper); // Create parent channel when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false); final NotificationChannel originalChannel = new NotificationChannel("id", "name", IMPORTANCE_DEFAULT); NotificationChannel parentChannel = parcelAndUnparcel(originalChannel, NotificationChannel.CREATOR); assertEquals(originalChannel, parentChannel); mBinderService.createNotificationChannels(PKG, new ParceledListSlice(Arrays.asList(parentChannel))); //Create conversation channel mBinderService.createConversationNotificationChannelForPackage( PKG, mUid, parentChannel, VALID_CONVO_SHORTCUT_ID); final NotificationChannel conversationChannel = mBinderService.getConversationNotificationChannel( PKG, mUserId, PKG, originalChannel.getId(), false, VALID_CONVO_SHORTCUT_ID); //Create notification record Notification.Builder nb = getMessageStyleNotifBuilder(false /* addDefaultMetadata */, null /* groupKey */, false /* isSummary */); nb.setShortcutId(VALID_CONVO_SHORTCUT_ID); nb.setChannelId(originalChannel.getId()); StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, "tag", mUid, 0, nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); NotificationRecord nr = new NotificationRecord(mContext, sbn, originalChannel); assertThat(nr.getChannel()).isEqualTo(originalChannel); mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); waitForIdle(); // Verify that the channel was changed to the conversation channel and not restored assertThat(service.getNotificationRecord(nr.getKey()).isConversation()).isTrue(); assertThat(service.getNotificationRecord(nr.getKey()).getChannel()).isEqualTo( conversationChannel); verify(service, never()).handleSavePolicyFile(); verify(preferencesHelper, never()).createNotificationChannel(anyString(), anyInt(), any(), anyBoolean(), anyBoolean(), anyInt(), anyBoolean()); } @Test public void testEnqueueToParentChannel_notDeleted_doesNotRestore() throws Exception { TestableNotificationManagerService service = spy(mService); PreferencesHelper preferencesHelper = spy(mService.mPreferencesHelper); service.setPreferencesHelper(preferencesHelper); // Create parent channel when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false); final NotificationChannel originalChannel = new NotificationChannel("id", "name", IMPORTANCE_DEFAULT); NotificationChannel parentChannel = parcelAndUnparcel(originalChannel, NotificationChannel.CREATOR); assertEquals(originalChannel, parentChannel); mBinderService.createNotificationChannels(PKG, new ParceledListSlice(Arrays.asList(parentChannel))); //Create deleted conversation channel mBinderService.createConversationNotificationChannelForPackage( PKG, mUid, parentChannel, VALID_CONVO_SHORTCUT_ID); final NotificationChannel conversationChannel = mBinderService.getConversationNotificationChannel( PKG, mUserId, PKG, originalChannel.getId(), false, VALID_CONVO_SHORTCUT_ID); //Create notification record without a shortcutId Notification.Builder nb = getMessageStyleNotifBuilder(false /* addDefaultMetadata */, null /* groupKey */, false /* isSummary */); nb.setShortcutId(null); nb.setChannelId(originalChannel.getId()); StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, "tag", mUid, 0, nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); NotificationRecord nr = new NotificationRecord(mContext, sbn, originalChannel); assertThat(nr.getChannel()).isEqualTo(originalChannel); mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(), nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); waitForIdle(); // Verify that the channel is the parent channel and no channel was restored //assertThat(service.getNotificationRecord(nr.getKey()).isConversation()).isFalse(); assertThat(service.getNotificationRecord(nr.getKey()).getChannel()).isEqualTo( parentChannel); verify(service, never()).handleSavePolicyFile(); verify(preferencesHelper, never()).createNotificationChannel(anyString(), anyInt(), any(), anyBoolean(), anyBoolean(), anyInt(), anyBoolean()); } @Test public void testGetConversationsForPackage_hasShortcut() throws Exception { mService.setPreferencesHelper(mPreferencesHelper); Loading