• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * 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.provider;
18 
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.app.Notification;
22 import android.app.NotificationManager;
23 
24 import com.android.systemui.dagger.SysUISingleton;
25 import com.android.systemui.statusbar.notification.collection.GroupEntry;
26 import com.android.systemui.statusbar.notification.collection.PipelineEntry;
27 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
28 import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
29 import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
30 import com.android.systemui.statusbar.notification.shared.NotificationBundleUi;
31 
32 import java.util.List;
33 
34 import javax.inject.Inject;
35 
36 /**
37  * Determines whether a notification is considered 'high priority'.
38  *
39  * Notifications that are high priority are visible on the lock screen/status bar and in the top
40  * section in the shade.
41  */
42 @SysUISingleton
43 public class HighPriorityProvider {
44     private final PeopleNotificationIdentifier mPeopleNotificationIdentifier;
45     private final GroupMembershipManager mGroupMembershipManager;
46 
47     @Inject
HighPriorityProvider( PeopleNotificationIdentifier peopleNotificationIdentifier, GroupMembershipManager groupManager)48     public HighPriorityProvider(
49             PeopleNotificationIdentifier peopleNotificationIdentifier,
50             GroupMembershipManager groupManager) {
51         mPeopleNotificationIdentifier = peopleNotificationIdentifier;
52         mGroupMembershipManager = groupManager;
53     }
54 
55     /**
56      * @return true if the PipelineEntry is high priority, else false
57      *
58      * A NotificationEntry is considered high priority if it:
59      *  - has importance greater than or equal to IMPORTANCE_DEFAULT
60      *  OR
61      *  - their importance has NOT been set to a low priority option by the user AND the
62      *  notification fulfills one of the following:
63      *      - has a person associated with it
64      *      - has a media session associated with it
65      *      - has messaging style
66      *
67      * A GroupEntry is considered high priority if its representativeEntry (summary) or any of its
68      * children are high priority.
69      */
isHighPriority(@ullable PipelineEntry entry)70     public boolean isHighPriority(@Nullable PipelineEntry entry) {
71         return isHighPriority(entry, /* allowImplicit = */ true);
72     }
73 
74     /**
75      * @return true if the PipelineEntry is explicitly high priority, else false
76      *
77      * A NotificationEntry is considered explicitly high priority if has importance greater than or
78      * equal to IMPORTANCE_DEFAULT.
79      *
80      * A GroupEntry is considered explicitly high priority if its representativeEntry (summary) or
81      * any of its children are explicitly high priority.
82      */
isExplicitlyHighPriority(@ullable PipelineEntry entry)83     public boolean isExplicitlyHighPriority(@Nullable PipelineEntry entry) {
84         return isHighPriority(entry, /* allowImplicit= */ false);
85     }
86 
isHighPriority(@ullable PipelineEntry entry, boolean allowImplicit)87     private boolean isHighPriority(@Nullable PipelineEntry entry, boolean allowImplicit) {
88         if (entry == null) {
89             return false;
90         }
91 
92         final NotificationEntry notifEntry = entry.getRepresentativeEntry();
93         if (notifEntry == null) {
94             return false;
95         }
96 
97         return notifEntry.getRanking().getImportance() >= NotificationManager.IMPORTANCE_DEFAULT
98                 || (allowImplicit && hasHighPriorityCharacteristics(notifEntry))
99                 || hasHighPriorityChild(entry, allowImplicit);
100     }
101 
102     /**
103      * @return true if the PipelineEntry is high priority conversation, else false
104      */
isHighPriorityConversation(@onNull PipelineEntry entry)105     public boolean isHighPriorityConversation(@NonNull PipelineEntry entry) {
106         final NotificationEntry notifEntry = entry.getRepresentativeEntry();
107         if (notifEntry == null) {
108             return  false;
109         }
110 
111         if (!isPeopleNotification(notifEntry)) {
112             return false;
113         }
114 
115         if (notifEntry.getRanking().getImportance() >= NotificationManager.IMPORTANCE_DEFAULT) {
116             return true;
117         }
118 
119         return isNotificationEntryWithAtLeastOneImportantChild(entry);
120     }
121 
isNotificationEntryWithAtLeastOneImportantChild(@onNull PipelineEntry entry)122     private boolean isNotificationEntryWithAtLeastOneImportantChild(@NonNull PipelineEntry entry) {
123         if (!(entry instanceof GroupEntry)) {
124             return false;
125         }
126         final GroupEntry groupEntry = (GroupEntry) entry;
127         return groupEntry.getChildren().stream().anyMatch(
128                 childEntry ->
129                         childEntry.getRanking().getImportance()
130                                 >= NotificationManager.IMPORTANCE_DEFAULT);
131     }
132 
133     /**
134      * Returns whether the given ListEntry has a high priority child or is in a group with a child
135      * that's high priority
136      */
hasHighPriorityChild(PipelineEntry entry, boolean allowImplicit)137     private boolean hasHighPriorityChild(PipelineEntry entry, boolean allowImplicit) {
138         if (NotificationBundleUi.isEnabled()) {
139             GroupEntry representativeGroupEntry = null;
140             if (entry instanceof GroupEntry) {
141                 representativeGroupEntry = (GroupEntry) entry;
142             } else if (entry instanceof NotificationEntry){
143                 final NotificationEntry notificationEntry = entry.getRepresentativeEntry();
144                 if (notificationEntry.getParent() != null
145                         && notificationEntry.getParent() instanceof GroupEntry parent
146                         && parent.getSummary() != null
147                         && parent.getSummary() == notificationEntry) {
148                     representativeGroupEntry = parent;
149                 }
150             }
151             return representativeGroupEntry != null &&
152                     representativeGroupEntry.getChildren().stream().anyMatch(
153                             childEntry -> isHighPriority(childEntry, allowImplicit));
154 
155         } else {
156             if (entry instanceof NotificationEntry
157                     && !mGroupMembershipManager.isGroupSummary((NotificationEntry) entry)) {
158                 return false;
159             }
160             List<NotificationEntry> children = mGroupMembershipManager.getChildren(entry);
161             if (children != null) {
162                 for (NotificationEntry child : children) {
163                     if (child != entry && isHighPriority(child, allowImplicit)) {
164                         return true;
165                     }
166                 }
167             }
168             return false;
169         }
170     }
171 
hasHighPriorityCharacteristics(NotificationEntry entry)172     private boolean hasHighPriorityCharacteristics(NotificationEntry entry) {
173         return !hasUserSetImportance(entry)
174                 && (entry.getSbn().getNotification().isMediaNotification()
175                 || isPeopleNotification(entry)
176                 || isMessagingStyle(entry));
177     }
178 
isMessagingStyle(NotificationEntry entry)179     private boolean isMessagingStyle(NotificationEntry entry) {
180         return entry.getSbn().getNotification().isStyle(Notification.MessagingStyle.class);
181     }
182 
isPeopleNotification(NotificationEntry entry)183     private boolean isPeopleNotification(NotificationEntry entry) {
184         return mPeopleNotificationIdentifier.getPeopleNotificationType(entry)
185                 != PeopleNotificationIdentifier.TYPE_NON_PERSON;
186     }
187 
hasUserSetImportance(NotificationEntry entry)188     private boolean hasUserSetImportance(NotificationEntry entry) {
189         return entry.getRanking().getChannel() != null
190                 && entry.getRanking().getChannel().hasUserSetImportance();
191     }
192 }
193