Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7e12126b authored by Valentin Iftime's avatar Valentin Iftime
Browse files

Check if notification group child is bundled and regroup when posted

 Check if summary & child notifications are not part of the same bundle after posting.
 The check is needed because if the notification was bundled while enqueued,
  NotificationAdjustmentExtractor is bypassed and regrouping is not triggered by GroupHelper#onChannelUpdate.

Flag: android.service.notification.notification_regroup_on_classification
Test: atest GroupHelperTest
Bug: 377382403
Change-Id: Ibcc21289bf64854a83422aff0d489dc1f9fe3453
parent 7b433205
Loading
Loading
Loading
Loading
+36 −1
Original line number Diff line number Diff line
@@ -788,6 +788,20 @@ public class GroupHelper {
                return;
            }

            // Check if summary & child notifications are not part of the same section/bundle
            // Needs a check here if notification was bundled while enqueued
            if (notificationRegroupOnClassification()
                    && android.service.notification.Flags.notificationClassification()) {
                if (isGroupChildBundled(record, summaryByGroupKey)) {
                    if (DEBUG) {
                        Slog.v(TAG, "isGroupChildInDifferentBundleThanSummary: " + record);
                    }
                    moveNotificationsToNewSection(record.getUserId(), pkgName,
                            List.of(new NotificationMoveOp(record, null, fullAggregateGroupKey)));
                    return;
                }
            }

            // scenario 3: sparse/singleton groups
            if (Flags.notificationForceGroupSingletons()) {
                try {
@@ -800,6 +814,27 @@ public class GroupHelper {
        }
    }

    private static boolean isGroupChildBundled(final NotificationRecord record,
            final Map<String, NotificationRecord> summaryByGroupKey) {
        final StatusBarNotification sbn = record.getSbn();
        final String groupKey = record.getSbn().getGroupKey();

        if (!sbn.isAppGroup()) {
            return false;
        }

        if (record.getNotification().isGroupSummary()) {
            return false;
        }

        final NotificationRecord summary = summaryByGroupKey.get(groupKey);
        if (summary == null) {
            return false;
        }

        return NotificationChannel.SYSTEM_RESERVED_IDS.contains(record.getChannel().getId());
    }

    /**
     * Called when a notification is removed, so that this helper can adjust the aggregate groups:
     *  - Removes the autogroup summary of the notification's section
@@ -1598,7 +1633,7 @@ public class GroupHelper {
        final int mSummaryId;
        private final Predicate<NotificationRecord> mSectionChecker;

        public NotificationSectioner(String name, int summaryId,
        private NotificationSectioner(String name, int summaryId,
                Predicate<NotificationRecord> sectionChecker) {
            mName = name;
            mSummaryId = summaryId;
+66 −3
Original line number Diff line number Diff line
@@ -2406,11 +2406,13 @@ public class GroupHelperTest extends UiServiceTestCase {
                NotificationChannel.NEWS_ID);
        for (NotificationRecord record: notificationList) {
            if (record.getChannel().getId().equals(channel1.getId())
                    && record.getNotification().isGroupChild()
                    && record.getSbn().getId() % 2 == 0) {
                record.updateNotificationChannel(socialChannel);
                mGroupHelper.onChannelUpdated(record);
            }
            if (record.getChannel().getId().equals(channel1.getId())
                    && record.getNotification().isGroupChild()
                    && record.getSbn().getId() % 2 != 0) {
                record.updateNotificationChannel(newsChannel);
                mGroupHelper.onChannelUpdated(record);
@@ -2468,7 +2470,8 @@ public class GroupHelperTest extends UiServiceTestCase {
                NotificationChannel.SOCIAL_MEDIA_ID, NotificationChannel.SOCIAL_MEDIA_ID,
                IMPORTANCE_DEFAULT);
        for (NotificationRecord record: notificationList) {
            if (record.getChannel().getId().equals(channel1.getId())) {
            if (record.getChannel().getId().equals(channel1.getId())
                    && record.getNotification().isGroupChild()) {
                record.updateNotificationChannel(socialChannel);
                mGroupHelper.onChannelUpdated(record);
            }
@@ -2525,7 +2528,8 @@ public class GroupHelperTest extends UiServiceTestCase {
                BASE_FLAGS, mSmallIcon, COLOR_DEFAULT, DEFAULT_VISIBILITY, DEFAULT_GROUP_ALERT,
                NotificationChannel.SOCIAL_MEDIA_ID);
        for (NotificationRecord record: notificationList) {
            if (record.getOriginalGroupKey().contains("testGrp")) {
            if (record.getOriginalGroupKey().contains("testGrp")
                    && record.getNotification().isGroupChild()) {
                record.updateNotificationChannel(socialChannel);
                mGroupHelper.onChannelUpdated(record);
            }
@@ -2623,7 +2627,8 @@ public class GroupHelperTest extends UiServiceTestCase {
                BASE_FLAGS, mSmallIcon, COLOR_DEFAULT, DEFAULT_VISIBILITY, DEFAULT_GROUP_ALERT,
                NotificationChannel.SOCIAL_MEDIA_ID);
        for (NotificationRecord record: notificationList) {
            if (record.getOriginalGroupKey().contains("testGrp")) {
            if (record.getOriginalGroupKey().contains("testGrp")
                    && record.getNotification().isGroupChild()) {
                record.updateNotificationChannel(socialChannel);
                mGroupHelper.onChannelUpdated(record);
            }
@@ -2641,6 +2646,64 @@ public class GroupHelperTest extends UiServiceTestCase {
                anyString(), anyString(), any());
    }

    @Test
    @EnableFlags({FLAG_NOTIFICATION_FORCE_GROUPING,
            FLAG_NOTIFICATION_REGROUP_ON_CLASSIFICATION,
            FLAG_NOTIFICATION_CLASSIFICATION})
    public void testValidGroupsRegrouped_notificationBundledWhileEnqueued() {
        // Check that valid group notifications are regrouped if classification is done
        // before onNotificationPostedWithDelay (within DELAY_FOR_ASSISTANT_TIME)
        final List<NotificationRecord> notificationList = new ArrayList<>();
        final ArrayMap<String, NotificationRecord> summaryByGroup = new ArrayMap<>();
        final String pkg = "package";

        final int summaryId = 0;
        final int numChildren = 3;
        // Post a regular/valid group: summary + notifications
        NotificationRecord summary = getNotificationRecord(pkg, summaryId,
                String.valueOf(summaryId), UserHandle.SYSTEM, "testGrp", true);
        notificationList.add(summary);
        summaryByGroup.put(summary.getGroupKey(), summary);
        for (int i = 0; i < numChildren; i++) {
            NotificationRecord child = getNotificationRecord(pkg, i + 42, String.valueOf(i + 42),
                    UserHandle.SYSTEM, "testGrp", false);
            notificationList.add(child);
        }

        // Classify/bundle child notifications. Don't call onChannelUpdated,
        // adjustments applied while enqueued will use NotificationAdjustmentExtractor.
        final NotificationChannel socialChannel = new NotificationChannel(
                NotificationChannel.SOCIAL_MEDIA_ID, NotificationChannel.SOCIAL_MEDIA_ID,
                IMPORTANCE_DEFAULT);
        final String expectedGroupKey_social = GroupHelper.getFullAggregateGroupKey(pkg,
                AGGREGATE_GROUP_KEY + "SocialSection", UserHandle.SYSTEM.getIdentifier());
        final NotificationAttributes expectedSummaryAttr_social = new NotificationAttributes(
                BASE_FLAGS, mSmallIcon, COLOR_DEFAULT, DEFAULT_VISIBILITY, DEFAULT_GROUP_ALERT,
                NotificationChannel.SOCIAL_MEDIA_ID);
        for (NotificationRecord record: notificationList) {
            if (record.getOriginalGroupKey().contains("testGrp")
                    && record.getNotification().isGroupChild()) {
                record.updateNotificationChannel(socialChannel);
            }
        }

        // Check that notifications are forced grouped and app-provided summaries are canceled
        for (NotificationRecord record: notificationList) {
            mGroupHelper.onNotificationPostedWithDelay(record, notificationList, summaryByGroup);
        }

        verify(mCallback, times(1)).addAutoGroupSummary(anyInt(), eq(pkg), anyString(),
                eq(expectedGroupKey_social), anyInt(), eq(expectedSummaryAttr_social));
        verify(mCallback, times(numChildren)).addAutoGroup(anyString(), eq(expectedGroupKey_social),
                eq(true));
        verify(mCallback, never()).removeAutoGroup(anyString());
        verify(mCallback, never()).removeAutoGroupSummary(anyInt(), anyString(), anyString());
        verify(mCallback, times(numChildren - 1)).updateAutogroupSummary(anyInt(), anyString(),
                anyString(), any());
        verify(mCallback, times(numChildren)).removeAppProvidedSummaryOnClassification(anyString(),
                anyString());
    }

    @Test
    @EnableFlags(FLAG_NOTIFICATION_FORCE_GROUPING)
    public void testMoveAggregateGroups_updateChannel_groupsUngrouped() {