1 /* 2 * Copyright (C) 2023 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 com.android.internal.annotations.VisibleForTesting 20 import com.android.systemui.CoreStartable 21 import com.android.systemui.statusbar.notification.collection.NotificationEntry 22 23 /** 24 * Decides whether a notification should visually interrupt the user in various ways. 25 * 26 * These include displaying the notification as heads-up (peeking while the device is awake or 27 * pulsing while the device is dozing), displaying the notification as a bubble, and launching a 28 * full-screen intent for the notification. 29 */ 30 interface VisualInterruptionDecisionProvider : CoreStartable { 31 /** 32 * Represents the decision to visually interrupt or not. 33 * 34 * Used for heads-up and bubble decisions; subclassed by [FullScreenIntentDecision] for 35 * full-screen intent decisions. 36 * 37 * @property[shouldInterrupt] whether a visual interruption should be triggered 38 * @property[logReason] a log-friendly string explaining the reason for the decision; should be 39 * used *only* for logging, not decision-making 40 */ 41 interface Decision { 42 val shouldInterrupt: Boolean 43 val logReason: String 44 } 45 46 /** 47 * Represents the decision to launch a full-screen intent for a notification or not. 48 * 49 * @property[wouldInterruptWithoutDnd] whether a full-screen intent should not be launched only 50 * because Do Not Disturb has suppressed it 51 */ 52 interface FullScreenIntentDecision : Decision { 53 val wouldInterruptWithoutDnd: Boolean 54 } 55 56 /** Initializes the provider. */ startnull57 override fun start() {} 58 59 /** 60 * Adds a [NotificationInterruptSuppressor] that can suppress visual interruptions. 61 * 62 * This method may be called before [start] has been called. 63 * 64 * This class may call suppressors, conditions, and filters in any order. 65 * 66 * @param[suppressor] the suppressor to add 67 */ addLegacySuppressornull68 fun addLegacySuppressor(suppressor: NotificationInterruptSuppressor) 69 70 /** 71 * Removes a previously-added suppressor. 72 * 73 * This method may be called before [start] has been called. 74 * 75 * @param[suppressor] the suppressor to remove 76 */ 77 @VisibleForTesting fun removeLegacySuppressor(suppressor: NotificationInterruptSuppressor) 78 79 /** 80 * Adds a [VisualInterruptionCondition] that can suppress visual interruptions without examining 81 * individual notifications. 82 * 83 * This method may be called before [start] has been called. 84 * 85 * This class may call suppressors, conditions, and filters in any order. 86 * 87 * @param[condition] the condition to add 88 */ 89 fun addCondition(condition: VisualInterruptionCondition) 90 91 /** 92 * Removes a previously-added condition. 93 * 94 * This method may be called before [start] has been called. 95 * 96 * @param[condition] the condition to remove 97 */ 98 @VisibleForTesting fun removeCondition(condition: VisualInterruptionCondition) 99 100 /** 101 * Adds a [VisualInterruptionFilter] that can suppress visual interruptions based on individual 102 * notifications. 103 * 104 * This method may be called before [start] has been called. 105 * 106 * This class may call suppressors, conditions, and filters in any order. 107 * 108 * @param[filter] the filter to add 109 */ 110 fun addFilter(filter: VisualInterruptionFilter) 111 112 /** 113 * Removes a previously-added filter. 114 * 115 * This method may be called before [start] has been called. 116 * 117 * @param[filter] the filter to remove 118 */ 119 @VisibleForTesting fun removeFilter(filter: VisualInterruptionFilter) 120 121 /** 122 * Decides whether a [notification][entry] should display as heads-up or not, but does not log 123 * that decision. 124 * 125 * [start] must be called before this method can be called. 126 * 127 * @param[entry] the notification that this decision is about 128 * @return the decision to display that notification as heads-up or not 129 */ 130 fun makeUnloggedHeadsUpDecision(entry: NotificationEntry): Decision 131 132 /** 133 * Decides whether a [notification][entry] should display as heads-up or not, and logs that 134 * decision. 135 * 136 * If the device is awake, the decision will consider whether the notification should "peek" 137 * (slide in from the top of the screen over the current activity). 138 * 139 * If the device is dozing, the decision will consider whether the notification should "pulse" 140 * (wake the screen up and display the ambient view of the notification). 141 * 142 * [start] must be called before this method can be called. 143 * 144 * @see[makeUnloggedHeadsUpDecision] 145 * 146 * @param[entry] the notification that this decision is about 147 * @return the decision to display that notification as heads-up or not 148 */ 149 fun makeAndLogHeadsUpDecision(entry: NotificationEntry): Decision 150 151 /** 152 * Decides whether a [notification][entry] should launch a full-screen intent or not, but does 153 * not log that decision. 154 * 155 * The returned decision can be logged by passing it to [logFullScreenIntentDecision]. 156 * 157 * [start] must be called before this method can be called. 158 * 159 * @see[makeAndLogHeadsUpDecision] 160 * 161 * @param[entry] the notification that this decision is about 162 * @return the decision to launch a full-screen intent for that notification or not 163 */ 164 fun makeUnloggedFullScreenIntentDecision(entry: NotificationEntry): FullScreenIntentDecision 165 166 /** 167 * Logs a previous [decision] to launch a full-screen intent or not. 168 * 169 * [start] must be called before this method can be called. 170 * 171 * @param[decision] the decision to log 172 */ 173 fun logFullScreenIntentDecision(decision: FullScreenIntentDecision) 174 175 /** 176 * Decides whether a [notification][entry] should display as a bubble or not. 177 * 178 * [start] must be called before this method can be called. 179 * 180 * @param[entry] the notification that this decision is about 181 * @return the decision to display that notification as a bubble or not 182 */ 183 fun makeAndLogBubbleDecision(entry: NotificationEntry): Decision 184 } 185