Loading packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManager.kt +13 −10 Original line number Original line Diff line number Diff line Loading @@ -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 Loading Loading @@ -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) Loading Loading @@ -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 Loading Loading @@ -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) Loading packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/HighPriorityProvider.java +2 −2 Original line number Original line Diff line number Diff line Loading @@ -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) { Loading packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHub.kt +3 −3 Original line number Original line Diff line number Diff line Loading @@ -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 /** /** Loading Loading @@ -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. */ Loading packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubNotificationListener.kt +54 −35 Original line number Original line Diff line number Diff line Loading @@ -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 Loading @@ -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 Loading Loading @@ -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) Loading @@ -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, Loading @@ -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) Loading Loading @@ -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) } Loading @@ -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( Loading Loading @@ -303,4 +323,3 @@ fun extractAvatarFromRow(entry: NotificationEntry): Drawable? = ?.drawable ?.drawable } } ?.firstOrNull() ?.firstOrNull() packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleNotificationIdentifier.kt +81 −8 Original line number Original line Diff line number Diff line Loading @@ -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
packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManager.kt +13 −10 Original line number Original line Diff line number Diff line Loading @@ -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 Loading Loading @@ -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) Loading Loading @@ -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 Loading Loading @@ -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) Loading
packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/HighPriorityProvider.java +2 −2 Original line number Original line Diff line number Diff line Loading @@ -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) { Loading
packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHub.kt +3 −3 Original line number Original line Diff line number Diff line Loading @@ -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 /** /** Loading Loading @@ -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. */ Loading
packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubNotificationListener.kt +54 −35 Original line number Original line Diff line number Diff line Loading @@ -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 Loading @@ -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 Loading Loading @@ -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) Loading @@ -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, Loading @@ -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) Loading Loading @@ -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) } Loading @@ -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( Loading Loading @@ -303,4 +323,3 @@ fun extractAvatarFromRow(entry: NotificationEntry): Drawable? = ?.drawable ?.drawable } } ?.firstOrNull() ?.firstOrNull()
packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleNotificationIdentifier.kt +81 −8 Original line number Original line Diff line number Diff line Loading @@ -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 } } }