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

Commit 3b20644f authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Update autogroup summary on child flag updates" into main

parents 0baf0b44 8c268afa
Loading
Loading
Loading
Loading
+37 −4
Original line number Diff line number Diff line
@@ -604,11 +604,14 @@ public class GroupHelper {
            maybeUngroupOnSectionChanged(record, prevSectionKey);
        }

        synchronized (mAggregatedNotifications) {
            // This notification is already aggregated
            if (record.getGroupKey().equals(fullAggregateGroupKey.toString())) {
                // Update summary if flags updated
                maybeUpdateSummaryAttributes(record, fullAggregateGroupKey, sectioner);
                return false;
            }
        synchronized (mAggregatedNotifications) {

            ArrayMap<String, NotificationAttributes> ungrouped =
                mUngroupedAbuseNotifications.getOrDefault(fullAggregateGroupKey, new ArrayMap<>());
            ungrouped.put(record.getKey(), new NotificationAttributes(
@@ -659,6 +662,36 @@ public class GroupHelper {
        return sbnToBeAutogrouped;
    }

    @GuardedBy("mAggregatedNotifications")
    private void maybeUpdateSummaryAttributes(NotificationRecord childRecord,
            FullyQualifiedGroupKey fullAggregateGroupKey,
            NotificationSectioner sectioner) {
        final ArrayMap<String, NotificationAttributes> aggregatedNotificationsAttrs =
                mAggregatedNotifications.getOrDefault(fullAggregateGroupKey, new ArrayMap<>());
        NotificationAttributes oldAttrs = aggregatedNotificationsAttrs.get(childRecord.getKey());
        if (oldAttrs != null) {
            NotificationAttributes newAttr = new NotificationAttributes(
                    childRecord.getFlags(),
                    childRecord.getNotification().getSmallIcon(),
                    childRecord.getNotification().color,
                    childRecord.getNotification().visibility,
                    childRecord.getNotification().getGroupAlertBehavior(),
                    childRecord.getChannel().getId());
            if (!oldAttrs.equals(newAttr)) {
                aggregatedNotificationsAttrs.put(childRecord.getKey(), newAttr);
                mAggregatedNotifications.put(fullAggregateGroupKey, aggregatedNotificationsAttrs);

                if (DEBUG) {
                    Slog.i(TAG, "maybeUpdateSummaryAttributes: " + childRecord);
                }

                // Update aggregate summary
                updateAggregateAppGroup(fullAggregateGroupKey, childRecord.getKey(), true,
                        sectioner.mSummaryId);
            }
        }
    }

    /**
     * A notification was added that was previously part of a valid section and needs to trigger
     * GH state cleanup.
+156 −0
Original line number Diff line number Diff line
@@ -824,6 +824,162 @@ public class GroupHelperTest extends UiServiceTestCase {
            any());
    }

    @Test
    @EnableFlags(FLAG_NOTIFICATION_FORCE_GROUPING)
    public void testAutoGrouped_updateOngoingChild_updatesSummary() {
        final String pkg = "package";
        final String expectedGroupKey = GroupHelper.getFullAggregateGroupKey(pkg,
                AGGREGATE_GROUP_KEY + "AlertingSection", UserHandle.SYSTEM.getIdentifier());

        // Post AUTOGROUP_AT_COUNT ongoing notifications
        ArrayList<NotificationRecord> notifications = new ArrayList<>();
        for (int i = 0; i < AUTOGROUP_AT_COUNT; i++) {
            NotificationRecord r = getNotificationRecord(pkg, i, String.valueOf(i),
                    UserHandle.SYSTEM);
            notifications.add(r);
        }

        for (NotificationRecord r: notifications) {
            mGroupHelper.onNotificationPosted(r, false);
            r.setOverrideGroupKey(expectedGroupKey);
        }

        // Update one notification to ONGOING_EVENT
        Mockito.reset(mCallback);
        final NotificationRecord updatedNotification = notifications.get(0);
        updatedNotification.getNotification().flags |= FLAG_ONGOING_EVENT;
        mGroupHelper.onNotificationPosted(updatedNotification, true);

        // Check that summary has FLAG_ONGOING_EVENT
        verify(mCallback).updateAutogroupSummary(anyInt(), anyString(), anyString(),
                eq(getNotificationAttributes(BASE_FLAGS | FLAG_ONGOING_EVENT)));
    }

    @Test
    @EnableFlags(FLAG_NOTIFICATION_FORCE_GROUPING)
    public void testAutoGrouped_noFlagsUpdate_doesNotUpdateSummary() {
        final String pkg = "package";
        final String expectedGroupKey = GroupHelper.getFullAggregateGroupKey(pkg,
                AGGREGATE_GROUP_KEY + "AlertingSection", UserHandle.SYSTEM.getIdentifier());

        // Post AUTOGROUP_AT_COUNT ongoing notifications
        ArrayList<NotificationRecord> notifications = new ArrayList<>();
        for (int i = 0; i < AUTOGROUP_AT_COUNT; i++) {
            NotificationRecord r = getNotificationRecord(pkg, i, String.valueOf(i),
                    UserHandle.SYSTEM);
            notifications.add(r);
        }

        for (NotificationRecord r: notifications) {
            mGroupHelper.onNotificationPosted(r, false);
            r.setOverrideGroupKey(expectedGroupKey);
        }

        // Update one notification without updating its flags
        Mockito.reset(mCallback);
        final NotificationRecord updatedNotification = notifications.get(0);
        mGroupHelper.onNotificationPosted(updatedNotification, true);

        // Check that nothing was updated
        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 testAddAggregateSummary_summaryNoChildren_updateFlags_updatesSummary() {
        final String pkg = "package";
        final String expectedGroupKey = GroupHelper.getFullAggregateGroupKey(pkg,
                AGGREGATE_GROUP_KEY + "AlertingSection", UserHandle.SYSTEM.getIdentifier());
        final List<NotificationRecord> notificationList = new ArrayList<>();
        final ArrayMap<String, NotificationRecord> summaryByGroup = new ArrayMap<>();
        // Post group summaries without children => force autogroup
        for (int i = 0; i < AUTOGROUP_AT_COUNT; i++) {
            NotificationRecord r = getNotificationRecord(pkg, i, String.valueOf(i),
                    UserHandle.SYSTEM, "testGrp " + i, true);
            notificationList.add(r);
            mGroupHelper.onNotificationPostedWithDelay(r, notificationList, summaryByGroup);
        }
        // Check that notifications were autogrouped
        verify(mCallback, times(1)).addAutoGroupSummary(anyInt(), eq(pkg), anyString(),
                eq(expectedGroupKey), anyInt(), eq(getNotificationAttributes(BASE_FLAGS)));
        verify(mCallback, times(AUTOGROUP_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());

        // Update notifications group key to aggregate group
        for (NotificationRecord r: notificationList) {
            r.setOverrideGroupKey(expectedGroupKey);
        }

        // Update to FLAG_ONGOING_EVENT
        Mockito.reset(mCallback);
        final NotificationRecord updatedNotification = notificationList.get(0);
        updatedNotification.getNotification().flags |= FLAG_ONGOING_EVENT;
        mGroupHelper.onNotificationPosted(updatedNotification, true);

        verify(mCallback, times(1)).removeAutoGroup(updatedNotification.getKey());
        updatedNotification.setOverrideGroupKey(null);

        mGroupHelper.onNotificationPostedWithDelay(updatedNotification, notificationList,
                summaryByGroup);

        // Check that summary has FLAG_ONGOING_EVENT
        verify(mCallback).updateAutogroupSummary(anyInt(), anyString(), anyString(),
                eq(getNotificationAttributes(BASE_FLAGS | FLAG_ONGOING_EVENT)));
    }

    @Test
    @EnableFlags(FLAG_NOTIFICATION_FORCE_GROUPING)
    public void testAddAggregateSummary_childrenNoSummary_updateFlags_updatesSummary() {
        final String pkg = "package";
        final String expectedGroupKey = GroupHelper.getFullAggregateGroupKey(pkg,
                AGGREGATE_GROUP_KEY + "AlertingSection", UserHandle.SYSTEM.getIdentifier());
        final List<NotificationRecord> notificationList = new ArrayList<>();
        final ArrayMap<String, NotificationRecord> summaryByGroup = new ArrayMap<>();
        // Post group notifications without summaries => force autogroup
        for (int i = 0; i < AUTOGROUP_AT_COUNT; i++) {
            NotificationRecord r = getNotificationRecord(pkg, i, String.valueOf(i),
                    UserHandle.SYSTEM, "testGrp " + i, false);
            notificationList.add(r);
            mGroupHelper.onNotificationPostedWithDelay(r, notificationList, summaryByGroup);
        }
        verify(mCallback, times(1)).addAutoGroupSummary(anyInt(), eq(pkg), anyString(),
                eq(expectedGroupKey), anyInt(), eq(getNotificationAttributes(BASE_FLAGS)));
        verify(mCallback, times(AUTOGROUP_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());

        // Update notification group
        for (NotificationRecord r: notificationList) {
            r.setOverrideGroupKey(expectedGroupKey);
        }

        // Update to FLAG_ONGOING_EVENT
        Mockito.reset(mCallback);
        final NotificationRecord updatedNotification = notificationList.get(0);
        updatedNotification.getNotification().flags |= FLAG_ONGOING_EVENT;
        mGroupHelper.onNotificationPosted(updatedNotification, true);

        verify(mCallback, times(1)).removeAutoGroup(updatedNotification.getKey());
        updatedNotification.setOverrideGroupKey(null);

        mGroupHelper.onNotificationPostedWithDelay(updatedNotification, notificationList,
                summaryByGroup);

        // Check that summary has FLAG_ONGOING_EVENT
        verify(mCallback).updateAutogroupSummary(anyInt(), anyString(), anyString(),
                eq(getNotificationAttributes(BASE_FLAGS | FLAG_ONGOING_EVENT)));
    }

    @Test
    @EnableFlags({FLAG_NOTIFICATION_FORCE_GROUPING})
    public void testDropToZeroRemoveGroup() {
+102 −0
Original line number Diff line number Diff line
@@ -2696,6 +2696,108 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
        assertThat(summary.getChannel().getId()).isEqualTo(newChannelId);
    }
    @Test
    @EnableFlags(FLAG_NOTIFICATION_FORCE_GROUPING)
    public void testAggregatedSummary_updateUngroupedChildFlags_updatesSummary() throws Exception {
        // Add 2 ungrouped notifications
        NotificationRecord nr0 = generateNotificationRecord(mTestNotificationChannel, 0, mUserId);
        mService.addEnqueuedNotification(nr0);
        NotificationManagerService.PostNotificationRunnable runnable =
                mService.new PostNotificationRunnable(nr0.getKey(), nr0.getSbn().getPackageName(),
                    nr0.getUid(), mPostNotificationTrackerFactory.newTracker(null));
        runnable.run();
        waitForIdle();
        moveTimeForwardAndWaitForIdle(DELAY_FORCE_REGROUP_TIME);
        NotificationRecord nr1 = generateNotificationRecord(mTestNotificationChannel, 1, mUserId);
        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);
        // Check that the aggregate group summary was created
        nr0.applyAdjustments();
        nr1.applyAdjustments();
        final String fullAggregateGroupKey = nr0.getGroupKey();
        NotificationRecord aggregateSummary = mService.mSummaryByGroupKey.get(
                fullAggregateGroupKey);
        assertThat(aggregateSummary).isNotNull();
        assertThat(aggregateSummary.getNotification().getGroup()).isEqualTo(fullAggregateGroupKey);
        assertThat(aggregateSummary.getNotification().getChannelId()).isEqualTo(
                nr0.getChannel().getId());
        assertThat(aggregateSummary.getSbn().isOngoing()).isFalse();
        // Update first child's flags
        final NotificationRecord updatedNotification = generateNotificationRecord(
                mTestNotificationChannel, 0, mUserId);
        updatedNotification.getNotification().flags |= FLAG_ONGOING_EVENT;
        mBinderService.enqueueNotificationWithTag(mPkg, mPkg, nr0.getSbn().getTag(),
                nr0.getSbn().getId(), updatedNotification.getNotification(),
                nr0.getSbn().getUserId());
        waitForIdle();
        moveTimeForwardAndWaitForIdle(DELAY_FORCE_REGROUP_TIME);
        // Check that summary has FLAG_ONGOING_EVENT
        assertThat(aggregateSummary.getSbn().isOngoing()).isTrue();
    }
    @Test
    @EnableFlags(FLAG_NOTIFICATION_FORCE_GROUPING)
    public void testAggregatedSummary_updateForceGroupedChildFlags_updatesSummary()
            throws Exception {
        // Add 2 summary notifications without children
        final String originalGroupName = "originalGroup";
        final NotificationRecord nr0 =
                generateNotificationRecord(mTestNotificationChannel, 0, originalGroupName, true);
        mService.addEnqueuedNotification(nr0);
        NotificationManagerService.PostNotificationRunnable runnable =
                mService.new PostNotificationRunnable(nr0.getKey(), nr0.getSbn().getPackageName(),
                    nr0.getUid(), mPostNotificationTrackerFactory.newTracker(null));
        runnable.run();
        waitForIdle();
        moveTimeForwardAndWaitForIdle(DELAY_FORCE_REGROUP_TIME);
        final NotificationRecord nr1 =
                generateNotificationRecord(mTestNotificationChannel, 1, originalGroupName, true);
        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);
        // Check that the aggregate group summary was created
        nr0.applyAdjustments();
        nr1.applyAdjustments();
        final String fullAggregateGroupKey = nr0.getGroupKey();
        NotificationRecord aggregateSummary = mService.mSummaryByGroupKey.get(
                fullAggregateGroupKey);
        assertThat(aggregateSummary).isNotNull();
        assertThat(aggregateSummary.getNotification().getGroup()).isEqualTo(fullAggregateGroupKey);
        assertThat(aggregateSummary.getNotification().getChannelId()).isEqualTo(
                nr0.getChannel().getId());
        assertThat(aggregateSummary.getSbn().isOngoing()).isFalse();
        assertThat(nr0.getNotification().isGroupSummary()).isFalse();
        assertThat(nr1.getNotification().isGroupSummary()).isFalse();
        // Update first child's flags
        final NotificationRecord updatedNotification =
                generateNotificationRecord(mTestNotificationChannel, 0, originalGroupName, true);
        updatedNotification.getNotification().flags |= FLAG_ONGOING_EVENT;
        mBinderService.enqueueNotificationWithTag(mPkg, mPkg, nr0.getSbn().getTag(),
                nr0.getSbn().getId(), updatedNotification.getNotification(),
                nr0.getSbn().getUserId());
        waitForIdle();
        moveTimeForwardAndWaitForIdle(DELAY_FORCE_REGROUP_TIME);
        // Check that summary has FLAG_ONGOING_EVENT
        assertThat(aggregateSummary.getSbn().isOngoing()).isTrue();
    }
    @Test
    @EnableFlags(FLAG_NOTIFICATION_FORCE_GROUPING)
    public void testAddAggregateNotification_notifyPostedLocked() throws Exception {