Loading services/core/java/com/android/server/notification/GroupHelper.java +43 −0 Original line number Diff line number Diff line Loading @@ -1638,6 +1638,49 @@ public class GroupHelper { return numChildren; } /** * Checks if all the group child notifications have been bundled * (and if the summary alert should be muted) * @return if the all children have been bundled */ protected boolean isSummaryWithAllChildrenBundled(final NotificationRecord summary, final List<NotificationRecord> postedNotificationsList, final List<NotificationRecord> enqueuedNotificationsList) { // Skip aggregate groups because the summary has GROUP_ALERT_CHILDREN flag if (isAggregatedGroup(summary)) { return false; } if (!summary.getNotification().isGroupSummary()) { return false; } final String groupKey = summary.getSbn().getGroup(); int numChildren = 0; int numBundledChildren = 0; // Find all posted children for this summary for (NotificationRecord r : postedNotificationsList) { if (!r.getNotification().isGroupSummary() && groupKey.equals(r.getSbn().getGroup())) { numChildren++; if (isInBundleSection(r)) { numBundledChildren++; } } } // Find all enqueued children for this summary for (NotificationRecord r : enqueuedNotificationsList) { if (!r.getNotification().isGroupSummary() && groupKey.equals(r.getSbn().getGroup())) { numChildren++; if (isInBundleSection(r)) { numBundledChildren++; } } } return (numChildren > 0 && numBundledChildren == numChildren); } private static boolean isGroupSummaryWithoutChildren(final NotificationRecord record, final List<NotificationRecord> notificationList) { final StatusBarNotification sbn = record.getSbn(); Loading services/core/java/com/android/server/notification/NotificationManagerService.java +7 −0 Original line number Diff line number Diff line Loading @@ -10293,6 +10293,13 @@ public class NotificationManagerService extends SystemService { int buzzBeepBlinkLoggingCode = 0; if (!r.isHidden()) { if (notificationClassification()) { if (mGroupHelper.isSummaryWithAllChildrenBundled(r, mNotificationList, mEnqueuedNotifications)) { notification.flags |= Notification.FLAG_SILENT; } } buzzBeepBlinkLoggingCode = mAttentionHelper.buzzBeepBlinkLocked(r, new NotificationAttentionHelper.Signals( mUserProfiles.isCurrentProfile(r.getUserId()), Loading services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +115 −0 Original line number Diff line number Diff line Loading @@ -44,6 +44,7 @@ import static android.app.Notification.FLAG_NO_DISMISS; import static android.app.Notification.FLAG_ONGOING_EVENT; import static android.app.Notification.FLAG_ONLY_ALERT_ONCE; import static android.app.Notification.FLAG_PROMOTED_ONGOING; import static android.app.Notification.FLAG_SILENT; import static android.app.Notification.FLAG_USER_INITIATED_JOB; import static android.app.Notification.GROUP_ALERT_CHILDREN; import static android.app.Notification.VISIBILITY_PRIVATE; Loading Loading @@ -19900,6 +19901,120 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { assertThat(disabledUserIds.getValue()).containsExactly(mUserId, 111); } @Test @EnableFlags(FLAG_NOTIFICATION_CLASSIFICATION) public void testNoChildrenYet_summaryNotSilent() throws Exception { // Post summary final String originalGroupName = "originalGroup"; final int summaryId = 0; final NotificationRecord summary = generateNotificationRecord(mTestNotificationChannel, summaryId, originalGroupName, true); mService.addEnqueuedNotification(summary); mService.new PostNotificationRunnable(summary.getKey(), summary.getSbn().getPackageName(), summary.getUid(), mPostNotificationTrackerFactory.newTracker(null)).run(); waitForIdle(); // Check that the summary does NOT have FLAG_SILENT set NotificationRecord s = mService.findNotificationLocked(summary.getSbn().getPackageName(), summary.getSbn().getTag(), summary.getSbn().getId(), summary.getSbn().getUserId()); assertThat(s).isNotNull(); assertThat(s.getNotification().flags & FLAG_SILENT).isEqualTo(0); } @Test @EnableFlags(FLAG_NOTIFICATION_CLASSIFICATION) public void testSomeChildrenBundled_summaryNotSilent() 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 an enqueued not bundled notification final String originalGroupName = "originalGroup"; final int summaryId = 0; final NotificationRecord r1 = generateNotificationRecord(mTestNotificationChannel, summaryId + 1, originalGroupName, false); mService.addEnqueuedNotification(r1); // And a posted bundled notification final NotificationRecord r2 = generateNotificationRecord(mTestNotificationChannel, summaryId + 2, originalGroupName, false); mService.addNotification(r2); Bundle signals = new Bundle(); signals.putInt(KEY_TYPE, TYPE_PROMOTION); Adjustment adjustment = new Adjustment(r2.getSbn().getPackageName(), r2.getKey(), signals, "", r2.getUser().getIdentifier()); mBinderService.applyAdjustmentFromAssistant(null, adjustment); waitForIdle(); r2.applyAdjustments(); assertThat(r2.getChannel().getId()).isEqualTo(PROMOTIONS_ID); // Post summary final NotificationRecord summary = generateNotificationRecord(mTestNotificationChannel, summaryId, originalGroupName, true); mService.addEnqueuedNotification(summary); mService.new PostNotificationRunnable(summary.getKey(), summary.getSbn().getPackageName(), summary.getUid(), mPostNotificationTrackerFactory.newTracker(null)).run(); waitForIdle(); // Check that the summary does NOT have FLAG_SILENT set NotificationRecord s = mService.findNotificationLocked(summary.getSbn().getPackageName(), summary.getSbn().getTag(), summary.getSbn().getId(), summary.getSbn().getUserId()); assertThat(s).isNotNull(); assertThat(s.getNotification().flags & FLAG_SILENT).isEqualTo(0); } @Test @EnableFlags(FLAG_NOTIFICATION_CLASSIFICATION) public void testAllChildrenBundled_summaryIsSilent() 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 a posted bundled notification and an enqueued bundled notification final String originalGroupName = "originalGroup"; final int summaryId = 0; final NotificationRecord r1 = generateNotificationRecord(mTestNotificationChannel, summaryId + 1, originalGroupName, false); mService.addEnqueuedNotification(r1); Bundle signals = new Bundle(); signals.putInt(KEY_TYPE, TYPE_NEWS); Adjustment adjustment = new Adjustment(r1.getSbn().getPackageName(), r1.getKey(), signals, "", r1.getUser().getIdentifier()); mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment); waitForIdle(); r1.applyAdjustments(); assertThat(r1.getChannel().getId()).isEqualTo(NEWS_ID); final NotificationRecord r2 = generateNotificationRecord(mTestNotificationChannel, summaryId + 2, originalGroupName, false); mService.addNotification(r2); signals.putInt(KEY_TYPE, TYPE_PROMOTION); adjustment = new Adjustment(r2.getSbn().getPackageName(), r2.getKey(), signals, "", r2.getUser().getIdentifier()); mBinderService.applyAdjustmentFromAssistant(null, adjustment); waitForIdle(); r2.applyAdjustments(); assertThat(r2.getChannel().getId()).isEqualTo(PROMOTIONS_ID); // Post summary final NotificationRecord summary = generateNotificationRecord(mTestNotificationChannel, summaryId, originalGroupName, true); mService.addEnqueuedNotification(summary); mService.new PostNotificationRunnable(summary.getKey(), summary.getSbn().getPackageName(), summary.getUid(), mPostNotificationTrackerFactory.newTracker(null)).run(); waitForIdle(); // Check that the summary has FLAG_SILENT set NotificationRecord s = mService.findNotificationLocked(summary.getSbn().getPackageName(), summary.getSbn().getTag(), summary.getSbn().getId(), summary.getSbn().getUserId()); assertThat(s).isNotNull(); assertThat(s.getNotification().flags & FLAG_SILENT).isEqualTo(FLAG_SILENT); } @Test @EnableFlags({FLAG_NM_SUMMARIZATION}) public void testDisableBundleAdjustment_unsummarizesNotifications() throws Exception { Loading
services/core/java/com/android/server/notification/GroupHelper.java +43 −0 Original line number Diff line number Diff line Loading @@ -1638,6 +1638,49 @@ public class GroupHelper { return numChildren; } /** * Checks if all the group child notifications have been bundled * (and if the summary alert should be muted) * @return if the all children have been bundled */ protected boolean isSummaryWithAllChildrenBundled(final NotificationRecord summary, final List<NotificationRecord> postedNotificationsList, final List<NotificationRecord> enqueuedNotificationsList) { // Skip aggregate groups because the summary has GROUP_ALERT_CHILDREN flag if (isAggregatedGroup(summary)) { return false; } if (!summary.getNotification().isGroupSummary()) { return false; } final String groupKey = summary.getSbn().getGroup(); int numChildren = 0; int numBundledChildren = 0; // Find all posted children for this summary for (NotificationRecord r : postedNotificationsList) { if (!r.getNotification().isGroupSummary() && groupKey.equals(r.getSbn().getGroup())) { numChildren++; if (isInBundleSection(r)) { numBundledChildren++; } } } // Find all enqueued children for this summary for (NotificationRecord r : enqueuedNotificationsList) { if (!r.getNotification().isGroupSummary() && groupKey.equals(r.getSbn().getGroup())) { numChildren++; if (isInBundleSection(r)) { numBundledChildren++; } } } return (numChildren > 0 && numBundledChildren == numChildren); } private static boolean isGroupSummaryWithoutChildren(final NotificationRecord record, final List<NotificationRecord> notificationList) { final StatusBarNotification sbn = record.getSbn(); Loading
services/core/java/com/android/server/notification/NotificationManagerService.java +7 −0 Original line number Diff line number Diff line Loading @@ -10293,6 +10293,13 @@ public class NotificationManagerService extends SystemService { int buzzBeepBlinkLoggingCode = 0; if (!r.isHidden()) { if (notificationClassification()) { if (mGroupHelper.isSummaryWithAllChildrenBundled(r, mNotificationList, mEnqueuedNotifications)) { notification.flags |= Notification.FLAG_SILENT; } } buzzBeepBlinkLoggingCode = mAttentionHelper.buzzBeepBlinkLocked(r, new NotificationAttentionHelper.Signals( mUserProfiles.isCurrentProfile(r.getUserId()), Loading
services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +115 −0 Original line number Diff line number Diff line Loading @@ -44,6 +44,7 @@ import static android.app.Notification.FLAG_NO_DISMISS; import static android.app.Notification.FLAG_ONGOING_EVENT; import static android.app.Notification.FLAG_ONLY_ALERT_ONCE; import static android.app.Notification.FLAG_PROMOTED_ONGOING; import static android.app.Notification.FLAG_SILENT; import static android.app.Notification.FLAG_USER_INITIATED_JOB; import static android.app.Notification.GROUP_ALERT_CHILDREN; import static android.app.Notification.VISIBILITY_PRIVATE; Loading Loading @@ -19900,6 +19901,120 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { assertThat(disabledUserIds.getValue()).containsExactly(mUserId, 111); } @Test @EnableFlags(FLAG_NOTIFICATION_CLASSIFICATION) public void testNoChildrenYet_summaryNotSilent() throws Exception { // Post summary final String originalGroupName = "originalGroup"; final int summaryId = 0; final NotificationRecord summary = generateNotificationRecord(mTestNotificationChannel, summaryId, originalGroupName, true); mService.addEnqueuedNotification(summary); mService.new PostNotificationRunnable(summary.getKey(), summary.getSbn().getPackageName(), summary.getUid(), mPostNotificationTrackerFactory.newTracker(null)).run(); waitForIdle(); // Check that the summary does NOT have FLAG_SILENT set NotificationRecord s = mService.findNotificationLocked(summary.getSbn().getPackageName(), summary.getSbn().getTag(), summary.getSbn().getId(), summary.getSbn().getUserId()); assertThat(s).isNotNull(); assertThat(s.getNotification().flags & FLAG_SILENT).isEqualTo(0); } @Test @EnableFlags(FLAG_NOTIFICATION_CLASSIFICATION) public void testSomeChildrenBundled_summaryNotSilent() 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 an enqueued not bundled notification final String originalGroupName = "originalGroup"; final int summaryId = 0; final NotificationRecord r1 = generateNotificationRecord(mTestNotificationChannel, summaryId + 1, originalGroupName, false); mService.addEnqueuedNotification(r1); // And a posted bundled notification final NotificationRecord r2 = generateNotificationRecord(mTestNotificationChannel, summaryId + 2, originalGroupName, false); mService.addNotification(r2); Bundle signals = new Bundle(); signals.putInt(KEY_TYPE, TYPE_PROMOTION); Adjustment adjustment = new Adjustment(r2.getSbn().getPackageName(), r2.getKey(), signals, "", r2.getUser().getIdentifier()); mBinderService.applyAdjustmentFromAssistant(null, adjustment); waitForIdle(); r2.applyAdjustments(); assertThat(r2.getChannel().getId()).isEqualTo(PROMOTIONS_ID); // Post summary final NotificationRecord summary = generateNotificationRecord(mTestNotificationChannel, summaryId, originalGroupName, true); mService.addEnqueuedNotification(summary); mService.new PostNotificationRunnable(summary.getKey(), summary.getSbn().getPackageName(), summary.getUid(), mPostNotificationTrackerFactory.newTracker(null)).run(); waitForIdle(); // Check that the summary does NOT have FLAG_SILENT set NotificationRecord s = mService.findNotificationLocked(summary.getSbn().getPackageName(), summary.getSbn().getTag(), summary.getSbn().getId(), summary.getSbn().getUserId()); assertThat(s).isNotNull(); assertThat(s.getNotification().flags & FLAG_SILENT).isEqualTo(0); } @Test @EnableFlags(FLAG_NOTIFICATION_CLASSIFICATION) public void testAllChildrenBundled_summaryIsSilent() 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 a posted bundled notification and an enqueued bundled notification final String originalGroupName = "originalGroup"; final int summaryId = 0; final NotificationRecord r1 = generateNotificationRecord(mTestNotificationChannel, summaryId + 1, originalGroupName, false); mService.addEnqueuedNotification(r1); Bundle signals = new Bundle(); signals.putInt(KEY_TYPE, TYPE_NEWS); Adjustment adjustment = new Adjustment(r1.getSbn().getPackageName(), r1.getKey(), signals, "", r1.getUser().getIdentifier()); mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment); waitForIdle(); r1.applyAdjustments(); assertThat(r1.getChannel().getId()).isEqualTo(NEWS_ID); final NotificationRecord r2 = generateNotificationRecord(mTestNotificationChannel, summaryId + 2, originalGroupName, false); mService.addNotification(r2); signals.putInt(KEY_TYPE, TYPE_PROMOTION); adjustment = new Adjustment(r2.getSbn().getPackageName(), r2.getKey(), signals, "", r2.getUser().getIdentifier()); mBinderService.applyAdjustmentFromAssistant(null, adjustment); waitForIdle(); r2.applyAdjustments(); assertThat(r2.getChannel().getId()).isEqualTo(PROMOTIONS_ID); // Post summary final NotificationRecord summary = generateNotificationRecord(mTestNotificationChannel, summaryId, originalGroupName, true); mService.addEnqueuedNotification(summary); mService.new PostNotificationRunnable(summary.getKey(), summary.getSbn().getPackageName(), summary.getUid(), mPostNotificationTrackerFactory.newTracker(null)).run(); waitForIdle(); // Check that the summary has FLAG_SILENT set NotificationRecord s = mService.findNotificationLocked(summary.getSbn().getPackageName(), summary.getSbn().getTag(), summary.getSbn().getId(), summary.getSbn().getUserId()); assertThat(s).isNotNull(); assertThat(s.getNotification().flags & FLAG_SILENT).isEqualTo(FLAG_SILENT); } @Test @EnableFlags({FLAG_NM_SUMMARIZATION}) public void testDisableBundleAdjustment_unsummarizesNotifications() throws Exception {