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

Commit 548a77ae authored by Automerger Merge Worker's avatar Automerger Merge Worker
Browse files

Merge "Treat groups of conversations as a conversation" into rvc-dev am: 1e75b1f5

Change-Id: I988da89e79279a78d544936ab3aed26a8b295545
parents 77bfc2fc 1e75b1f5
Loading
Loading
Loading
Loading
+13 −10
Original line number Original line Diff line number Diff line
@@ -27,6 +27,9 @@ import com.android.systemui.statusbar.notification.NotificationFilter
import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager
import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager
import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider
import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier.Companion.TYPE_IMPORTANT_PERSON
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier.Companion.TYPE_NON_PERSON
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier.Companion.TYPE_PERSON
import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_ALERTING
import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_ALERTING
import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_HEADS_UP
import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_HEADS_UP
import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_PEOPLE
import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_PEOPLE
@@ -72,11 +75,14 @@ open class NotificationRankingManager @Inject constructor(
        val aRank = a.ranking.rank
        val aRank = a.ranking.rank
        val bRank = b.ranking.rank
        val bRank = b.ranking.rank


        val aIsPeople = a.isPeopleNotification()
        val aPersonType = a.getPeopleNotificationType()
        val bIsPeople = b.isPeopleNotification()
        val bPersonType = b.getPeopleNotificationType()


        val aIsImportantPeople = a.isImportantPeopleNotification()
        val aIsPeople = aPersonType == TYPE_PERSON
        val bIsImportantPeople = b.isImportantPeopleNotification()
        val bIsPeople = bPersonType == TYPE_PERSON

        val aIsImportantPeople = aPersonType == TYPE_IMPORTANT_PERSON
        val bIsImportantPeople = bPersonType == TYPE_IMPORTANT_PERSON


        val aMedia = isImportantMedia(a)
        val aMedia = isImportantMedia(a)
        val bMedia = isImportantMedia(b)
        val bMedia = isImportantMedia(b)
@@ -165,7 +171,7 @@ open class NotificationRankingManager @Inject constructor(
    ) {
    ) {
        if (usePeopleFiltering && isHeadsUp) {
        if (usePeopleFiltering && isHeadsUp) {
            entry.bucket = BUCKET_HEADS_UP
            entry.bucket = BUCKET_HEADS_UP
        } else if (usePeopleFiltering && entry.isPeopleNotification()) {
        } else if (usePeopleFiltering && entry.getPeopleNotificationType() != TYPE_NON_PERSON) {
            entry.bucket = BUCKET_PEOPLE
            entry.bucket = BUCKET_PEOPLE
        } else if (isHeadsUp || isMedia || isSystemMax || entry.isHighPriority()) {
        } else if (isHeadsUp || isMedia || isSystemMax || entry.isHighPriority()) {
            entry.bucket = BUCKET_ALERTING
            entry.bucket = BUCKET_ALERTING
@@ -198,11 +204,8 @@ open class NotificationRankingManager @Inject constructor(
        }
        }
    }
    }


    private fun NotificationEntry.isPeopleNotification() =
    private fun NotificationEntry.getPeopleNotificationType() =
            peopleNotificationIdentifier.isPeopleNotification(sbn, ranking)
            peopleNotificationIdentifier.getPeopleNotificationType(sbn, ranking)

    private fun NotificationEntry.isImportantPeopleNotification() =
            peopleNotificationIdentifier.isImportantPeopleNotification(sbn, ranking)


    private fun NotificationEntry.isHighPriority() =
    private fun NotificationEntry.isHighPriority() =
            highPriorityProvider.isHighPriority(this)
            highPriorityProvider.isHighPriority(this)
+2 −2
Original line number Original line Diff line number Diff line
@@ -103,8 +103,8 @@ public class HighPriorityProvider {
    }
    }


    private boolean isPeopleNotification(NotificationEntry entry) {
    private boolean isPeopleNotification(NotificationEntry entry) {
        return mPeopleNotificationIdentifier.isPeopleNotification(
        return mPeopleNotificationIdentifier.getPeopleNotificationType(
                entry.getSbn(), entry.getRanking());
                entry.getSbn(), entry.getRanking()) != PeopleNotificationIdentifier.TYPE_NON_PERSON;
    }
    }


    private boolean hasUserSetImportance(NotificationEntry entry) {
    private boolean hasUserSetImportance(NotificationEntry entry) {
+3 −3
Original line number Original line Diff line number Diff line
@@ -16,7 +16,6 @@


package com.android.systemui.statusbar.notification.people
package com.android.systemui.statusbar.notification.people


import android.app.PendingIntent
import android.graphics.drawable.Drawable
import android.graphics.drawable.Drawable


/**
/**
@@ -45,10 +44,11 @@ data class PeopleHubModel(val people: Collection<PersonModel>)
/** `Model` for a single "Person" in PeopleHub. */
/** `Model` for a single "Person" in PeopleHub. */
data class PersonModel(
data class PersonModel(
    val key: PersonKey,
    val key: PersonKey,
    val userId: Int,
    // TODO: these should live in the ViewModel
    val name: CharSequence,
    val name: CharSequence,
    val avatar: Drawable,
    val avatar: Drawable,
    val clickRunnable: Runnable,
    val clickRunnable: Runnable
    val userId: Int
)
)


/** Unique identifier for a Person in PeopleHub. */
/** Unique identifier for a Person in PeopleHub. */
+54 −35
Original line number Original line Diff line number Diff line
@@ -20,9 +20,7 @@ import android.app.Notification
import android.content.Context
import android.content.Context
import android.content.pm.LauncherApps
import android.content.pm.LauncherApps
import android.content.pm.PackageManager
import android.content.pm.PackageManager
import android.content.pm.ShortcutInfo
import android.content.pm.UserInfo
import android.content.pm.UserInfo
import android.graphics.drawable.BitmapDrawable
import android.graphics.drawable.Drawable
import android.graphics.drawable.Drawable
import android.os.UserManager
import android.os.UserManager
import android.service.notification.NotificationListenerService
import android.service.notification.NotificationListenerService
@@ -45,6 +43,7 @@ import com.android.systemui.statusbar.NotificationLockscreenUserManager
import com.android.systemui.statusbar.notification.NotificationEntryListener
import com.android.systemui.statusbar.notification.NotificationEntryListener
import com.android.systemui.statusbar.notification.NotificationEntryManager
import com.android.systemui.statusbar.notification.NotificationEntryManager
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier.Companion.TYPE_NON_PERSON
import com.android.systemui.statusbar.policy.ExtensionController
import com.android.systemui.statusbar.policy.ExtensionController
import java.util.ArrayDeque
import java.util.ArrayDeque
import java.util.concurrent.Executor
import java.util.concurrent.Executor
@@ -79,7 +78,7 @@ class NotificationPersonExtractorPluginBoundary @Inject constructor(


    override fun extractPerson(sbn: StatusBarNotification) =
    override fun extractPerson(sbn: StatusBarNotification) =
            plugin?.extractPerson(sbn)?.run {
            plugin?.extractPerson(sbn)?.run {
                PersonModel(key, name, avatar, clickRunnable, sbn.user.identifier)
                PersonModel(key, sbn.user.identifier, name, avatar, clickRunnable)
            }
            }


    override fun extractPersonKey(sbn: StatusBarNotification) = plugin?.extractPersonKey(sbn)
    override fun extractPersonKey(sbn: StatusBarNotification) = plugin?.extractPersonKey(sbn)
@@ -93,9 +92,9 @@ class PeopleHubDataSourceImpl @Inject constructor(
    private val notificationEntryManager: NotificationEntryManager,
    private val notificationEntryManager: NotificationEntryManager,
    private val extractor: NotificationPersonExtractor,
    private val extractor: NotificationPersonExtractor,
    private val userManager: UserManager,
    private val userManager: UserManager,
        private val launcherApps: LauncherApps,
    launcherApps: LauncherApps,
        private val packageManager: PackageManager,
    packageManager: PackageManager,
        private val c: Context,
    context: Context,
    private val notificationListener: NotificationListener,
    private val notificationListener: NotificationListener,
    @Background private val bgExecutor: Executor,
    @Background private val bgExecutor: Executor,
    @Main private val mainExecutor: Executor,
    @Main private val mainExecutor: Executor,
@@ -106,10 +105,19 @@ class PeopleHubDataSourceImpl @Inject constructor(
    private var userChangeSubscription: Subscription? = null
    private var userChangeSubscription: Subscription? = null
    private val dataListeners = mutableListOf<DataListener<PeopleHubModel>>()
    private val dataListeners = mutableListOf<DataListener<PeopleHubModel>>()
    private val peopleHubManagerForUser = SparseArray<PeopleHubManager>()
    private val peopleHubManagerForUser = SparseArray<PeopleHubManager>()
    val context: Context = c.applicationContext

    val iconFactory = ConversationIconFactory(context, launcherApps, packageManager,
    private val iconFactory = run {
            IconDrawableFactory.newInstance(context), context.resources.getDimensionPixelSize(
        val appContext = context.applicationContext
            R.dimen.notification_guts_conversation_icon_size))
        ConversationIconFactory(
                appContext,
                launcherApps,
                packageManager,
                IconDrawableFactory.newInstance(appContext),
                appContext.resources.getDimensionPixelSize(
                        R.dimen.notification_guts_conversation_icon_size
                )
        )
    }


    private val notificationEntryListener = object : NotificationEntryListener {
    private val notificationEntryListener = object : NotificationEntryListener {
        override fun onEntryInflated(entry: NotificationEntry) = addVisibleEntry(entry)
        override fun onEntryInflated(entry: NotificationEntry) = addVisibleEntry(entry)
@@ -206,7 +214,8 @@ class PeopleHubDataSourceImpl @Inject constructor(
    }
    }


    private fun NotificationEntry.extractPerson(): PersonModel? {
    private fun NotificationEntry.extractPerson(): PersonModel? {
        if (!peopleNotificationIdentifier.isPeopleNotification(sbn, ranking)) {
        val type = peopleNotificationIdentifier.getPeopleNotificationType(sbn, ranking)
        if (type == TYPE_NON_PERSON) {
            return null
            return null
        }
        }
        val clickRunnable = Runnable { notificationListener.unsnoozeNotification(key) }
        val clickRunnable = Runnable { notificationListener.unsnoozeNotification(key) }
@@ -215,23 +224,34 @@ class PeopleHubDataSourceImpl @Inject constructor(
                ?: extras.getString(Notification.EXTRA_CONVERSATION_TITLE)
                ?: extras.getString(Notification.EXTRA_CONVERSATION_TITLE)
                ?: extras.getString(Notification.EXTRA_TITLE)
                ?: extras.getString(Notification.EXTRA_TITLE)
                ?: return null
                ?: return null
        val drawable = ranking.shortcutInfo?.getIcon(iconFactory, sbn, ranking)
        val drawable = ranking.getIcon(iconFactory, sbn)
                ?: iconFactory.getConversationDrawable(extractAvatarFromRow(this), sbn.packageName,
                ?: iconFactory.getConversationDrawable(
                        sbn.uid, ranking.channel.isImportantConversation)
                        extractAvatarFromRow(this),

                        sbn.packageName,
        return PersonModel(key, name, drawable, clickRunnable, sbn.user.identifier)
                        sbn.uid,
    }
                        ranking.channel.isImportantConversation

                )
    private fun ShortcutInfo.getIcon(iconFactory: ConversationIconFactory,
        return PersonModel(key, sbn.user.identifier, name, drawable, clickRunnable)
                                     sbn: StatusBarNotification,
    }
                                     ranking: NotificationListenerService.Ranking): Drawable? {

        return iconFactory.getConversationDrawable(ranking.shortcutInfo, sbn.packageName, sbn.uid,
    private fun NotificationListenerService.Ranking.getIcon(
                ranking.channel.isImportantConversation)
        iconFactory: ConversationIconFactory,
    }
        sbn: StatusBarNotification

    ): Drawable? =
    private fun NotificationEntry.extractPersonKey(): PersonKey? =
            shortcutInfo?.let { shortcutInfo ->
                iconFactory.getConversationDrawable(
                        shortcutInfo,
                        sbn.packageName,
                        sbn.uid,
                        channel.isImportantConversation
                )
            }

    private fun NotificationEntry.extractPersonKey(): PersonKey? {
        // TODO migrate to shortcut id when snoozing is conversation wide
        // TODO migrate to shortcut id when snoozing is conversation wide
            if (peopleNotificationIdentifier.isPeopleNotification(sbn, ranking)) key else null
        val type = peopleNotificationIdentifier.getPeopleNotificationType(sbn, ranking)
        return if (type != TYPE_NON_PERSON) key else null
    }
}
}


private fun NotificationLockscreenUserManager.registerListener(
private fun NotificationLockscreenUserManager.registerListener(
@@ -303,4 +323,3 @@ fun extractAvatarFromRow(entry: NotificationEntry): Drawable? =
                            ?.drawable
                            ?.drawable
                }
                }
                ?.firstOrNull()
                ?.firstOrNull()
+81 −8
Original line number Original line Diff line number Diff line
@@ -16,24 +16,97 @@


package com.android.systemui.statusbar.notification.people
package com.android.systemui.statusbar.notification.people


import android.annotation.IntDef
import android.service.notification.NotificationListenerService.Ranking
import android.service.notification.NotificationListenerService.Ranking
import android.service.notification.StatusBarNotification
import android.service.notification.StatusBarNotification
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier.Companion.PeopleNotificationType
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier.Companion.TYPE_IMPORTANT_PERSON
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier.Companion.TYPE_NON_PERSON
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier.Companion.TYPE_PERSON
import com.android.systemui.statusbar.phone.NotificationGroupManager
import javax.inject.Inject
import javax.inject.Inject
import javax.inject.Singleton
import javax.inject.Singleton
import kotlin.math.max


interface PeopleNotificationIdentifier {
interface PeopleNotificationIdentifier {
    fun isPeopleNotification(sbn: StatusBarNotification, ranking: Ranking): Boolean

    fun isImportantPeopleNotification(sbn: StatusBarNotification, ranking: Ranking): Boolean
    /**
     * Identifies if the given notification can be classified as a "People" notification.
     *
     * @return [TYPE_NON_PERSON] if not a people notification, [TYPE_PERSON] if a standard people
     *  notification, and [TYPE_IMPORTANT_PERSON] if an "important" people notification.
     */
    @PeopleNotificationType
    fun getPeopleNotificationType(sbn: StatusBarNotification, ranking: Ranking): Int

    companion object {

        @Retention(AnnotationRetention.SOURCE)
        @IntDef(prefix = ["TYPE_"], value = [TYPE_NON_PERSON, TYPE_PERSON, TYPE_IMPORTANT_PERSON])
        annotation class PeopleNotificationType

        const val TYPE_NON_PERSON = 0
        const val TYPE_PERSON = 1
        const val TYPE_IMPORTANT_PERSON = 2
    }
}
}


@Singleton
@Singleton
class PeopleNotificationIdentifierImpl @Inject constructor(
class PeopleNotificationIdentifierImpl @Inject constructor(
    private val personExtractor: NotificationPersonExtractor
    private val personExtractor: NotificationPersonExtractor,
    private val groupManager: NotificationGroupManager
) : PeopleNotificationIdentifier {
) : PeopleNotificationIdentifier {


    override fun isPeopleNotification(sbn: StatusBarNotification, ranking: Ranking) =
    @PeopleNotificationType
            ranking.isConversation || personExtractor.isPersonNotification(sbn)
    override fun getPeopleNotificationType(sbn: StatusBarNotification, ranking: Ranking): Int =
            when (val type = ranking.personTypeInfo) {
                TYPE_IMPORTANT_PERSON -> TYPE_IMPORTANT_PERSON
                else -> {
                    when (val type = upperBound(type, extractPersonTypeInfo(sbn))) {
                        TYPE_IMPORTANT_PERSON -> TYPE_IMPORTANT_PERSON
                        else -> upperBound(type, getPeopleTypeOfSummary(sbn))
                    }
                }
            }

    /**
     * Given two [PeopleNotificationType]s, determine the upper bound. Used to constrain a
     * notification to a type given multiple signals, i.e. notification groups, where each child
     * has a [PeopleNotificationType] that is used to constrain the summary.
     */
    @PeopleNotificationType
    private fun upperBound(
        @PeopleNotificationType type: Int,
        @PeopleNotificationType other: Int
    ): Int =
            max(type, other)

    private val Ranking.personTypeInfo
        get() = when {
            channel.isImportantConversation -> TYPE_IMPORTANT_PERSON
            isConversation -> TYPE_PERSON
            else -> TYPE_NON_PERSON
        }

    private fun extractPersonTypeInfo(sbn: StatusBarNotification) =
            if (personExtractor.isPersonNotification(sbn)) TYPE_PERSON else TYPE_NON_PERSON


    override fun isImportantPeopleNotification(sbn: StatusBarNotification, ranking: Ranking) =
    private fun getPeopleTypeOfSummary(statusBarNotification: StatusBarNotification): Int {
            isPeopleNotification(sbn, ranking) && ranking.channel.isImportantConversation
        if (!groupManager.isSummaryOfGroup(statusBarNotification)) {
            return TYPE_NON_PERSON
        }

        val childTypes = groupManager.getLogicalChildren(statusBarNotification)
                ?.asSequence()
                ?.map { getPeopleNotificationType(it.sbn, it.ranking) }
                ?: return TYPE_NON_PERSON

        var groupType = TYPE_NON_PERSON
        for (childType in childTypes) {
            groupType = upperBound(groupType, childType)
            if (groupType == TYPE_IMPORTANT_PERSON)
                break
        }
        return groupType
    }
}
}
Loading