summaryrefslogtreecommitdiff
path: root/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProvider.java
blob: 62bbd667af1caa67f7defddd395807a0f0487b1c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
/*
 * Copyright (C) 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.systemui.statusbar.notification.interruption;

import com.android.systemui.statusbar.notification.collection.NotificationEntry;

/**
 * Provides bubble-up and heads-up state for notification entries.
 *
 * When a notification is heads-up when dozing, this is also called "pulsing."
 */
public interface NotificationInterruptStateProvider {
    /**
     * Enum representing a decision of whether to show a full screen intent. While many of the
     * relevant properties could overlap, the decision represents the deciding factor for whether
     * the full screen intent should or shouldn't launch.
     */
    enum FullScreenIntentDecision {
        /**
         * Full screen intents are disabled.
         */
        NO_FSI_DISABLED(false),
        /**
         * No full screen intent included, so there is nothing to show.
         */
        NO_FULL_SCREEN_INTENT(false),
        /**
         * Suppressed by DND settings.
         */
        NO_FSI_SUPPRESSED_BY_DND(false),
        /**
         * Full screen intent was suppressed *only* by DND, and if not for DND would have shown. We
         * track this separately in order to allow the intent to be shown if the DND decision
         * changes.
         */
        NO_FSI_SUPPRESSED_ONLY_BY_DND(false),
        /**
         * Notification importance not high enough to show FSI.
         */
        NO_FSI_NOT_IMPORTANT_ENOUGH(false),
        /**
         * Notification should not FSI due to having suppressive GroupAlertBehavior. This blocks a
         * potentially malicious use of flags that previously allowed apps to escalate a HUN to an
         * FSI even while the device was unlocked.
         */
        NO_FSI_SUPPRESSIVE_GROUP_ALERT_BEHAVIOR(false),
        /**
         * Notification should not FSI due to having suppressive BubbleMetadata. This blocks a
         * potentially malicious use of flags that previously allowed apps to escalate a HUN to an
         * FSI even while the device was unlocked.
         */
        NO_FSI_SUPPRESSIVE_BUBBLE_METADATA(false),
        /**
         * Device screen is off, so the FSI should launch.
         */
        FSI_DEVICE_NOT_INTERACTIVE(true),
        /**
         * Device is currently dreaming, so FSI should launch.
         */
        FSI_DEVICE_IS_DREAMING(true),
        /**
         * Keyguard is showing, so FSI should launch.
         */
        FSI_KEYGUARD_SHOWING(true),
        /**
         * The notification is expected to show heads-up, so FSI is not needed.
         */
        NO_FSI_EXPECTED_TO_HUN(false),
        /**
         * The notification is not expected to HUN while the keyguard is occluded, so show FSI.
         */
        FSI_KEYGUARD_OCCLUDED(true),
        /**
         * The notification is not expected to HUN when the keyguard is showing but not occluded,
         * which likely means that the shade is showing over the lockscreen; show FSI in this case.
         */
        FSI_LOCKED_SHADE(true),
        /**
         * FSI requires keyguard to be showing, but there is no keyguard. This is a (potentially
         * malicious) warning state where we suppress the FSI because the device is in use knowing
         * that the HUN will probably not display.
         */
        NO_FSI_NO_HUN_OR_KEYGUARD(false),
        /**
         * No conditions blocking FSI launch.
         */
        FSI_EXPECTED_NOT_TO_HUN(true);

        public final boolean shouldLaunch;

        FullScreenIntentDecision(boolean shouldLaunch) {
            this.shouldLaunch = shouldLaunch;
        }
    }

    /**
     * If the device is awake (not dozing):
     *  Whether the notification should peek in from the top and alert the user.
     *
     * If the device is dozing:
     *  Whether the notification should show the ambient view of the notification ("pulse").
     *
     * @param entry the entry to check
     * @return true if the entry should heads up, false otherwise
     */
    boolean shouldHeadsUp(NotificationEntry entry);

    /**
     * Returns the value of whether this entry should peek (from shouldHeadsUp(entry)), but only
     * optionally logs the status.
     *
     * This method should be used in cases where the caller needs to check whether a notification
     * qualifies for a heads up, but is not necessarily guaranteed to make the heads-up happen.
     *
     * @param entry the entry to check
     * @param log whether or not to log the results of this check
     * @return true if the entry should heads up, false otherwise
     */
    boolean checkHeadsUp(NotificationEntry entry, boolean log);

    /**
     * Whether the notification should appear as a bubble with a fly-out on top of the screen.
     *
     * @param entry the entry to check
     * @return true if the entry should bubble up, false otherwise
     */
    boolean shouldBubbleUp(NotificationEntry entry);

    /**
     * Whether to launch the entry's full screen intent when the entry is added.
     *
     * @param entry the entry that was added
     * @return {@code true} if we should launch the full screen intent
     */
    boolean shouldLaunchFullScreenIntentWhenAdded(NotificationEntry entry);

    /**
     * Whether an entry's full screen intent would be launched.
     *
     * This method differs from shouldLaunchFullScreenIntentWhenAdded by returning more information
     * on the decision, and only optionally logging the outcome. It should be used in cases where
     * the caller needs to know what the decision would be, but may not actually launch the full
     * screen intent.
     *
     * @param entry the entry to evaluate
     * @return FullScreenIntentDecision representing the decision for whether to show the intent
     */
    FullScreenIntentDecision getFullScreenIntentDecision(NotificationEntry entry);

    /**
     * Write the full screen launch decision for the given entry to logs.
     *
     * @param entry the NotificationEntry for which the decision applies
     * @param decision reason for launch or no-launch of FSI for entry
     */
    void logFullScreenIntentDecision(NotificationEntry entry, FullScreenIntentDecision decision);

    /**
     * Add a component that can suppress visual interruptions.
     */
    void addSuppressor(NotificationInterruptSuppressor suppressor);

    /**
     * Whether heads-up notification should be skipped when Less Boring heads up is enabled.
     */
    void setUseLessBoringHeadsUp(boolean lessBoring);
}