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 * Device screen is off, so the FSI should launch. 71 */ 72 FSI_DEVICE_NOT_INTERACTIVE(true), 73 /** 74 * Device is currently dreaming, so FSI should launch. 75 */ 76 FSI_DEVICE_IS_DREAMING(true), 77 /** 78 * Keyguard is showing, so FSI should launch. 79 */ 80 FSI_KEYGUARD_SHOWING(true), 81 /** 82 * The notification is expected to show heads-up, so FSI is not needed. 83 */ 84 NO_FSI_EXPECTED_TO_HUN(false), 85 /** 86 * The notification is not expected to HUN while the keyguard is occluded, so show FSI. 87 */ 88 FSI_KEYGUARD_OCCLUDED(true), 89 /** 90 * The notification is not expected to HUN when the keyguard is showing but not occluded, 91 * which likely means that the shade is showing over the lockscreen; show FSI in this case. 92 */ 93 FSI_LOCKED_SHADE(true), 94 /** 95 * FSI requires keyguard to be showing, but there is no keyguard. This is a (potentially 96 * malicious) warning state where we suppress the FSI because the device is in use knowing 97 * that the HUN will probably not display. 98 */ 99 NO_FSI_NO_HUN_OR_KEYGUARD(false), 100 /** 101 * The notification is coming from a suspended packages, so FSI is suppressed. 102 */ 103 NO_FSI_SUSPENDED(false), 104 /** 105 * The device is not provisioned, launch FSI. 106 */ 107 FSI_NOT_PROVISIONED(true), 108 /** 109 * The current user has not completed setup, launch FSI. 110 */ 111 FSI_USER_SETUP_INCOMPLETE(true); 112 113 public final boolean shouldLaunch; 114 FullScreenIntentDecision(boolean shouldLaunch)115 FullScreenIntentDecision(boolean shouldLaunch) { 116 this.shouldLaunch = shouldLaunch; 117 } 118 } 119 120 /** 121 * If the device is awake (not dozing): 122 * Whether the notification should peek in from the top and alert the user. 123 * 124 * If the device is dozing: 125 * Whether the notification should show the ambient view of the notification ("pulse"). 126 * 127 * @param entry the entry to check 128 * @return true if the entry should heads up, false otherwise 129 */ shouldHeadsUp(NotificationEntry entry)130 boolean shouldHeadsUp(NotificationEntry entry); 131 132 /** 133 * Returns the value of whether this entry should peek (from shouldHeadsUp(entry)), but only 134 * optionally logs the status. 135 * 136 * This method should be used in cases where the caller needs to check whether a notification 137 * qualifies for a heads up, but is not necessarily guaranteed to make the heads-up happen. 138 * 139 * @param entry the entry to check 140 * @param log whether or not to log the results of this check 141 * @return true if the entry should heads up, false otherwise 142 */ checkHeadsUp(NotificationEntry entry, boolean log)143 boolean checkHeadsUp(NotificationEntry entry, boolean log); 144 145 /** 146 * Whether the notification should appear as a bubble with a fly-out on top of the screen. 147 * 148 * @param entry the entry to check 149 * @return true if the entry should bubble up, false otherwise 150 */ shouldBubbleUp(NotificationEntry entry)151 boolean shouldBubbleUp(NotificationEntry entry); 152 153 /** 154 * Whether to launch the entry's full screen intent when the entry is added. 155 * 156 * @param entry the entry that was added 157 * @return {@code true} if we should launch the full screen intent 158 */ shouldLaunchFullScreenIntentWhenAdded(NotificationEntry entry)159 boolean shouldLaunchFullScreenIntentWhenAdded(NotificationEntry entry); 160 161 /** 162 * Whether an entry's full screen intent would be launched. 163 * 164 * This method differs from shouldLaunchFullScreenIntentWhenAdded by returning more information 165 * on the decision, and only optionally logging the outcome. It should be used in cases where 166 * the caller needs to know what the decision would be, but may not actually launch the full 167 * screen intent. 168 * 169 * @param entry the entry to evaluate 170 * @return FullScreenIntentDecision representing the decision for whether to show the intent 171 */ 172 @NonNull getFullScreenIntentDecision(@onNull NotificationEntry entry)173 FullScreenIntentDecision getFullScreenIntentDecision(@NonNull NotificationEntry entry); 174 175 /** 176 * Write the full screen launch decision for the given entry to logs. 177 * 178 * @param entry the NotificationEntry for which the decision applies 179 * @param decision reason for launch or no-launch of FSI for entry 180 */ logFullScreenIntentDecision(NotificationEntry entry, FullScreenIntentDecision decision)181 void logFullScreenIntentDecision(NotificationEntry entry, FullScreenIntentDecision decision); 182 183 /** 184 * Add a component that can suppress visual interruptions. 185 */ addSuppressor(NotificationInterruptSuppressor suppressor)186 void addSuppressor(NotificationInterruptSuppressor suppressor); 187 188 /** 189 * Remove a component that can suppress visual interruptions. 190 */ removeSuppressor(NotificationInterruptSuppressor suppressor)191 void removeSuppressor(NotificationInterruptSuppressor suppressor); 192 } 193