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.interruption; 18 19 import androidx.annotation.NonNull; 20 21 import com.android.systemui.statusbar.notification.collection.NotificationEntry; 22 23 /** 24 * Provides bubble-up and heads-up state for notification entries. 25 * 26 * When a notification is heads-up when dozing, this is also called "pulsing." 27 */ 28 public interface NotificationInterruptStateProvider { 29 /** 30 * Enum representing a decision of whether to show a full screen intent. While many of the 31 * relevant properties could overlap, the decision represents the deciding factor for whether 32 * the full screen intent should or shouldn't launch. 33 */ 34 enum FullScreenIntentDecision { 35 /** 36 * Full screen intents are disabled. 37 */ 38 NO_FSI_SHOW_STICKY_HUN(false), 39 /** 40 * No full screen intent included, so there is nothing to show. 41 */ 42 NO_FULL_SCREEN_INTENT(false), 43 /** 44 * Suppressed by DND settings. 45 */ 46 NO_FSI_SUPPRESSED_BY_DND(false), 47 /** 48 * Full screen intent was suppressed *only* by DND, and if not for DND would have shown. We 49 * track this separately in order to allow the intent to be shown if the DND decision 50 * changes. 51 */ 52 NO_FSI_SUPPRESSED_ONLY_BY_DND(false), 53 /** 54 * Notification importance not high enough to show FSI. 55 */ 56 NO_FSI_NOT_IMPORTANT_ENOUGH(false), 57 /** 58 * Notification should not FSI due to having suppressive GroupAlertBehavior. This blocks a 59 * potentially malicious use of flags that previously allowed apps to escalate a HUN to an 60 * FSI even while the device was unlocked. 61 */ 62 NO_FSI_SUPPRESSIVE_GROUP_ALERT_BEHAVIOR(false), 63 /** 64 * Notification should not FSI due to having suppressive BubbleMetadata. This blocks a 65 * potentially malicious use of flags that previously allowed apps to escalate a HUN to an 66 * FSI even while the device was unlocked. 67 */ 68 NO_FSI_SUPPRESSIVE_BUBBLE_METADATA(false), 69 /** 70 * Notification should not FSI due to being explicitly silent. 71 * see {@link android.app.Notification#isSilent} 72 */ 73 NO_FSI_SUPPRESSIVE_SILENT_NOTIFICATION(false), 74 /** 75 * Device screen is off, so the FSI should launch. 76 */ 77 FSI_DEVICE_NOT_INTERACTIVE(true), 78 /** 79 * Device is currently dreaming, so FSI should launch. 80 */ 81 FSI_DEVICE_IS_DREAMING(true), 82 /** 83 * Keyguard is showing, so FSI should launch. 84 */ 85 FSI_KEYGUARD_SHOWING(true), 86 /** 87 * The notification is expected to show heads-up, so FSI is not needed. 88 */ 89 NO_FSI_EXPECTED_TO_HUN(false), 90 /** 91 * The notification is not expected to HUN while the keyguard is occluded, so show FSI. 92 */ 93 FSI_KEYGUARD_OCCLUDED(true), 94 /** 95 * The notification is not expected to HUN when the keyguard is showing but not occluded, 96 * which likely means that the shade is showing over the lockscreen; show FSI in this case. 97 */ 98 FSI_LOCKED_SHADE(true), 99 /** 100 * FSI requires keyguard to be showing, but there is no keyguard. This is a (potentially 101 * malicious) warning state where we suppress the FSI because the device is in use knowing 102 * that the HUN will probably not display. 103 */ 104 NO_FSI_NO_HUN_OR_KEYGUARD(false), 105 /** 106 * The notification is coming from a suspended packages, so FSI is suppressed. 107 */ 108 NO_FSI_SUSPENDED(false), 109 /** 110 * The device is not provisioned, launch FSI. 111 */ 112 FSI_NOT_PROVISIONED(true), 113 /** 114 * The current user has not completed setup, launch FSI. 115 */ 116 FSI_USER_SETUP_INCOMPLETE(true); 117 118 public final boolean shouldLaunch; 119 FullScreenIntentDecision(boolean shouldLaunch)120 FullScreenIntentDecision(boolean shouldLaunch) { 121 this.shouldLaunch = shouldLaunch; 122 } 123 } 124 125 /** 126 * If the device is awake (not dozing): 127 * Whether the notification should peek in from the top and alert the user. 128 * 129 * If the device is dozing: 130 * Whether the notification should show the ambient view of the notification ("pulse"). 131 * 132 * @param entry the entry to check 133 * @return true if the entry should heads up, false otherwise 134 */ shouldHeadsUp(NotificationEntry entry)135 boolean shouldHeadsUp(NotificationEntry entry); 136 137 /** 138 * Returns the value of whether this entry should peek (from shouldHeadsUp(entry)), but only 139 * optionally logs the status. 140 * 141 * This method should be used in cases where the caller needs to check whether a notification 142 * qualifies for a heads up, but is not necessarily guaranteed to make the heads-up happen. 143 * 144 * @param entry the entry to check 145 * @param log whether or not to log the results of this check 146 * @return true if the entry should heads up, false otherwise 147 */ checkHeadsUp(NotificationEntry entry, boolean log)148 boolean checkHeadsUp(NotificationEntry entry, boolean log); 149 150 /** 151 * Whether the notification should appear as a bubble with a fly-out on top of the screen. 152 * 153 * @param entry the entry to check 154 * @return true if the entry should bubble up, false otherwise 155 */ shouldBubbleUp(NotificationEntry entry)156 boolean shouldBubbleUp(NotificationEntry entry); 157 158 /** 159 * Whether to launch the entry's full screen intent when the entry is added. 160 * 161 * @param entry the entry that was added 162 * @return {@code true} if we should launch the full screen intent 163 */ shouldLaunchFullScreenIntentWhenAdded(NotificationEntry entry)164 boolean shouldLaunchFullScreenIntentWhenAdded(NotificationEntry entry); 165 166 /** 167 * Whether an entry's full screen intent would be launched. 168 * 169 * This method differs from shouldLaunchFullScreenIntentWhenAdded by returning more information 170 * on the decision, and only optionally logging the outcome. It should be used in cases where 171 * the caller needs to know what the decision would be, but may not actually launch the full 172 * screen intent. 173 * 174 * @param entry the entry to evaluate 175 * @return FullScreenIntentDecision representing the decision for whether to show the intent 176 */ 177 @NonNull getFullScreenIntentDecision(@onNull NotificationEntry entry)178 FullScreenIntentDecision getFullScreenIntentDecision(@NonNull NotificationEntry entry); 179 180 /** 181 * Write the full screen launch decision for the given entry to logs. 182 * 183 * @param entry the NotificationEntry for which the decision applies 184 * @param decision reason for launch or no-launch of FSI for entry 185 */ logFullScreenIntentDecision(NotificationEntry entry, FullScreenIntentDecision decision)186 void logFullScreenIntentDecision(NotificationEntry entry, FullScreenIntentDecision decision); 187 188 /** 189 * Add a component that can suppress visual interruptions. 190 */ addSuppressor(NotificationInterruptSuppressor suppressor)191 void addSuppressor(NotificationInterruptSuppressor suppressor); 192 193 /** 194 * Remove a component that can suppress visual interruptions. 195 */ removeSuppressor(NotificationInterruptSuppressor suppressor)196 void removeSuppressor(NotificationInterruptSuppressor suppressor); 197 } 198