• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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