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

Commit 08795234 authored by Ibrahim Yilmaz's avatar Ibrahim Yilmaz
Browse files

"Hide silent notifications in status bar" should apply to silent conversations,too

Notification is designed to be in a single section. So convo has two options when it is silent, convo or silent one.
This is our current section prio :  HeadsUp > FGS > People > Alerting > Silent > Minimized > Unknown/Default
As convo(people) has higher priority than silent, convo notifs always falls convo.

We decided to divide People notification into two groups, silent and alerting. Given that, new prio is going to be:

HeadsUp > FGS > People(alerting) > People(silent) >  Alerting > Silent > Minimized > Unknown/Default

Fixes: b/275711619
Test: atest NotificationIconAreaControllerTest
Change-Id: Ib9efcc199d8675fd16dc394075a53ff25a060786
parent 5a582c83
Loading
Loading
Loading
Loading
+47 −31
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import com.android.systemui.statusbar.notification.collection.listbuilder.OnBefo
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifComparator
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifPromoter
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner
import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider
import com.android.systemui.statusbar.notification.collection.render.NodeController
import com.android.systemui.statusbar.notification.dagger.PeopleHeader
import com.android.systemui.statusbar.notification.icon.ConversationIconManager
@@ -42,7 +43,8 @@ import javax.inject.Inject
class ConversationCoordinator @Inject constructor(
        private val peopleNotificationIdentifier: PeopleNotificationIdentifier,
        private val conversationIconManager: ConversationIconManager,
    @PeopleHeader peopleHeaderController: NodeController
        private val highPriorityProvider: HighPriorityProvider,
        @PeopleHeader private val peopleHeaderController: NodeController,
) : Coordinator {

    private val promotedEntriesToSummaryOfSameChannel =
@@ -78,21 +80,23 @@ class ConversationCoordinator @Inject constructor(
        }
    }

    val sectioner = object : NotifSectioner("People", BUCKET_PEOPLE) {
    val peopleAlertingSectioner = object : NotifSectioner("People(alerting)", BUCKET_PEOPLE) {
        override fun isInSection(entry: ListEntry): Boolean =
                isConversation(entry)
               highPriorityProvider.isHighPriorityConversation(entry)

        override fun getComparator() = object : NotifComparator("People") {
            override fun compare(entry1: ListEntry, entry2: ListEntry): Int {
                val type1 = getPeopleType(entry1)
                val type2 = getPeopleType(entry2)
                return type2.compareTo(type1)
            }
        override fun getComparator(): NotifComparator = notifComparator

        override fun getHeaderNodeController(): NodeController? = conversationHeaderNodeController
    }

        override fun getHeaderNodeController() =
                // TODO: remove SHOW_ALL_SECTIONS, this redundant method, and peopleHeaderController
                if (RankingCoordinator.SHOW_ALL_SECTIONS) peopleHeaderController else null
    val peopleSilentSectioner = object : NotifSectioner("People(silent)", BUCKET_PEOPLE) {
        // Because the peopleAlertingSectioner is above this one, it will claim all conversations that are alerting.
        // All remaining conversations must be silent.
        override fun isInSection(entry: ListEntry): Boolean = isConversation(entry)

        override fun getComparator(): NotifComparator = notifComparator

        override fun getHeaderNodeController(): NodeController? = conversationHeaderNodeController
    }

    override fun attach(pipeline: NotifPipeline) {
@@ -109,7 +113,19 @@ class ConversationCoordinator @Inject constructor(
                peopleNotificationIdentifier.getPeopleNotificationType(it)
            } ?: TYPE_NON_PERSON

    companion object {
    private val notifComparator: NotifComparator = object : NotifComparator("People") {
        override fun compare(entry1: ListEntry, entry2: ListEntry): Int {
            val type1 = getPeopleType(entry1)
            val type2 = getPeopleType(entry2)
            return type2.compareTo(type1)
        }
    }

    // TODO: remove SHOW_ALL_SECTIONS, this redundant method, and peopleHeaderController
    private val conversationHeaderNodeController: NodeController? =
            if (RankingCoordinator.SHOW_ALL_SECTIONS) peopleHeaderController else null

    private companion object {
        private const val TAG = "ConversationCoordinator"
    }
}
+13 −4
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import com.android.systemui.statusbar.notification.collection.PipelineDumpable
import com.android.systemui.statusbar.notification.collection.PipelineDumper
import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner
import com.android.systemui.statusbar.notification.collection.provider.SectionStyleProvider
import javax.inject.Inject

/**
@@ -32,6 +33,7 @@ interface NotifCoordinators : Coordinator, PipelineDumpable
@CoordinatorScope
class NotifCoordinatorsImpl @Inject constructor(
        notifPipelineFlags: NotifPipelineFlags,
        sectionStyleProvider: SectionStyleProvider,
        dataStoreCoordinator: DataStoreCoordinator,
        hideLocallyDismissedNotifsCoordinator: HideLocallyDismissedNotifsCoordinator,
        hideNotifsForOtherUsersCoordinator: HideNotifsForOtherUsersCoordinator,
@@ -56,7 +58,7 @@ class NotifCoordinatorsImpl @Inject constructor(
        viewConfigCoordinator: ViewConfigCoordinator,
        visualStabilityCoordinator: VisualStabilityCoordinator,
        sensitiveContentCoordinator: SensitiveContentCoordinator,
        dismissibilityCoordinator: DismissibilityCoordinator
        dismissibilityCoordinator: DismissibilityCoordinator,
) : NotifCoordinators {

    private val mCoordinators: MutableList<Coordinator> = ArrayList()
@@ -99,13 +101,20 @@ class NotifCoordinatorsImpl @Inject constructor(
        mCoordinators.add(dismissibilityCoordinator)

        // Manually add Ordered Sections
        // HeadsUp > FGS > People > Alerting > Silent > Minimized > Unknown/Default
        mOrderedSections.add(headsUpCoordinator.sectioner)
        mOrderedSections.add(headsUpCoordinator.sectioner) // HeadsUp
        mOrderedSections.add(appOpsCoordinator.sectioner) // ForegroundService
        mOrderedSections.add(conversationCoordinator.sectioner) // People
        mOrderedSections.add(conversationCoordinator.peopleAlertingSectioner) // People Alerting
        mOrderedSections.add(conversationCoordinator.peopleSilentSectioner) // People Silent
        mOrderedSections.add(rankingCoordinator.alertingSectioner) // Alerting
        mOrderedSections.add(rankingCoordinator.silentSectioner) // Silent
        mOrderedSections.add(rankingCoordinator.minimizedSectioner) // Minimized

        sectionStyleProvider.setMinimizedSections(setOf(rankingCoordinator.minimizedSectioner))
        sectionStyleProvider.setSilentSections(listOf(
                conversationCoordinator.peopleSilentSectioner,
                rankingCoordinator.silentSectioner,
                rankingCoordinator.minimizedSectioner,
        ))
    }

    /**
+0 −9
Original line number Diff line number Diff line
@@ -27,15 +27,12 @@ import com.android.systemui.statusbar.notification.collection.coordinator.dagger
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner;
import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider;
import com.android.systemui.statusbar.notification.collection.provider.SectionStyleProvider;
import com.android.systemui.statusbar.notification.collection.render.NodeController;
import com.android.systemui.statusbar.notification.collection.render.SectionHeaderController;
import com.android.systemui.statusbar.notification.dagger.AlertingHeader;
import com.android.systemui.statusbar.notification.dagger.SilentHeader;
import com.android.systemui.statusbar.notification.stack.NotificationPriorityBucketKt;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import javax.inject.Inject;
@@ -52,7 +49,6 @@ public class RankingCoordinator implements Coordinator {
    public static final boolean SHOW_ALL_SECTIONS = false;
    private final StatusBarStateController mStatusBarStateController;
    private final HighPriorityProvider mHighPriorityProvider;
    private final SectionStyleProvider mSectionStyleProvider;
    private final NodeController mSilentNodeController;
    private final SectionHeaderController mSilentHeaderController;
    private final NodeController mAlertingHeaderController;
@@ -63,13 +59,11 @@ public class RankingCoordinator implements Coordinator {
    public RankingCoordinator(
            StatusBarStateController statusBarStateController,
            HighPriorityProvider highPriorityProvider,
            SectionStyleProvider sectionStyleProvider,
            @AlertingHeader NodeController alertingHeaderController,
            @SilentHeader SectionHeaderController silentHeaderController,
            @SilentHeader NodeController silentNodeController) {
        mStatusBarStateController = statusBarStateController;
        mHighPriorityProvider = highPriorityProvider;
        mSectionStyleProvider = sectionStyleProvider;
        mAlertingHeaderController = alertingHeaderController;
        mSilentNodeController = silentNodeController;
        mSilentHeaderController = silentHeaderController;
@@ -78,9 +72,6 @@ public class RankingCoordinator implements Coordinator {
    @Override
    public void attach(NotifPipeline pipeline) {
        mStatusBarStateController.addCallback(mStatusBarStateCallback);
        mSectionStyleProvider.setMinimizedSections(Collections.singleton(mMinimizedNotifSectioner));
        mSectionStyleProvider.setSilentSections(
                Arrays.asList(mSilentNotifSectioner, mMinimizedNotifSectioner));

        pipeline.addPreGroupFilter(mSuspendedFilter);
        pipeline.addPreGroupFilter(mDndVisualEffectsFilter);
+34 −2
Original line number Diff line number Diff line
@@ -16,10 +16,13 @@

package com.android.systemui.statusbar.notification.collection.provider;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.Notification;
import android.app.NotificationManager;

import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.statusbar.notification.collection.GroupEntry;
import com.android.systemui.statusbar.notification.collection.ListEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
@@ -63,7 +66,7 @@ public class HighPriorityProvider {
     * A GroupEntry is considered high priority if its representativeEntry (summary) or children are
     * high priority
     */
    public boolean isHighPriority(ListEntry entry) {
    public boolean isHighPriority(@Nullable ListEntry entry) {
        if (entry == null) {
            return false;
        }
@@ -78,6 +81,36 @@ public class HighPriorityProvider {
                || hasHighPriorityChild(entry);
    }

    /**
     * @return true if the ListEntry is high priority conversation, else false
     */
    public boolean isHighPriorityConversation(@NonNull ListEntry entry) {
        final NotificationEntry notifEntry = entry.getRepresentativeEntry();
        if (notifEntry == null) {
            return  false;
        }

        if (!isPeopleNotification(notifEntry)) {
            return false;
        }

        if (notifEntry.getRanking().getImportance() >= NotificationManager.IMPORTANCE_DEFAULT) {
            return true;
        }

        return isNotificationEntryWithAtLeastOneImportantChild(entry);
    }

    private boolean isNotificationEntryWithAtLeastOneImportantChild(@NonNull ListEntry entry) {
        if (!(entry instanceof GroupEntry)) {
            return false;
        }
        final GroupEntry groupEntry = (GroupEntry) entry;
        return groupEntry.getChildren().stream().anyMatch(
                childEntry ->
                        childEntry.getRanking().getImportance()
                                >= NotificationManager.IMPORTANCE_DEFAULT);
    }

    private boolean hasHighPriorityChild(ListEntry entry) {
        if (entry instanceof NotificationEntry
@@ -93,7 +126,6 @@ public class HighPriorityProvider {
                }
            }
        }

        return false;
    }

+53 −0
Original line number Diff line number Diff line
@@ -96,6 +96,59 @@ public class HighPriorityProviderTest extends SysuiTestCase {
        assertTrue(mHighPriorityProvider.isHighPriority(entry));
    }

    @Test
    public void highImportanceConversation() {
        // GIVEN notification is high importance and is a people notification
        final Notification notification = new Notification.Builder(mContext, "test")
                .build();
        final NotificationEntry entry = new NotificationEntryBuilder()
                .setNotification(notification)
                .setImportance(IMPORTANCE_HIGH)
                .build();
        when(mPeopleNotificationIdentifier
                .getPeopleNotificationType(entry))
                .thenReturn(TYPE_PERSON);

        // THEN it is high priority conversation
        assertTrue(mHighPriorityProvider.isHighPriorityConversation(entry));
    }

    @Test
    public void lowImportanceConversation() {
        // GIVEN notification is high importance and is a people notification
        final Notification notification = new Notification.Builder(mContext, "test")
                .build();
        final NotificationEntry entry = new NotificationEntryBuilder()
                .setNotification(notification)
                .setImportance(IMPORTANCE_LOW)
                .build();
        when(mPeopleNotificationIdentifier
                .getPeopleNotificationType(entry))
                .thenReturn(TYPE_PERSON);

        // THEN it is low priority conversation
        assertFalse(mHighPriorityProvider.isHighPriorityConversation(entry));
    }

    @Test
    public void highImportanceConversationWhenAnyOfChildIsHighPriority() {
        // GIVEN notification is high importance and is a people notification
        final NotificationEntry summary = createNotifEntry(false);
        final NotificationEntry lowPriorityChild = createNotifEntry(false);
        final NotificationEntry highPriorityChild = createNotifEntry(true);
        when(mPeopleNotificationIdentifier
                .getPeopleNotificationType(summary))
                .thenReturn(TYPE_PERSON);
        final GroupEntry groupEntry = new GroupEntryBuilder()
                .setParent(GroupEntry.ROOT_ENTRY)
                .setSummary(summary)
                .setChildren(List.of(lowPriorityChild, highPriorityChild))
                .build();

        // THEN the groupEntry is high priority conversation since it has a high priority child
        assertTrue(mHighPriorityProvider.isHighPriorityConversation(groupEntry));
    }

    @Test
    public void messagingStyle() {
        // GIVEN notification is low importance but has messaging style
Loading