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

Commit 9d5a97fa authored by Valentin Iftime's avatar Valentin Iftime Committed by Iavor-Valentin Iftime
Browse files

Use valid auto-group notification trigger key for sparse groups

 When force grouping sparse groups, if the triggering notification is a summary,
  it will be removed and using it as the triggering notification will result in a NPE.
 Use another (first valid child) notification as the trigger in this case.

Flag: com.android.server.notification.notification_force_group_singletons
Test: atest GroupHelperTest

Bug: 366204575
Change-Id: I31e27a0130d58cd08a24f7db4f6fd44977c22abf
parent e6a46578
Loading
Loading
Loading
Loading
+11 −2
Original line number Original line Diff line number Diff line
@@ -1197,6 +1197,11 @@ public class GroupHelper {
            final ArrayMap<String, NotificationAttributes> aggregatedNotificationsAttrs =
            final ArrayMap<String, NotificationAttributes> aggregatedNotificationsAttrs =
                    mAggregatedNotifications.getOrDefault(fullAggregateGroupKey, new ArrayMap<>());
                    mAggregatedNotifications.getOrDefault(fullAggregateGroupKey, new ArrayMap<>());
            final boolean hasSummary = !aggregatedNotificationsAttrs.isEmpty();
            final boolean hasSummary = !aggregatedNotificationsAttrs.isEmpty();
            String triggeringKey = null;
            if (!record.getNotification().isGroupSummary()) {
                // Use this record as triggeringKey only if not a group summary (will be removed)
                triggeringKey = record.getKey();
            }
            for (NotificationRecord r : notificationList) {
            for (NotificationRecord r : notificationList) {
                // Add notifications for detected sparse groups
                // Add notifications for detected sparse groups
                if (sparseGroupSummaries.containsKey(r.getGroupKey())) {
                if (sparseGroupSummaries.containsKey(r.getGroupKey())) {
@@ -1213,6 +1218,10 @@ public class GroupHelper {
                                r.getNotification().getGroupAlertBehavior(),
                                r.getNotification().getGroupAlertBehavior(),
                                r.getChannel().getId()));
                                r.getChannel().getId()));


                        // Pick the first valid triggeringKey
                        if (triggeringKey == null) {
                            triggeringKey = r.getKey();
                        }
                    } else if (r.getNotification().isGroupSummary()) {
                    } else if (r.getNotification().isGroupSummary()) {
                        // Remove summary notifications
                        // Remove summary notifications
                        if (DEBUG) {
                        if (DEBUG) {
@@ -1235,7 +1244,7 @@ public class GroupHelper {


            mAggregatedNotifications.put(fullAggregateGroupKey, aggregatedNotificationsAttrs);
            mAggregatedNotifications.put(fullAggregateGroupKey, aggregatedNotificationsAttrs);
            // add/update aggregate summary
            // add/update aggregate summary
            updateAggregateAppGroup(fullAggregateGroupKey, record.getKey(), hasSummary,
            updateAggregateAppGroup(fullAggregateGroupKey, triggeringKey, hasSummary,
                    sectioner.mSummaryId);
                    sectioner.mSummaryId);


            //cleanup mUngroupedAbuseNotifications
            //cleanup mUngroupedAbuseNotifications
+55 −2
Original line number Original line Diff line number Diff line
@@ -2465,6 +2465,7 @@ public class GroupHelperTest extends UiServiceTestCase {
        final String pkg = "package";
        final String pkg = "package";
        final String expectedGroupKey = GroupHelper.getFullAggregateGroupKey(pkg,
        final String expectedGroupKey = GroupHelper.getFullAggregateGroupKey(pkg,
            AGGREGATE_GROUP_KEY + "AlertingSection", UserHandle.SYSTEM.getIdentifier());
            AGGREGATE_GROUP_KEY + "AlertingSection", UserHandle.SYSTEM.getIdentifier());
        String expectedTriggeringKey = null;
        // Post singleton groups, above forced group limit
        // Post singleton groups, above forced group limit
        for (int i = 0; i < AUTOGROUP_SINGLETONS_AT_COUNT; i++) {
        for (int i = 0; i < AUTOGROUP_SINGLETONS_AT_COUNT; i++) {
            NotificationRecord summary = getNotificationRecord(pkg, i,
            NotificationRecord summary = getNotificationRecord(pkg, i,
@@ -2473,15 +2474,67 @@ public class GroupHelperTest extends UiServiceTestCase {
            NotificationRecord child = getNotificationRecord(pkg, i + 42,
            NotificationRecord child = getNotificationRecord(pkg, i + 42,
                String.valueOf(i + 42), UserHandle.SYSTEM, "testGrp "+i, false);
                String.valueOf(i + 42), UserHandle.SYSTEM, "testGrp "+i, false);
            notificationList.add(child);
            notificationList.add(child);
            expectedTriggeringKey = child.getKey();
            summaryByGroup.put(summary.getGroupKey(), summary);
            summaryByGroup.put(summary.getGroupKey(), summary);
            mGroupHelper.onNotificationPostedWithDelay(child, notificationList, summaryByGroup);
            mGroupHelper.onNotificationPostedWithDelay(child, notificationList, summaryByGroup);
            summary.isCanceled = true;  // simulate removing the app summary
            summary.isCanceled = true;  // simulate removing the app summary
            mGroupHelper.onNotificationPostedWithDelay(summary, notificationList, summaryByGroup);
            mGroupHelper.onNotificationPostedWithDelay(summary, notificationList, summaryByGroup);
        }
        // Check that notifications are forced grouped
        verify(mCallback, times(1)).addAutoGroupSummary(anyInt(), eq(pkg),
                eq(expectedTriggeringKey), eq(expectedGroupKey), anyInt(),
                eq(getNotificationAttributes(BASE_FLAGS)));
        verify(mCallback, times(AUTOGROUP_SINGLETONS_AT_COUNT)).addAutoGroup(anyString(),
                eq(expectedGroupKey), eq(true));
        verify(mCallback, never()).removeAutoGroup(anyString());
        verify(mCallback, never()).removeAutoGroupSummary(anyInt(), anyString(), anyString());
        verify(mCallback, never()).updateAutogroupSummary(anyInt(), anyString(), anyString(),
                any());

        // Check that summaries are canceled
        verify(mCallback, times(AUTOGROUP_SINGLETONS_AT_COUNT)).removeAppProvidedSummary(
                anyString());
    }


    @Test
    @EnableFlags({FLAG_NOTIFICATION_FORCE_GROUPING,
            Flags.FLAG_NOTIFICATION_FORCE_GROUP_SINGLETONS})
    public void testAddAggregateSummary_summaryTriggers_singletonGroups() {
        final List<NotificationRecord> notificationList = new ArrayList<>();
        final ArrayMap<String, NotificationRecord> summaryByGroup = new ArrayMap<>();
        final String pkg = "package";
        final String expectedGroupKey = GroupHelper.getFullAggregateGroupKey(pkg,
                AGGREGATE_GROUP_KEY + "AlertingSection", UserHandle.SYSTEM.getIdentifier());
        final int firstChildIdx = 1;
        // Post singleton groups, below forced group limit
        for (int i = 0; i < AUTOGROUP_SINGLETONS_AT_COUNT - 1; i++) {
            NotificationRecord summary = getNotificationRecord(pkg, i,
                    String.valueOf(i), UserHandle.SYSTEM, "testGrp " + i, true);
            notificationList.add(summary);
            NotificationRecord child = getNotificationRecord(pkg, i + 42,
                    String.valueOf(i + 42), UserHandle.SYSTEM, "testGrp " + i, false);
            notificationList.add(child);
            summaryByGroup.put(summary.getGroupKey(), summary);
            mGroupHelper.onNotificationPostedWithDelay(summary, notificationList, summaryByGroup);
            mGroupHelper.onNotificationPostedWithDelay(child, notificationList, summaryByGroup);
        }
        }

        // Post triggering group summary
        final String expectedTriggeringKey = notificationList.get(firstChildIdx).getKey();
        final int triggerIdx = AUTOGROUP_SINGLETONS_AT_COUNT - 1;
        NotificationRecord summary = getNotificationRecord(pkg, triggerIdx,
                String.valueOf(triggerIdx), UserHandle.SYSTEM, "testGrp " + triggerIdx, true);
        notificationList.add(summary);
        NotificationRecord child = getNotificationRecord(pkg, triggerIdx + 42,
                String.valueOf(triggerIdx + 42), UserHandle.SYSTEM, "testGrp " + triggerIdx, false);
        notificationList.add(child);
        summaryByGroup.put(summary.getGroupKey(), summary);
        mGroupHelper.onNotificationPostedWithDelay(summary, notificationList, summaryByGroup);

        // Check that notifications are forced grouped
        // Check that notifications are forced grouped
        verify(mCallback, times(1)).addAutoGroupSummary(anyInt(), eq(pkg), anyString(),
        verify(mCallback, times(1)).addAutoGroupSummary(anyInt(), eq(pkg),
                eq(expectedGroupKey), anyInt(), eq(getNotificationAttributes(BASE_FLAGS)));
                eq(expectedTriggeringKey), eq(expectedGroupKey), anyInt(),
                eq(getNotificationAttributes(BASE_FLAGS)));
        verify(mCallback, times(AUTOGROUP_SINGLETONS_AT_COUNT)).addAutoGroup(anyString(),
        verify(mCallback, times(AUTOGROUP_SINGLETONS_AT_COUNT)).addAutoGroup(anyString(),
                eq(expectedGroupKey), eq(true));
                eq(expectedGroupKey), eq(true));
        verify(mCallback, never()).removeAutoGroup(anyString());
        verify(mCallback, never()).removeAutoGroup(anyString());