Loading services/core/java/com/android/server/notification/GroupHelper.java +14 −1 Original line number Diff line number Diff line Loading @@ -744,7 +744,7 @@ public class GroupHelper { * * And updates the internal state of un-app-grouped notifications and their flags. * * @return true if the notification was previously auto-grouped * @return true if the notification was previously auto-grouped and was ungrouped by this method */ private boolean maybeUngroupWithSections(NotificationRecord record, @Nullable FullyQualifiedGroupKey fullAggregateGroupKey) { Loading Loading @@ -773,6 +773,19 @@ public class GroupHelper { mAggregatedNotifications.getOrDefault(fullAggregateGroupKey, new ArrayMap<>()); // check if the removed notification was part of the aggregate group if (aggregatedNotificationsAttrs.containsKey(record.getKey())) { // If bundled and the section did not change, do not un-autogroup final NotificationSectioner sectioner = getSection(record); if (sectioner != null && NOTIFICATION_BUNDLE_SECTIONS.contains(sectioner) && fullAggregateGroupKey.equals( FullyQualifiedGroupKey.forRecord(record, sectioner))) { if (DEBUG) { Slog.i(TAG, "Skip removeAutoGroup because bundled: " + record); } maybeUpdateSummaryAttributes(record, fullAggregateGroupKey, sectioner); return false; } aggregatedNotificationsAttrs.remove(sbn.getKey()); mAggregatedNotifications.put(fullAggregateGroupKey, aggregatedNotificationsAttrs); wasUnAggregated = true; Loading services/tests/uiservicestests/src/com/android/server/notification/GroupHelperTest.java +40 −0 Original line number Diff line number Diff line Loading @@ -1043,6 +1043,46 @@ public class GroupHelperTest extends UiServiceTestCase { verify(mCallback, times(1)).removeAutoGroupSummary(anyInt(), anyString(), anyString()); } @Test @EnableFlags({FLAG_NOTIFICATION_FORCE_GROUPING, FLAG_NOTIFICATION_CLASSIFICATION}) public void testAppStartsGroupingBundledNotification_doesNotUnAutogroup() { final String pkg = "package"; final NotificationChannel socialChannel = new NotificationChannel( NotificationChannel.SOCIAL_MEDIA_ID, NotificationChannel.SOCIAL_MEDIA_ID, IMPORTANCE_LOW); final String expectedGroupKey_social = GroupHelper.getFullAggregateGroupKey(pkg, AGGREGATE_GROUP_KEY + "SocialSection", UserHandle.SYSTEM.getIdentifier()); ArrayList<NotificationRecord> posted = new ArrayList<>(); // Post ungrouped bundled notifications to trigger autogrouping for (int i = 0; i < AUTOGROUP_BUNDLES_AT_COUNT; i++) { NotificationRecord r = getNotificationRecord(pkg, i, String.valueOf(i), UserHandle.SYSTEM); r.updateNotificationChannel(socialChannel); posted.add(r); mGroupHelper.onNotificationPosted(r, false); } verify(mCallback, times(1)).addAutoGroupSummary(anyInt(), eq(pkg), anyString(), eq(expectedGroupKey_social), anyInt(), any()); verify(mCallback, times(AUTOGROUP_BUNDLES_AT_COUNT - 1)).addAutoGroup(anyString(), eq(expectedGroupKey_social), anyBoolean()); verify(mCallback, never()).removeAutoGroup(anyString()); verify(mCallback, never()).removeAutoGroupSummary(anyInt(), anyString(), anyString()); Mockito.reset(mCallback); // Set a group name for the notifications (app grouped) and post update for (int i = 0; i < AUTOGROUP_BUNDLES_AT_COUNT; i++) { final NotificationRecord r = getNotificationRecord(pkg, i, String.valueOf(i), UserHandle.SYSTEM, "app group", false); r.getSbn().setOverrideGroupKey(expectedGroupKey_social); r.updateNotificationChannel(socialChannel); mGroupHelper.onNotificationPosted(r, true); } verify(mCallback, never()).removeAutoGroup(anyString()); verify(mCallback, never()).removeAutoGroupSummary(anyInt(), anyString(), anyString()); verify(mCallback, never()).updateAutogroupSummary(anyInt(), anyString(), anyString(), any()); } @Test @EnableFlags({FLAG_NOTIFICATION_FORCE_GROUPING}) public void testNewNotificationsAddedToAutogroup_ifOriginalNotificationsCanceled() { Loading services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +135 −0 Original line number Diff line number Diff line Loading @@ -20454,6 +20454,141 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { assertThat(s.getNotification().flags & FLAG_SILENT).isEqualTo(0); } @Test @EnableFlags(FLAG_NOTIFICATION_CLASSIFICATION) public void testUpdateBundledChild_doesNotUnAutogroup() throws Exception { when(mAssistants.isClassificationTypeAllowed(anyInt(), anyInt())).thenReturn(true); when(mAssistants.isAdjustmentAllowedForPackage(anyInt(), anyString(), anyString())).thenReturn(true); when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true); when(mAssistants.isServiceTokenValidLocked(any())).thenReturn(true); // Post a grouped child notification and bundle it final String originalGroupName = "originalGroup"; final int summaryId = 0; final NotificationRecord nr0 = generateNotificationRecord(mTestNotificationChannel, summaryId, originalGroupName, false); mService.addEnqueuedNotification(nr0); Bundle signals = new Bundle(); signals.putInt(KEY_TYPE, TYPE_NEWS); Adjustment adjustment = new Adjustment(nr0.getSbn().getPackageName(), nr0.getKey(), signals, "", nr0.getUser().getIdentifier()); mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment); waitForIdle(); assertThat(nr0.getChannel().getId()).isEqualTo(NEWS_ID); NotificationManagerService.PostNotificationRunnable runnable = mService.new PostNotificationRunnable(nr0.getKey(), nr0.getSbn().getPackageName(), nr0.getUid(), mPostNotificationTrackerFactory.newTracker(null)); runnable.run(); waitForIdle(); moveTimeForwardAndWaitForIdle(DELAY_FORCE_REGROUP_TIME); nr0.applyAdjustments(); // Check that the notification was autogrouped assertThat(nr0.getSbn().getOverrideGroupKey()).isNotEmpty(); final String fullAggregateGroupKey = nr0.getGroupKey(); NotificationRecord aggregateSummary = mService.mSummaryByGroupKey.get( fullAggregateGroupKey); assertThat(aggregateSummary).isNotNull(); assertThat(aggregateSummary.getSbn().isOngoing()).isFalse(); // Update the notification final NotificationRecord updatedNotification = generateNotificationRecord( mTestNotificationChannel, summaryId, nr0.getSbn().getTag(), originalGroupName, false); updatedNotification.getNotification().flags |= Notification.FLAG_ONGOING_EVENT; updatedNotification.getSbn().setOverrideGroupKey(nr0.getSbn().getOverrideGroupKey()); mService.addEnqueuedNotification(updatedNotification); assertThat(updatedNotification.getGroupKey()).isEqualTo(fullAggregateGroupKey); signals = new Bundle(); signals.putInt(KEY_TYPE, TYPE_NEWS); adjustment = new Adjustment(nr0.getSbn().getPackageName(), nr0.getKey(), signals, "", nr0.getUser().getIdentifier()); mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment); waitForIdle(); runnable = mService.new PostNotificationRunnable(nr0.getKey(), nr0.getSbn().getPackageName(), nr0.getUid(), mPostNotificationTrackerFactory.newTracker(null)); runnable.run(); waitForIdle(); nr0.applyAdjustments(); // Check that the notification has not been un-autogrouped assertThat(aggregateSummary).isNotNull(); assertThat(updatedNotification.getGroupKey()).isEqualTo(fullAggregateGroupKey); moveTimeForwardAndWaitForIdle(DELAY_FORCE_REGROUP_TIME); assertThat(aggregateSummary.getSbn().isOngoing()).isTrue(); } @Test @EnableFlags(FLAG_NOTIFICATION_CLASSIFICATION) public void testUpdateNotBundledChild_doesUnAutogroup() throws Exception { when(mAssistants.isClassificationTypeAllowed(anyInt(), anyInt())).thenReturn(true); when(mAssistants.isAdjustmentAllowedForPackage(anyInt(), anyString(), anyString())).thenReturn(true); when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true); when(mAssistants.isServiceTokenValidLocked(any())).thenReturn(true); // Create a group with 2 children and no summary => force group them final String originalGroupName = "originalGroup"; final int notifId = 0; final NotificationRecord nr0 = generateNotificationRecord(mTestNotificationChannel, notifId, originalGroupName, false); final String originalGroupKey = nr0.getGroupKey(); mService.addEnqueuedNotification(nr0); NotificationManagerService.PostNotificationRunnable runnable = mService.new PostNotificationRunnable(nr0.getKey(), nr0.getSbn().getPackageName(), nr0.getUid(), mPostNotificationTrackerFactory.newTracker(null)); runnable.run(); waitForIdle(); final NotificationRecord nr1 = generateNotificationRecord(mTestNotificationChannel, notifId + 1, originalGroupName, false); mService.addEnqueuedNotification(nr1); runnable = mService.new PostNotificationRunnable(nr1.getKey(), nr1.getSbn().getPackageName(), nr1.getUid(), mPostNotificationTrackerFactory.newTracker(null)); runnable.run(); waitForIdle(); moveTimeForwardAndWaitForIdle(DELAY_FORCE_REGROUP_TIME); nr0.applyAdjustments(); nr1.applyAdjustments(); // Check that the notifications were autogrouped assertThat(nr0.getSbn().getOverrideGroupKey()).isNotEmpty(); assertThat(nr1.getSbn().getOverrideGroupKey()).isNotEmpty(); final String fullAggregateGroupKey = nr0.getGroupKey(); NotificationRecord aggregateSummary = mService.mSummaryByGroupKey.get( fullAggregateGroupKey); assertThat(aggregateSummary).isNotNull(); assertThat(aggregateSummary.getSbn().isOngoing()).isFalse(); // Update the first notification final NotificationRecord updatedNotification = generateNotificationRecord( mTestNotificationChannel, notifId, nr0.getSbn().getTag(), originalGroupName, false); updatedNotification.getNotification().flags |= Notification.FLAG_ONGOING_EVENT; updatedNotification.getSbn().setOverrideGroupKey(nr0.getSbn().getOverrideGroupKey()); mService.addEnqueuedNotification(updatedNotification); assertThat(updatedNotification.getGroupKey()).isEqualTo(fullAggregateGroupKey); runnable = mService.new PostNotificationRunnable(nr0.getKey(), nr0.getSbn().getPackageName(), nr0.getUid(), mPostNotificationTrackerFactory.newTracker(null)); runnable.run(); waitForIdle(); nr0.applyAdjustments(); // Check that it has been un-autogrouped assertThat(aggregateSummary).isNotNull(); assertThat(updatedNotification.getGroupKey()).isEqualTo(originalGroupKey); // And then re-autogrouped after DELAY_FORCE_REGROUP_TIME moveTimeForwardAndWaitForIdle(DELAY_FORCE_REGROUP_TIME); nr0.applyAdjustments(); assertThat(updatedNotification.getGroupKey()).isEqualTo(fullAggregateGroupKey); assertThat(aggregateSummary.getSbn().isOngoing()).isTrue(); } @Test @EnableFlags({FLAG_NM_SUMMARIZATION}) public void testDisableBundleAdjustment_unsummarizesNotifications() throws Exception { Loading
services/core/java/com/android/server/notification/GroupHelper.java +14 −1 Original line number Diff line number Diff line Loading @@ -744,7 +744,7 @@ public class GroupHelper { * * And updates the internal state of un-app-grouped notifications and their flags. * * @return true if the notification was previously auto-grouped * @return true if the notification was previously auto-grouped and was ungrouped by this method */ private boolean maybeUngroupWithSections(NotificationRecord record, @Nullable FullyQualifiedGroupKey fullAggregateGroupKey) { Loading Loading @@ -773,6 +773,19 @@ public class GroupHelper { mAggregatedNotifications.getOrDefault(fullAggregateGroupKey, new ArrayMap<>()); // check if the removed notification was part of the aggregate group if (aggregatedNotificationsAttrs.containsKey(record.getKey())) { // If bundled and the section did not change, do not un-autogroup final NotificationSectioner sectioner = getSection(record); if (sectioner != null && NOTIFICATION_BUNDLE_SECTIONS.contains(sectioner) && fullAggregateGroupKey.equals( FullyQualifiedGroupKey.forRecord(record, sectioner))) { if (DEBUG) { Slog.i(TAG, "Skip removeAutoGroup because bundled: " + record); } maybeUpdateSummaryAttributes(record, fullAggregateGroupKey, sectioner); return false; } aggregatedNotificationsAttrs.remove(sbn.getKey()); mAggregatedNotifications.put(fullAggregateGroupKey, aggregatedNotificationsAttrs); wasUnAggregated = true; Loading
services/tests/uiservicestests/src/com/android/server/notification/GroupHelperTest.java +40 −0 Original line number Diff line number Diff line Loading @@ -1043,6 +1043,46 @@ public class GroupHelperTest extends UiServiceTestCase { verify(mCallback, times(1)).removeAutoGroupSummary(anyInt(), anyString(), anyString()); } @Test @EnableFlags({FLAG_NOTIFICATION_FORCE_GROUPING, FLAG_NOTIFICATION_CLASSIFICATION}) public void testAppStartsGroupingBundledNotification_doesNotUnAutogroup() { final String pkg = "package"; final NotificationChannel socialChannel = new NotificationChannel( NotificationChannel.SOCIAL_MEDIA_ID, NotificationChannel.SOCIAL_MEDIA_ID, IMPORTANCE_LOW); final String expectedGroupKey_social = GroupHelper.getFullAggregateGroupKey(pkg, AGGREGATE_GROUP_KEY + "SocialSection", UserHandle.SYSTEM.getIdentifier()); ArrayList<NotificationRecord> posted = new ArrayList<>(); // Post ungrouped bundled notifications to trigger autogrouping for (int i = 0; i < AUTOGROUP_BUNDLES_AT_COUNT; i++) { NotificationRecord r = getNotificationRecord(pkg, i, String.valueOf(i), UserHandle.SYSTEM); r.updateNotificationChannel(socialChannel); posted.add(r); mGroupHelper.onNotificationPosted(r, false); } verify(mCallback, times(1)).addAutoGroupSummary(anyInt(), eq(pkg), anyString(), eq(expectedGroupKey_social), anyInt(), any()); verify(mCallback, times(AUTOGROUP_BUNDLES_AT_COUNT - 1)).addAutoGroup(anyString(), eq(expectedGroupKey_social), anyBoolean()); verify(mCallback, never()).removeAutoGroup(anyString()); verify(mCallback, never()).removeAutoGroupSummary(anyInt(), anyString(), anyString()); Mockito.reset(mCallback); // Set a group name for the notifications (app grouped) and post update for (int i = 0; i < AUTOGROUP_BUNDLES_AT_COUNT; i++) { final NotificationRecord r = getNotificationRecord(pkg, i, String.valueOf(i), UserHandle.SYSTEM, "app group", false); r.getSbn().setOverrideGroupKey(expectedGroupKey_social); r.updateNotificationChannel(socialChannel); mGroupHelper.onNotificationPosted(r, true); } verify(mCallback, never()).removeAutoGroup(anyString()); verify(mCallback, never()).removeAutoGroupSummary(anyInt(), anyString(), anyString()); verify(mCallback, never()).updateAutogroupSummary(anyInt(), anyString(), anyString(), any()); } @Test @EnableFlags({FLAG_NOTIFICATION_FORCE_GROUPING}) public void testNewNotificationsAddedToAutogroup_ifOriginalNotificationsCanceled() { Loading
services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +135 −0 Original line number Diff line number Diff line Loading @@ -20454,6 +20454,141 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { assertThat(s.getNotification().flags & FLAG_SILENT).isEqualTo(0); } @Test @EnableFlags(FLAG_NOTIFICATION_CLASSIFICATION) public void testUpdateBundledChild_doesNotUnAutogroup() throws Exception { when(mAssistants.isClassificationTypeAllowed(anyInt(), anyInt())).thenReturn(true); when(mAssistants.isAdjustmentAllowedForPackage(anyInt(), anyString(), anyString())).thenReturn(true); when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true); when(mAssistants.isServiceTokenValidLocked(any())).thenReturn(true); // Post a grouped child notification and bundle it final String originalGroupName = "originalGroup"; final int summaryId = 0; final NotificationRecord nr0 = generateNotificationRecord(mTestNotificationChannel, summaryId, originalGroupName, false); mService.addEnqueuedNotification(nr0); Bundle signals = new Bundle(); signals.putInt(KEY_TYPE, TYPE_NEWS); Adjustment adjustment = new Adjustment(nr0.getSbn().getPackageName(), nr0.getKey(), signals, "", nr0.getUser().getIdentifier()); mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment); waitForIdle(); assertThat(nr0.getChannel().getId()).isEqualTo(NEWS_ID); NotificationManagerService.PostNotificationRunnable runnable = mService.new PostNotificationRunnable(nr0.getKey(), nr0.getSbn().getPackageName(), nr0.getUid(), mPostNotificationTrackerFactory.newTracker(null)); runnable.run(); waitForIdle(); moveTimeForwardAndWaitForIdle(DELAY_FORCE_REGROUP_TIME); nr0.applyAdjustments(); // Check that the notification was autogrouped assertThat(nr0.getSbn().getOverrideGroupKey()).isNotEmpty(); final String fullAggregateGroupKey = nr0.getGroupKey(); NotificationRecord aggregateSummary = mService.mSummaryByGroupKey.get( fullAggregateGroupKey); assertThat(aggregateSummary).isNotNull(); assertThat(aggregateSummary.getSbn().isOngoing()).isFalse(); // Update the notification final NotificationRecord updatedNotification = generateNotificationRecord( mTestNotificationChannel, summaryId, nr0.getSbn().getTag(), originalGroupName, false); updatedNotification.getNotification().flags |= Notification.FLAG_ONGOING_EVENT; updatedNotification.getSbn().setOverrideGroupKey(nr0.getSbn().getOverrideGroupKey()); mService.addEnqueuedNotification(updatedNotification); assertThat(updatedNotification.getGroupKey()).isEqualTo(fullAggregateGroupKey); signals = new Bundle(); signals.putInt(KEY_TYPE, TYPE_NEWS); adjustment = new Adjustment(nr0.getSbn().getPackageName(), nr0.getKey(), signals, "", nr0.getUser().getIdentifier()); mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment); waitForIdle(); runnable = mService.new PostNotificationRunnable(nr0.getKey(), nr0.getSbn().getPackageName(), nr0.getUid(), mPostNotificationTrackerFactory.newTracker(null)); runnable.run(); waitForIdle(); nr0.applyAdjustments(); // Check that the notification has not been un-autogrouped assertThat(aggregateSummary).isNotNull(); assertThat(updatedNotification.getGroupKey()).isEqualTo(fullAggregateGroupKey); moveTimeForwardAndWaitForIdle(DELAY_FORCE_REGROUP_TIME); assertThat(aggregateSummary.getSbn().isOngoing()).isTrue(); } @Test @EnableFlags(FLAG_NOTIFICATION_CLASSIFICATION) public void testUpdateNotBundledChild_doesUnAutogroup() throws Exception { when(mAssistants.isClassificationTypeAllowed(anyInt(), anyInt())).thenReturn(true); when(mAssistants.isAdjustmentAllowedForPackage(anyInt(), anyString(), anyString())).thenReturn(true); when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true); when(mAssistants.isServiceTokenValidLocked(any())).thenReturn(true); // Create a group with 2 children and no summary => force group them final String originalGroupName = "originalGroup"; final int notifId = 0; final NotificationRecord nr0 = generateNotificationRecord(mTestNotificationChannel, notifId, originalGroupName, false); final String originalGroupKey = nr0.getGroupKey(); mService.addEnqueuedNotification(nr0); NotificationManagerService.PostNotificationRunnable runnable = mService.new PostNotificationRunnable(nr0.getKey(), nr0.getSbn().getPackageName(), nr0.getUid(), mPostNotificationTrackerFactory.newTracker(null)); runnable.run(); waitForIdle(); final NotificationRecord nr1 = generateNotificationRecord(mTestNotificationChannel, notifId + 1, originalGroupName, false); mService.addEnqueuedNotification(nr1); runnable = mService.new PostNotificationRunnable(nr1.getKey(), nr1.getSbn().getPackageName(), nr1.getUid(), mPostNotificationTrackerFactory.newTracker(null)); runnable.run(); waitForIdle(); moveTimeForwardAndWaitForIdle(DELAY_FORCE_REGROUP_TIME); nr0.applyAdjustments(); nr1.applyAdjustments(); // Check that the notifications were autogrouped assertThat(nr0.getSbn().getOverrideGroupKey()).isNotEmpty(); assertThat(nr1.getSbn().getOverrideGroupKey()).isNotEmpty(); final String fullAggregateGroupKey = nr0.getGroupKey(); NotificationRecord aggregateSummary = mService.mSummaryByGroupKey.get( fullAggregateGroupKey); assertThat(aggregateSummary).isNotNull(); assertThat(aggregateSummary.getSbn().isOngoing()).isFalse(); // Update the first notification final NotificationRecord updatedNotification = generateNotificationRecord( mTestNotificationChannel, notifId, nr0.getSbn().getTag(), originalGroupName, false); updatedNotification.getNotification().flags |= Notification.FLAG_ONGOING_EVENT; updatedNotification.getSbn().setOverrideGroupKey(nr0.getSbn().getOverrideGroupKey()); mService.addEnqueuedNotification(updatedNotification); assertThat(updatedNotification.getGroupKey()).isEqualTo(fullAggregateGroupKey); runnable = mService.new PostNotificationRunnable(nr0.getKey(), nr0.getSbn().getPackageName(), nr0.getUid(), mPostNotificationTrackerFactory.newTracker(null)); runnable.run(); waitForIdle(); nr0.applyAdjustments(); // Check that it has been un-autogrouped assertThat(aggregateSummary).isNotNull(); assertThat(updatedNotification.getGroupKey()).isEqualTo(originalGroupKey); // And then re-autogrouped after DELAY_FORCE_REGROUP_TIME moveTimeForwardAndWaitForIdle(DELAY_FORCE_REGROUP_TIME); nr0.applyAdjustments(); assertThat(updatedNotification.getGroupKey()).isEqualTo(fullAggregateGroupKey); assertThat(aggregateSummary.getSbn().isOngoing()).isTrue(); } @Test @EnableFlags({FLAG_NM_SUMMARIZATION}) public void testDisableBundleAdjustment_unsummarizesNotifications() throws Exception {