• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License
15  */
16 
17 package com.android.systemui.statusbar.notification.collection.coordinator
18 
19 import com.android.systemui.statusbar.notification.collection.ListEntry
20 import com.android.systemui.statusbar.notification.collection.NotifPipeline
21 import com.android.systemui.statusbar.notification.collection.NotificationEntry
22 import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope
23 import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeRenderListListener
24 import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifComparator
25 import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifPromoter
26 import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner
27 import com.android.systemui.statusbar.notification.collection.render.NodeController
28 import com.android.systemui.statusbar.notification.dagger.PeopleHeader
29 import com.android.systemui.statusbar.notification.icon.ConversationIconManager
30 import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier
31 import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier.Companion.PeopleNotificationType
32 import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier.Companion.TYPE_NON_PERSON
33 import com.android.systemui.statusbar.notification.stack.BUCKET_PEOPLE
34 import javax.inject.Inject
35 
36 /**
37  * A Conversation/People Coordinator that:
38  * - Elevates important conversation notifications
39  * - Puts conversations into its own people section. @see [NotifCoordinators] for section ordering.
40  */
41 @CoordinatorScope
42 class ConversationCoordinator @Inject constructor(
43     private val peopleNotificationIdentifier: PeopleNotificationIdentifier,
44     private val conversationIconManager: ConversationIconManager,
45     @PeopleHeader peopleHeaderController: NodeController
46 ) : Coordinator {
47 
48     private val promotedEntriesToSummaryOfSameChannel =
49         mutableMapOf<NotificationEntry, NotificationEntry>()
50 
51     private val onBeforeRenderListListener = OnBeforeRenderListListener { _ ->
52         val unimportantSummaries = promotedEntriesToSummaryOfSameChannel
53             .mapNotNull { (promoted, summary) ->
54                 val originalGroup = summary.parent
55                 when {
56                     originalGroup == null -> null
57                     originalGroup == promoted.parent -> null
58                     originalGroup.parent == null -> null
59                     originalGroup.summary != summary -> null
60                     originalGroup.children.any { it.channel == summary.channel } -> null
61                     else -> summary.key
62                 }
63             }
64         conversationIconManager.setUnimportantConversations(unimportantSummaries)
65         promotedEntriesToSummaryOfSameChannel.clear()
66     }
67 
68     private val notificationPromoter = object : NotifPromoter(TAG) {
69         override fun shouldPromoteToTopLevel(entry: NotificationEntry): Boolean {
70             val shouldPromote = entry.channel?.isImportantConversation == true
71             if (shouldPromote) {
72                 val summary = entry.parent?.summary
73                 if (summary != null && entry.channel == summary.channel) {
74                     promotedEntriesToSummaryOfSameChannel[entry] = summary
75                 }
76             }
77             return shouldPromote
78         }
79     }
80 
81     val sectioner = object : NotifSectioner("People", BUCKET_PEOPLE) {
82         override fun isInSection(entry: ListEntry): Boolean =
83                 isConversation(entry)
84 
85         override fun getComparator() = object : NotifComparator("People") {
86             override fun compare(entry1: ListEntry, entry2: ListEntry): Int {
87                 val type1 = getPeopleType(entry1)
88                 val type2 = getPeopleType(entry2)
89                 return type2.compareTo(type1)
90             }
91         }
92 
93         override fun getHeaderNodeController() =
94                 // TODO: remove SHOW_ALL_SECTIONS, this redundant method, and peopleHeaderController
95                 if (RankingCoordinator.SHOW_ALL_SECTIONS) peopleHeaderController else null
96     }
97 
98     override fun attach(pipeline: NotifPipeline) {
99         pipeline.addPromoter(notificationPromoter)
100         pipeline.addOnBeforeRenderListListener(onBeforeRenderListListener)
101     }
102 
103     private fun isConversation(entry: ListEntry): Boolean =
104         getPeopleType(entry) != TYPE_NON_PERSON
105 
106     @PeopleNotificationType
107     private fun getPeopleType(entry: ListEntry): Int =
108         entry.representativeEntry?.let {
109             peopleNotificationIdentifier.getPeopleNotificationType(it)
110         } ?: TYPE_NON_PERSON
111 
112     companion object {
113         private const val TAG = "ConversationCoordinator"
114     }
115 }
116