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