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

Commit 960f4ced authored by Steve Elliott's avatar Steve Elliott
Browse files

Fix ranking of people notifications and peoplehub

Test: manual, atest
Fixes: 145312530
Fixes: 143551319
Change-Id: Ief7b81fd2afdd52c248430796197195eb562ab13
parent b11f9312
Loading
Loading
Loading
Loading
+26 −45
Original line number Diff line number Diff line
@@ -16,37 +16,29 @@

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

import android.app.Notification
import android.app.NotificationManager.IMPORTANCE_DEFAULT
import android.app.NotificationManager.IMPORTANCE_HIGH
import android.app.NotificationManager.IMPORTANCE_LOW
import android.app.NotificationManager.IMPORTANCE_MIN
import android.app.Person
import android.service.notification.NotificationListenerService.Ranking
import android.service.notification.NotificationListenerService.RankingMap
import android.service.notification.StatusBarNotification
import com.android.internal.annotations.VisibleForTesting

import com.android.systemui.statusbar.NotificationMediaManager
import com.android.systemui.statusbar.notification.NotificationFilter
import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager
import com.android.systemui.statusbar.notification.logging.NotifEvent
import com.android.systemui.statusbar.notification.logging.NotifLog
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier
import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_ALERTING
import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_PEOPLE
import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_SILENT
import com.android.systemui.statusbar.phone.NotificationGroupManager
import com.android.systemui.statusbar.policy.HeadsUpManager

import dagger.Lazy
import java.util.Objects
import java.util.ArrayList

import javax.inject.Inject

import kotlin.Comparator

import dagger.Lazy

private const val TAG = "NotifRankingManager"

/**
@@ -64,7 +56,8 @@ open class NotificationRankingManager @Inject constructor(
    private val headsUpManager: HeadsUpManager,
    private val notifFilter: NotificationFilter,
    private val notifLog: NotifLog,
    sectionsFeatureManager: NotificationSectionsFeatureManager
    sectionsFeatureManager: NotificationSectionsFeatureManager,
    private val peopleNotificationIdentifier: PeopleNotificationIdentifier
) {

    var rankingMap: RankingMap? = null
@@ -79,6 +72,9 @@ open class NotificationRankingManager @Inject constructor(
        val aRank = a.ranking.rank
        val bRank = b.ranking.rank

        val aIsPeople = a.isPeopleNotification()
        val bIsPeople = b.isPeopleNotification()

        val aMedia = isImportantMedia(a)
        val bMedia = isImportantMedia(b)

@@ -88,25 +84,19 @@ open class NotificationRankingManager @Inject constructor(
        val aHeadsUp = a.isRowHeadsUp
        val bHeadsUp = b.isRowHeadsUp

        if (usePeopleFiltering && a.isPeopleNotification() != b.isPeopleNotification()) {
            if (a.isPeopleNotification()) -1 else 1
        } else if (aHeadsUp != bHeadsUp) {
            if (aHeadsUp) -1 else 1
        } else if (aHeadsUp) {
        when {
            usePeopleFiltering && aIsPeople != bIsPeople -> if (aIsPeople) -1 else 1
            aHeadsUp != bHeadsUp -> if (aHeadsUp) -1 else 1
            // Provide consistent ranking with headsUpManager
            headsUpManager.compare(a, b)
        } else if (aMedia != bMedia) {
            aHeadsUp -> headsUpManager.compare(a, b)
            // Upsort current media notification.
            if (aMedia) -1 else 1
        } else if (aSystemMax != bSystemMax) {
            aMedia != bMedia -> if (aMedia) -1 else 1
            // Upsort PRIORITY_MAX system notifications
            if (aSystemMax) -1 else 1
        } else if (a.isHighPriority != b.isHighPriority) {
            -1 * java.lang.Boolean.compare(a.isHighPriority, b.isHighPriority)
        } else if (aRank != bRank) {
            aRank - bRank
        } else {
            nb.notification.`when`.compareTo(na.notification.`when`)
            aSystemMax != bSystemMax -> if (aSystemMax) -1 else 1
            a.isHighPriority != b.isHighPriority ->
                -1 * a.isHighPriority.compareTo(b.isHighPriority)
            aRank != bRank -> aRank - bRank
            else -> nb.notification.`when`.compareTo(na.notification.`when`)
        }
    }

@@ -138,10 +128,9 @@ open class NotificationRankingManager @Inject constructor(
        val c = entry.channel
        val n = entry.sbn.notification

        if (((n.isForegroundService && entry.ranking.importance >= IMPORTANCE_LOW) ||
        if ((n.isForegroundService && entry.ranking.importance >= IMPORTANCE_LOW) ||
                n.hasMediaSession() ||
            n.hasPerson() ||
            n.hasStyle(Notification.MessagingStyle::class.java))) {
                entry.isPeopleNotification()) {
            // Users who have long pressed and demoted to silent should not see the notification
            // in the top section
            if (c != null && c.hasUserSetImportance()) {
@@ -204,7 +193,7 @@ open class NotificationRankingManager @Inject constructor(
        isMedia: Boolean,
        isSystemMax: Boolean
    ) {
        if (usePeopleFiltering && entry.hasAssociatedPeople()) {
        if (usePeopleFiltering && entry.isPeopleNotification()) {
            entry.bucket = BUCKET_PEOPLE
        } else if (isHeadsUp || isMedia || isSystemMax || entry.isHighPriority) {
            entry.bucket = BUCKET_ALERTING
@@ -235,6 +224,11 @@ open class NotificationRankingManager @Inject constructor(
            }
        }
    }

    private fun NotificationEntry.isPeopleNotification() =
            sbn.isPeopleNotification()
    private fun StatusBarNotification.isPeopleNotification() =
            peopleNotificationIdentifier.isPeopleNotification(this)
}

// Convenience functions
@@ -245,16 +239,3 @@ private fun NotificationEntry.isSystemMax(): Boolean {
private fun StatusBarNotification.isSystemNotification(): Boolean {
    return "android" == packageName || "com.android.systemui" == packageName
}

private fun Notification.hasPerson(): Boolean {
    val people: ArrayList<Person> =
            (extras?.getParcelableArrayList(Notification.EXTRA_PEOPLE_LIST)) ?: ArrayList()
    return people.isNotEmpty()
}

private fun Notification.hasStyle(targetStyleClass: Class<*>): Boolean {
    return targetStyleClass == notificationStyle
}

private fun NotificationEntry.isPeopleNotification(): Boolean =
        sbn.notification.hasStyle(Notification.MessagingStyle::class.java)
+1 −1
Original line number Diff line number Diff line
@@ -318,7 +318,7 @@ public class NotificationSectionsManager implements StackScrollAlgorithm.Section
                }
                mParent.addView(mPeopleHubView, targetIndex);
                return true;
            } else if (currentHubIndex != targetIndex - 1) {
            } else if (currentHubIndex != targetIndex) {
                if (currentHubIndex < targetIndex) {
                    targetIndex--;
                }
+3 −1
Original line number Diff line number Diff line
@@ -85,6 +85,7 @@ import com.android.systemui.statusbar.notification.collection.NotificationRowBin
import com.android.systemui.statusbar.notification.collection.NotificationRowBinderImpl;
import com.android.systemui.statusbar.notification.logging.NotifLog;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
import com.android.systemui.statusbar.notification.row.RowInflaterTask;
@@ -228,7 +229,8 @@ public class NotificationEntryManagerTest extends SysuiTestCase {
                        mHeadsUpManager,
                        mock(NotificationFilter.class),
                        mNotifLog,
                        mock(NotificationSectionsFeatureManager.class)),
                        mock(NotificationSectionsFeatureManager.class),
                        mock(PeopleNotificationIdentifier.class)),
                mEnvironment
        );
        Dependency.get(InitController.class).executePostInitTasks();
+27 −52
Original line number Diff line number Diff line
@@ -20,7 +20,6 @@ import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager.IMPORTANCE_DEFAULT
import android.app.NotificationManager.IMPORTANCE_LOW
import android.app.Person
import android.service.notification.NotificationListenerService.RankingMap
import android.service.notification.StatusBarNotification
import android.testing.AndroidTestingRunner
@@ -36,6 +35,7 @@ import com.android.systemui.statusbar.NotificationMediaManager
import com.android.systemui.statusbar.notification.NotificationFilter
import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager
import com.android.systemui.statusbar.notification.logging.NotifLog
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier
import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_ALERTING
import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_SILENT
import com.android.systemui.statusbar.phone.NotificationGroupManager
@@ -52,62 +52,41 @@ import org.mockito.Mockito.mock

@SmallTest
@RunWith(AndroidTestingRunner::class)
class NotificationRankingManagerTest
    : SysuiTestCase() {
class NotificationRankingManagerTest : SysuiTestCase() {

    private var lazyMedia: Lazy<NotificationMediaManager> = Lazy {
        mock<NotificationMediaManager>(NotificationMediaManager::class.java)
    private val lazyMedia: Lazy<NotificationMediaManager> = Lazy {
        mock(NotificationMediaManager::class.java)
    }

    private val rankingManager = TestableNotificationRankingManager(
            lazyMedia,
            mock<NotificationGroupManager>(NotificationGroupManager::class.java),
            mock<HeadsUpManager>(HeadsUpManager::class.java),
            mock<NotificationFilter>(NotificationFilter::class.java),
            mock<NotifLog>(NotifLog::class.java),
            mock<NotificationSectionsFeatureManager>(NotificationSectionsFeatureManager::class.java)
    )
    private lateinit var personNotificationIdentifier: PeopleNotificationIdentifier
    private lateinit var rankingManager: TestableNotificationRankingManager

    @Before
    fun setup() {
        personNotificationIdentifier =
                mock(PeopleNotificationIdentifier::class.java)
        rankingManager = TestableNotificationRankingManager(
                lazyMedia,
                mock(NotificationGroupManager::class.java),
                mock(HeadsUpManager::class.java),
                mock(NotificationFilter::class.java),
                mock(NotifLog::class.java),
                mock(NotificationSectionsFeatureManager::class.java),
                personNotificationIdentifier
        )
    }

    @Test
    fun testPeopleNotification_isHighPriority() {
        val person = Person.Builder()
                .setName("name")
                .setKey("abc")
                .setUri("uri")
                .setBot(true)
                .build()

        val notification = Notification.Builder(mContext, "test")
                .addPerson(person)
                .build()

        val sbn = StatusBarNotification("pkg", "pkg", 0, "tag", 0, 0,
                notification, mContext.user, "", 0)

        val e = NotificationEntryBuilder()
                .setNotification(notification)
                .setSbn(sbn)
                .build()

        assertTrue(rankingManager.isHighPriority2(e))
    }

    @Test
    fun messagingStyleHighPriority() {

        val notif = Notification.Builder(mContext, "test")
                .setStyle(Notification.MessagingStyle(""))
                .build()

        val sbn = StatusBarNotification("pkg", "pkg", 0, "tag", 0, 0,
                notif, mContext.getUser(), "", 0)
        `when`(personNotificationIdentifier.isPeopleNotification(sbn)).thenReturn(true)

        val e = NotificationEntryBuilder()
                .setNotification(notif)
                .setNotification(notification)
                .setSbn(sbn)
                .build()

@@ -117,7 +96,7 @@ class NotificationRankingManagerTest
    @Test
    fun lowForegroundHighPriority() {
        val notification = mock(Notification::class.java)
        `when`<Boolean>(notification.isForegroundService).thenReturn(true)
        `when`(notification.isForegroundService).thenReturn(true)

        val sbn = StatusBarNotification("pkg", "pkg", 0, "tag", 0, 0,
                notification, mContext.user, "", 0)
@@ -136,15 +115,7 @@ class NotificationRankingManagerTest

    @Test
    fun userChangeTrumpsHighPriorityCharacteristics() {
        val person = Person.Builder()
                .setName("name")
                .setKey("abc")
                .setUri("uri")
                .setBot(true)
                .build()

        val notification = Notification.Builder(mContext, "test")
                .addPerson(person)
                .setStyle(Notification.MessagingStyle(""))
                .setFlag(Notification.FLAG_FOREGROUND_SERVICE, true)
                .build()
@@ -152,6 +123,8 @@ class NotificationRankingManagerTest
        val sbn = StatusBarNotification("pkg", "pkg", 0, "tag", 0, 0,
                notification, mContext.user, "", 0)

        `when`(personNotificationIdentifier.isPeopleNotification(sbn)).thenReturn(true)

        val channel = NotificationChannel("a", "a", IMPORTANCE_LOW)
        channel.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE)

@@ -297,14 +270,16 @@ class NotificationRankingManagerTest
        headsUpManager: HeadsUpManager,
        filter: NotificationFilter,
        notifLog: NotifLog,
        sectionsFeatureManager: NotificationSectionsFeatureManager
        sectionsFeatureManager: NotificationSectionsFeatureManager,
        peopleNotificationIdentifier: PeopleNotificationIdentifier
    ) : NotificationRankingManager(
        mediaManager,
        groupManager,
        headsUpManager,
        filter,
        notifLog,
        sectionsFeatureManager
        sectionsFeatureManager,
        peopleNotificationIdentifier
    ) {

        fun isHighPriority2(e: NotificationEntry): Boolean {
+3 −1
Original line number Diff line number Diff line
@@ -74,6 +74,7 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationRankingManager;
import com.android.systemui.statusbar.notification.logging.NotifLog;
import com.android.systemui.statusbar.notification.people.PeopleHubSectionFooterViewAdapter;
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.FooterView;
import com.android.systemui.statusbar.notification.row.NotificationBlockingHelperManager;
@@ -164,7 +165,8 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase {
                        mHeadsUpManager,
                        mock(NotificationFilter.class),
                        mock(NotifLog.class),
                        mock(NotificationSectionsFeatureManager.class)
                        mock(NotificationSectionsFeatureManager.class),
                        mock(PeopleNotificationIdentifier.class)
                ),
                mock(NotificationEntryManager.KeyguardEnvironment.class));
        mDependency.injectTestDependency(NotificationEntryManager.class, mEntryManager);