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.wm.shell.bubbles; 18 19 import static java.lang.annotation.ElementType.FIELD; 20 import static java.lang.annotation.ElementType.LOCAL_VARIABLE; 21 import static java.lang.annotation.ElementType.PARAMETER; 22 import static java.lang.annotation.RetentionPolicy.SOURCE; 23 24 import android.content.pm.UserInfo; 25 import android.content.res.Configuration; 26 import android.os.Bundle; 27 import android.os.Looper; 28 import android.service.notification.NotificationListenerService.RankingMap; 29 import android.util.ArraySet; 30 import android.util.Pair; 31 import android.util.SparseArray; 32 import android.view.View; 33 34 import androidx.annotation.IntDef; 35 import androidx.annotation.Nullable; 36 37 import com.android.wm.shell.common.annotations.ExternalThread; 38 39 import java.io.FileDescriptor; 40 import java.io.PrintWriter; 41 import java.lang.annotation.Retention; 42 import java.lang.annotation.Target; 43 import java.util.HashMap; 44 import java.util.List; 45 import java.util.concurrent.Executor; 46 import java.util.function.BiConsumer; 47 import java.util.function.Consumer; 48 import java.util.function.IntConsumer; 49 50 /** 51 * Interface to engage bubbles feature. 52 */ 53 @ExternalThread 54 public interface Bubbles { 55 56 @Retention(SOURCE) 57 @IntDef({DISMISS_USER_GESTURE, DISMISS_AGED, DISMISS_TASK_FINISHED, DISMISS_BLOCKED, 58 DISMISS_NOTIF_CANCEL, DISMISS_ACCESSIBILITY_ACTION, DISMISS_NO_LONGER_BUBBLE, 59 DISMISS_USER_CHANGED, DISMISS_GROUP_CANCELLED, DISMISS_INVALID_INTENT, 60 DISMISS_OVERFLOW_MAX_REACHED, DISMISS_SHORTCUT_REMOVED, DISMISS_PACKAGE_REMOVED, 61 DISMISS_NO_BUBBLE_UP, DISMISS_RELOAD_FROM_DISK}) 62 @Target({FIELD, LOCAL_VARIABLE, PARAMETER}) 63 @interface DismissReason {} 64 65 int DISMISS_USER_GESTURE = 1; 66 int DISMISS_AGED = 2; 67 int DISMISS_TASK_FINISHED = 3; 68 int DISMISS_BLOCKED = 4; 69 int DISMISS_NOTIF_CANCEL = 5; 70 int DISMISS_ACCESSIBILITY_ACTION = 6; 71 int DISMISS_NO_LONGER_BUBBLE = 7; 72 int DISMISS_USER_CHANGED = 8; 73 int DISMISS_GROUP_CANCELLED = 9; 74 int DISMISS_INVALID_INTENT = 10; 75 int DISMISS_OVERFLOW_MAX_REACHED = 11; 76 int DISMISS_SHORTCUT_REMOVED = 12; 77 int DISMISS_PACKAGE_REMOVED = 13; 78 int DISMISS_NO_BUBBLE_UP = 14; 79 int DISMISS_RELOAD_FROM_DISK = 15; 80 81 /** 82 * @return {@code true} if there is a bubble associated with the provided key and if its 83 * notification is hidden from the shade or there is a group summary associated with the 84 * provided key that is hidden from the shade because it has been dismissed but still has child 85 * bubbles active. 86 */ isBubbleNotificationSuppressedFromShade(String key, String groupKey)87 boolean isBubbleNotificationSuppressedFromShade(String key, String groupKey); 88 89 /** 90 * @return {@code true} if the current notification entry same as selected bubble 91 * notification entry and the stack is currently expanded. 92 */ isBubbleExpanded(String key)93 boolean isBubbleExpanded(String key); 94 95 /** @return {@code true} if stack of bubbles is expanded or not. */ isStackExpanded()96 boolean isStackExpanded(); 97 98 /** 99 * Removes a group key indicating that the summary for this group should no longer be 100 * suppressed. 101 * 102 * @param callback If removed, this callback will be called with the summary key of the group 103 */ removeSuppressedSummaryIfNecessary(String groupKey, Consumer<String> callback, Executor callbackExecutor)104 void removeSuppressedSummaryIfNecessary(String groupKey, Consumer<String> callback, 105 Executor callbackExecutor); 106 107 /** Tell the stack of bubbles to collapse. */ collapseStack()108 void collapseStack(); 109 110 /** Tell the controller need update its UI to fit theme. */ updateForThemeChanges()111 void updateForThemeChanges(); 112 113 /** 114 * Request the stack expand if needed, then select the specified Bubble as current. 115 * If no bubble exists for this entry, one is created. 116 * 117 * @param entry the notification for the bubble to be selected 118 */ expandStackAndSelectBubble(BubbleEntry entry)119 void expandStackAndSelectBubble(BubbleEntry entry); 120 121 /** 122 * Request the stack expand if needed, then select the specified Bubble as current. 123 * 124 * @param bubble the bubble to be selected 125 */ expandStackAndSelectBubble(Bubble bubble)126 void expandStackAndSelectBubble(Bubble bubble); 127 128 /** 129 * @return a bubble that matches the provided shortcutId, if one exists. 130 */ 131 @Nullable getBubbleWithShortcutId(String shortcutId)132 Bubble getBubbleWithShortcutId(String shortcutId); 133 134 /** Called for any taskbar changes. */ onTaskbarChanged(Bundle b)135 void onTaskbarChanged(Bundle b); 136 137 /** Open the overflow view. */ openBubbleOverflow()138 void openBubbleOverflow(); 139 140 /** 141 * We intercept notification entries (including group summaries) dismissed by the user when 142 * there is an active bubble associated with it. We do this so that developers can still 143 * cancel it (and hence the bubbles associated with it). However, these intercepted 144 * notifications should then be hidden from the shade since the user has cancelled them, so we 145 * {@link Bubble#setSuppressNotification}. For the case of suppressed summaries, we also add 146 * {@link BubbleData#addSummaryToSuppress}. 147 * 148 * @param entry the notification of the BubbleEntry should be removed. 149 * @param children the list of child notification of the BubbleEntry from 1st param entry, 150 * this will be null if entry does have no children. 151 * @param removeCallback the remove callback for SystemUI side to remove notification, the int 152 * number should be list position of children list and use -1 for 153 * removing the parent notification. 154 * 155 * @return true if we want to intercept the dismissal of the entry, else false. 156 */ handleDismissalInterception(BubbleEntry entry, @Nullable List<BubbleEntry> children, IntConsumer removeCallback, Executor callbackExecutor)157 boolean handleDismissalInterception(BubbleEntry entry, @Nullable List<BubbleEntry> children, 158 IntConsumer removeCallback, Executor callbackExecutor); 159 160 /** Set the proxy to commnuicate with SysUi side components. */ setSysuiProxy(SysuiProxy proxy)161 void setSysuiProxy(SysuiProxy proxy); 162 163 /** 164 * Set the scrim view for bubbles. 165 * 166 * @param callback The callback made with the executor and the executor's looper that the view 167 * will be running on. 168 **/ setBubbleScrim(View view, BiConsumer<Executor, Looper> callback)169 void setBubbleScrim(View view, BiConsumer<Executor, Looper> callback); 170 171 /** Set a listener to be notified of bubble expand events. */ setExpandListener(BubbleExpandListener listener)172 void setExpandListener(BubbleExpandListener listener); 173 174 /** 175 * Called when new notification entry added. 176 * 177 * @param entry the {@link BubbleEntry} by the notification. 178 */ onEntryAdded(BubbleEntry entry)179 void onEntryAdded(BubbleEntry entry); 180 181 /** 182 * Called when new notification entry updated. 183 * 184 * @param entry the {@link BubbleEntry} by the notification. 185 * @param shouldBubbleUp {@code true} if this notification should bubble up. 186 */ onEntryUpdated(BubbleEntry entry, boolean shouldBubbleUp)187 void onEntryUpdated(BubbleEntry entry, boolean shouldBubbleUp); 188 189 /** 190 * Called when new notification entry removed. 191 * 192 * @param entry the {@link BubbleEntry} by the notification. 193 */ onEntryRemoved(BubbleEntry entry)194 void onEntryRemoved(BubbleEntry entry); 195 196 /** 197 * Called when NotificationListener has received adjusted notification rank and reapplied 198 * filtering and sorting. This is used to dismiss or create bubbles based on changes in 199 * permissions on the notification channel or the global setting. 200 * 201 * @param rankingMap the updated ranking map from NotificationListenerService 202 * @param entryDataByKey a map of ranking key to bubble entry and whether the entry should 203 * bubble up 204 */ onRankingUpdated(RankingMap rankingMap, HashMap<String, Pair<BubbleEntry, Boolean>> entryDataByKey)205 void onRankingUpdated(RankingMap rankingMap, 206 HashMap<String, Pair<BubbleEntry, Boolean>> entryDataByKey); 207 208 /** 209 * Called when the status bar has become visible or invisible (either permanently or 210 * temporarily). 211 */ onStatusBarVisibilityChanged(boolean visible)212 void onStatusBarVisibilityChanged(boolean visible); 213 214 /** Called when system zen mode state changed. */ onZenStateChanged()215 void onZenStateChanged(); 216 217 /** 218 * Called when statusBar state changed. 219 * 220 * @param isShade {@code true} is state is SHADE. 221 */ onStatusBarStateChanged(boolean isShade)222 void onStatusBarStateChanged(boolean isShade); 223 224 /** 225 * Called when the current user changed. 226 * 227 * @param newUserId the new user's id. 228 */ onUserChanged(int newUserId)229 void onUserChanged(int newUserId); 230 231 /** 232 * Called when the current user profiles change. 233 * 234 * @param currentProfiles the user infos for the current profile. 235 */ onCurrentProfilesChanged(SparseArray<UserInfo> currentProfiles)236 void onCurrentProfilesChanged(SparseArray<UserInfo> currentProfiles); 237 238 /** 239 * Called when config changed. 240 * 241 * @param newConfig the new config. 242 */ onConfigChanged(Configuration newConfig)243 void onConfigChanged(Configuration newConfig); 244 245 /** Description of current bubble state. */ dump(FileDescriptor fd, PrintWriter pw, String[] args)246 void dump(FileDescriptor fd, PrintWriter pw, String[] args); 247 248 /** Listener to find out about stack expansion / collapse events. */ 249 interface BubbleExpandListener { 250 /** 251 * Called when the expansion state of the bubble stack changes. 252 * 253 * @param isExpanding whether it's expanding or collapsing 254 * @param key the notification key associated with bubble being expanded 255 */ onBubbleExpandChanged(boolean isExpanding, String key)256 void onBubbleExpandChanged(boolean isExpanding, String key); 257 } 258 259 /** Listener to be notified when the flags for notification or bubble suppression changes.*/ 260 interface SuppressionChangedListener { 261 /** Called when the notification suppression state of a bubble changes. */ onBubbleNotificationSuppressionChange(Bubble bubble)262 void onBubbleNotificationSuppressionChange(Bubble bubble); 263 } 264 265 /** Listener to be notified when a pending intent has been canceled for a bubble. */ 266 interface PendingIntentCanceledListener { 267 /** Called when the pending intent for a bubble has been canceled. */ onPendingIntentCanceled(Bubble bubble)268 void onPendingIntentCanceled(Bubble bubble); 269 } 270 271 /** Callback to tell SysUi components execute some methods. */ 272 interface SysuiProxy { isNotificationShadeExpand(Consumer<Boolean> callback)273 void isNotificationShadeExpand(Consumer<Boolean> callback); 274 getPendingOrActiveEntry(String key, Consumer<BubbleEntry> callback)275 void getPendingOrActiveEntry(String key, Consumer<BubbleEntry> callback); 276 getShouldRestoredEntries(ArraySet<String> savedBubbleKeys, Consumer<List<BubbleEntry>> callback)277 void getShouldRestoredEntries(ArraySet<String> savedBubbleKeys, 278 Consumer<List<BubbleEntry>> callback); 279 setNotificationInterruption(String key)280 void setNotificationInterruption(String key); 281 requestNotificationShadeTopUi(boolean requestTopUi, String componentTag)282 void requestNotificationShadeTopUi(boolean requestTopUi, String componentTag); 283 notifyRemoveNotification(String key, int reason)284 void notifyRemoveNotification(String key, int reason); 285 notifyInvalidateNotifications(String reason)286 void notifyInvalidateNotifications(String reason); 287 notifyMaybeCancelSummary(String key)288 void notifyMaybeCancelSummary(String key); 289 removeNotificationEntry(String key)290 void removeNotificationEntry(String key); 291 updateNotificationBubbleButton(String key)292 void updateNotificationBubbleButton(String key); 293 updateNotificationSuppression(String key)294 void updateNotificationSuppression(String key); 295 onStackExpandChanged(boolean shouldExpand)296 void onStackExpandChanged(boolean shouldExpand); 297 onUnbubbleConversation(String key)298 void onUnbubbleConversation(String key); 299 } 300 } 301