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