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

Commit 184a2675 authored by Valentin Iftime's avatar Valentin Iftime Committed by Iavor-Valentin Iftime
Browse files

Add GroupHelper sections for new conversations

 Add support for auto-grouping conversation notifications.

Flag: android.service.notification.notification_force_grouping
Flag: com.android.server.notification.notification_force_group_conversations

Test: atest GroupHelperTest
Bug: 336488844
Change-Id: I384b3d089602cd6f459af6d185cda42a84ab23c7
parent 3a80cdca
Loading
Loading
Loading
Loading
+35 −14
Original line number Diff line number Diff line
@@ -122,8 +122,9 @@ public class GroupHelper {
            getNotificationShadeSections();

    private static List<NotificationSectioner> getNotificationShadeSections() {
        ArrayList<NotificationSectioner> sectionsList = new ArrayList<>();
        if (android.service.notification.Flags.notificationClassification()) {
            return List.of(
            sectionsList.addAll(List.of(
                new NotificationSectioner("PromotionsSection", 0, (record) ->
                    NotificationChannel.PROMOTIONS_ID.equals(record.getChannel().getId())),
                new NotificationSectioner("SocialSection", 0, (record) ->
@@ -131,18 +132,36 @@ public class GroupHelper {
                new NotificationSectioner("NewsSection", 0, (record) ->
                    NotificationChannel.NEWS_ID.equals(record.getChannel().getId())),
                new NotificationSectioner("RecsSection", 0, (record) ->
                    NotificationChannel.RECS_ID.equals(record.getChannel().getId())),
                new NotificationSectioner("AlertingSection", 0, (record) ->
                    record.getImportance() >= NotificationManager.IMPORTANCE_DEFAULT),
                new NotificationSectioner("SilentSection", 1, (record) ->
                    record.getImportance() < NotificationManager.IMPORTANCE_DEFAULT));
                    NotificationChannel.RECS_ID.equals(record.getChannel().getId()))));
        }

        if (Flags.notificationForceGroupConversations()) {
            // add priority people section
            sectionsList.add(new NotificationSectioner("PeopleSection(priority)", 1, (record) ->
                    record.isConversation() && record.getChannel().isImportantConversation()));

            if (android.app.Flags.sortSectionByTime()) {
                // add single people (alerting) section
                sectionsList.add(new NotificationSectioner("PeopleSection", 0,
                        NotificationRecord::isConversation));
            } else {
            return List.of(
                // add people alerting section
                sectionsList.add(new NotificationSectioner("PeopleSection(alerting)", 1, (record) ->
                        record.isConversation()
                        && record.getImportance() >= NotificationManager.IMPORTANCE_DEFAULT));
                // add people silent section
                sectionsList.add(new NotificationSectioner("PeopleSection(silent)", 1, (record) ->
                        record.isConversation()
                        && record.getImportance() < NotificationManager.IMPORTANCE_DEFAULT));
            }
        }

        sectionsList.addAll(List.of(
            new NotificationSectioner("AlertingSection", 0, (record) ->
                record.getImportance() >= NotificationManager.IMPORTANCE_DEFAULT),
            new NotificationSectioner("SilentSection", 1, (record) ->
                    record.getImportance() < NotificationManager.IMPORTANCE_DEFAULT));
        }
                record.getImportance() < NotificationManager.IMPORTANCE_DEFAULT)));
        return sectionsList;
    }

    public GroupHelper(Context context, PackageManager packageManager, int autoGroupAtCount,
@@ -1387,9 +1406,11 @@ public class GroupHelper {
        }

        private boolean isNotificationGroupable(final NotificationRecord record) {
            if (!Flags.notificationForceGroupConversations()) {
                if (record.isConversation()) {
                    return false;
                }
            }

            Notification notification = record.getSbn().getNotification();
            boolean isColorizedFGS = notification.isForegroundService()
+7 −0
Original line number Diff line number Diff line
@@ -149,3 +149,10 @@ flag {
  description: "This flag enables forced auto-grouping singleton groups"
  bug: "336488844"
}

flag {
  name: "notification_force_group_conversations"
  namespace: "systemui"
  description: "This flag enables forced auto-grouping conversations"
  bug: "336488844"
}
+86 −4
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
 */
package com.android.server.notification;

import static android.app.Flags.FLAG_SORT_SECTION_BY_TIME;
import static android.app.Notification.COLOR_DEFAULT;
import static android.app.Notification.FLAG_AUTO_CANCEL;
import static android.app.Notification.FLAG_BUBBLE;
@@ -36,6 +37,7 @@ import static android.service.notification.Flags.FLAG_NOTIFICATION_FORCE_GROUPIN
import static android.service.notification.NotificationListenerService.REASON_APP_CANCEL;
import static android.platform.test.flag.junit.SetFlagsRule.DefaultInitValueType.DEVICE_DEFAULT;

import static com.android.server.notification.Flags.FLAG_NOTIFICATION_FORCE_GROUP_CONVERSATIONS;
import static com.android.server.notification.GroupHelper.AGGREGATE_GROUP_KEY;
import static com.android.server.notification.GroupHelper.AUTOGROUP_KEY;
import static com.android.server.notification.GroupHelper.BASE_FLAGS;
@@ -2575,7 +2577,11 @@ public class GroupHelperTest extends UiServiceTestCase {
        assertThat(cachedSummary).isNull();
    }

    private void checkNonGroupableNotifications() {
    @Test
    @EnableFlags(FLAG_NOTIFICATION_FORCE_GROUPING)
    @DisableFlags(FLAG_NOTIFICATION_FORCE_GROUP_CONVERSATIONS)
    public void testNonGroupableNotifications() {
        // Check that there is no valid section for: conversations, calls, foreground services
        NotificationRecord notification_conversation = mock(NotificationRecord.class);
        when(notification_conversation.isConversation()).thenReturn(true);
        assertThat(GroupHelper.getSection(notification_conversation)).isNull();
@@ -2648,8 +2654,6 @@ public class GroupHelperTest extends UiServiceTestCase {
                "", false, recsChannel);
        assertThat(GroupHelper.getSection(notification_recs).mName).isEqualTo(
                "AlertingSection");

        checkNonGroupableNotifications();
    }

    @Test
@@ -2694,8 +2698,86 @@ public class GroupHelperTest extends UiServiceTestCase {
                "", false, recsChannel);
        assertThat(GroupHelper.getSection(notification_recs).mName).isEqualTo(
                "RecsSection");
    }

    @Test
    @EnableFlags({FLAG_NOTIFICATION_FORCE_GROUPING, FLAG_NOTIFICATION_FORCE_GROUP_CONVERSATIONS})
    public void testNonGroupableNotifications_forceGroupConversations() {
        // Check that there is no valid section for: calls, foreground services
        NotificationRecord notification_call = spy(getNotificationRecord(mPkg, 0, "", mUser,
                "", false, IMPORTANCE_LOW));
        Notification n = mock(Notification.class);
        StatusBarNotification sbn = spy(getSbn("package", 0, "0", UserHandle.SYSTEM));
        when(notification_call.isConversation()).thenReturn(false);
        when(notification_call.getNotification()).thenReturn(n);
        when(notification_call.getSbn()).thenReturn(sbn);
        when(sbn.getNotification()).thenReturn(n);
        when(n.isStyle(Notification.CallStyle.class)).thenReturn(true);
        assertThat(GroupHelper.getSection(notification_call)).isNull();

        NotificationRecord notification_colorFg = spy(getNotificationRecord(mPkg, 0, "", mUser,
                "", false, IMPORTANCE_LOW));
        sbn = spy(getSbn("package", 0, "0", UserHandle.SYSTEM));
        n = mock(Notification.class);
        when(notification_colorFg.isConversation()).thenReturn(false);
        when(notification_colorFg.getNotification()).thenReturn(n);
        when(notification_colorFg.getSbn()).thenReturn(sbn);
        when(sbn.getNotification()).thenReturn(n);
        when(n.isForegroundService()).thenReturn(true);
        when(n.isColorized()).thenReturn(true);
        when(n.isStyle(Notification.CallStyle.class)).thenReturn(false);
        assertThat(GroupHelper.getSection(notification_colorFg)).isNull();
    }

    @Test
    @EnableFlags({FLAG_NOTIFICATION_FORCE_GROUPING, FLAG_NOTIFICATION_FORCE_GROUP_CONVERSATIONS})
    @DisableFlags(FLAG_SORT_SECTION_BY_TIME)
    public void testConversationGroupSections_disableSortSectionByTime() {
        // Check that there are separate sections for conversations: alerting and silent
        NotificationRecord notification_conversation_silent = getNotificationRecord(mPkg, 0, "",
                mUser, "", false, IMPORTANCE_LOW);
        notification_conversation_silent = spy(notification_conversation_silent);
        when(notification_conversation_silent.isConversation()).thenReturn(true);
        assertThat(GroupHelper.getSection(notification_conversation_silent).mName).isEqualTo(
                "PeopleSection(silent)");

        checkNonGroupableNotifications();
        // Check that there is a correct section for conversations
        NotificationRecord notification_conversation_alerting = getNotificationRecord(mPkg, 0, "",
                mUser, "", false, IMPORTANCE_DEFAULT);
        notification_conversation_alerting = spy(notification_conversation_alerting);
        when(notification_conversation_alerting.isConversation()).thenReturn(true);
        assertThat(GroupHelper.getSection(notification_conversation_alerting).mName).isEqualTo(
                "PeopleSection(alerting)");
    }

    @Test
    @EnableFlags({FLAG_NOTIFICATION_FORCE_GROUPING,
            FLAG_NOTIFICATION_FORCE_GROUP_CONVERSATIONS,
            FLAG_SORT_SECTION_BY_TIME})
    public void testConversationGroupSections() {
        // Check that there is a single section for silent/alerting conversations
        NotificationRecord notification_conversation_silent = getNotificationRecord(mPkg, 0, "",
                mUser, "", false, IMPORTANCE_LOW);
        notification_conversation_silent = spy(notification_conversation_silent);
        when(notification_conversation_silent.isConversation()).thenReturn(true);
        assertThat(GroupHelper.getSection(notification_conversation_silent).mName).isEqualTo(
                "PeopleSection");

        NotificationRecord notification_conversation_alerting = getNotificationRecord(mPkg, 0, "",
                mUser, "", false, IMPORTANCE_DEFAULT);
        notification_conversation_alerting = spy(notification_conversation_alerting);
        when(notification_conversation_alerting.isConversation()).thenReturn(true);
        assertThat(GroupHelper.getSection(notification_conversation_alerting).mName).isEqualTo(
                "PeopleSection");

        // Check that there is a section for priority conversations
        NotificationRecord notification_conversation_prio = getNotificationRecord(mPkg, 0, "",
                mUser, "", false, IMPORTANCE_DEFAULT);
        notification_conversation_prio = spy(notification_conversation_prio);
        when(notification_conversation_prio.isConversation()).thenReturn(true);
        notification_conversation_prio.getChannel().setImportantConversation(true);
        assertThat(GroupHelper.getSection(notification_conversation_prio).mName).isEqualTo(
                "PeopleSection(priority)");
    }

}