1 package com.android.systemui.statusbar.policy 2 3 import android.graphics.Region 4 import com.android.systemui.Dumpable 5 import com.android.systemui.dagger.SysUISingleton 6 import com.android.systemui.statusbar.notification.collection.NotificationEntry 7 import dagger.Binds 8 import dagger.Module 9 import java.io.PrintWriter 10 import java.util.stream.Stream 11 import javax.inject.Inject 12 13 /** 14 * A manager which handles heads up notifications which is a special mode where they simply peek 15 * from the top of the screen. 16 */ 17 interface HeadsUpManager : Dumpable { 18 /** The stream of all current notifications managed by this manager. */ 19 val allEntries: Stream<NotificationEntry> 20 21 /** Add a listener to receive callbacks onHeadsUpGoingAway. */ addHeadsUpPhoneListenernull22 fun addHeadsUpPhoneListener(listener: OnHeadsUpPhoneListenerChange) 23 24 /** Adds an OnHeadUpChangedListener to observe events. */ 25 fun addListener(listener: OnHeadsUpChangedListener) 26 27 fun addSwipedOutNotification(key: String) 28 29 /** 30 * Whether or not the alert can be removed currently. If it hasn't been on screen long enough it 31 * should not be removed unless forced 32 * 33 * @param key the key to check if removable 34 * @return true if the alert entry can be removed 35 */ 36 fun canRemoveImmediately(key: String): Boolean 37 38 /** 39 * Compare two entries and decide how they should be ranked. 40 * 41 * @return -1 if the first argument should be ranked higher than the second, 1 if the second one 42 * should be ranked higher and 0 if they are equal. 43 */ 44 fun compare(a: NotificationEntry?, b: NotificationEntry?): Int 45 /** 46 * Extends the lifetime of the currently showing pulsing notification so that the pulse lasts 47 * longer. 48 */ 49 fun extendHeadsUp() 50 51 /** Returns when a HUN entry should be removed in milliseconds from now. */ 52 fun getEarliestRemovalTime(key: String?): Long 53 54 /** Returns the top Heads Up Notification, which appears to show at first. */ 55 fun getTopEntry(): NotificationEntry? 56 57 /** 58 * Gets the touchable region needed for heads up notifications. Returns null if no touchable 59 * region is required (ie: no heads up notification currently exists). 60 */ 61 fun getTouchableRegion(): Region? 62 63 /** 64 * Whether or not there are any entries managed by HeadsUpManager. 65 * 66 * @return true if there is a heads up entry, false otherwise 67 */ 68 fun hasNotifications(): Boolean = false 69 70 /** Returns whether there are any pinned Heads Up Notifications or not. */ 71 fun hasPinnedHeadsUp(): Boolean 72 73 /** Returns whether or not the given notification is managed by this manager. */ 74 fun isHeadsUpEntry(key: String): Boolean 75 76 /** @see setHeadsUpAnimatingAway */ 77 fun isHeadsUpAnimatingAwayValue(): Boolean 78 79 /** Returns if the given notification is snoozed or not. */ 80 fun isSnoozed(packageName: String): Boolean 81 82 /** Returns whether the entry is (pinned and expanded) or (has an active remote input). */ 83 fun isSticky(key: String?): Boolean 84 85 fun isTrackingHeadsUp(): Boolean 86 87 fun onExpandingFinished() 88 89 /** Removes the OnHeadUpChangedListener from the observer list. */ 90 fun removeListener(listener: OnHeadsUpChangedListener) 91 92 /** 93 * Try to remove the notification. May not succeed if the notification has not been shown long 94 * enough and needs to be kept around. 95 * 96 * @param key the key of the notification to remove 97 * @param releaseImmediately force a remove regardless of earliest removal time 98 * @return true if notification is removed, false otherwise 99 */ 100 fun removeNotification(key: String, releaseImmediately: Boolean): Boolean 101 102 /** 103 * Try to remove the notification. May not succeed if the notification has not been shown long 104 * enough and needs to be kept around. 105 * 106 * @param key the key of the notification to remove 107 * @param releaseImmediately force a remove regardless of earliest removal time 108 * @param animate if true, animate the removal 109 * @return true if notification is removed, false otherwise 110 */ 111 fun removeNotification(key: String, releaseImmediately: Boolean, animate: Boolean): Boolean 112 113 /** Clears all managed notifications. */ 114 fun releaseAllImmediately() 115 116 fun setAnimationStateHandler(handler: AnimationStateHandler) 117 118 /** 119 * Set an entry to be expanded and therefore stick in the heads up area if it's pinned until 120 * it's collapsed again. 121 */ 122 fun setExpanded(entry: NotificationEntry, expanded: Boolean) 123 124 /** 125 * Sets whether an entry's guts are exposed and therefore it should stick in the heads up area 126 * if it's pinned until it's hidden again. 127 */ 128 fun setGutsShown(entry: NotificationEntry, gutsShown: Boolean) 129 130 /** 131 * Set that we are exiting the headsUp pinned mode, but some notifications might still be 132 * animating out. This is used to keep the touchable regions in a reasonable state. 133 */ 134 fun setHeadsUpAnimatingAway(headsUpAnimatingAway: Boolean) 135 136 /** 137 * Notifies that a remote input textbox in notification gets active or inactive. 138 * 139 * @param entry The entry of the target notification. 140 * @param remoteInputActive True to notify active, False to notify inactive. 141 */ 142 fun setRemoteInputActive(entry: NotificationEntry, remoteInputActive: Boolean) 143 144 fun setTrackingHeadsUp(tracking: Boolean) 145 146 /** Sets the current user. */ 147 fun setUser(user: Int) 148 149 /** 150 * Notes that the user took an action on an entry that might indirectly cause the system or the 151 * app to remove the notification. 152 * 153 * @param entry the entry that might be indirectly removed by the user's action 154 * @see 155 * com.android.systemui.statusbar.notification.collection.coordinator.HeadsUpCoordinator.mActionPressListener 156 * @see .canRemoveImmediately 157 */ 158 fun setUserActionMayIndirectlyRemove(entry: NotificationEntry) 159 160 /** 161 * Decides whether a click is invalid for a notification, i.e. it has not been shown long enough 162 * that a user might have consciously clicked on it. 163 * 164 * @param key the key of the touched notification 165 * @return whether the touch is invalid and should be discarded 166 */ 167 fun shouldSwallowClick(key: String): Boolean 168 169 /** 170 * Called when posting a new notification that should alert the user and appear on screen. Adds 171 * the notification to be managed. 172 * 173 * @param entry entry to show 174 */ 175 fun showNotification(entry: NotificationEntry) 176 177 fun snooze() 178 179 /** 180 * Unpins all pinned Heads Up Notifications. 181 * 182 * @param userUnPinned The unpinned action is trigger by user real operation. 183 */ 184 fun unpinAll(userUnPinned: Boolean) 185 186 fun updateNotification(key: String, shouldHeadsUpAgain: Boolean) 187 } 188 189 /** Sets the animation state of the HeadsUpManager. */ 190 interface AnimationStateHandler { 191 fun setHeadsUpGoingAwayAnimationsAllowed(allowed: Boolean) 192 } 193 194 /** Listener to register for HeadsUpNotification Phone changes. */ 195 interface OnHeadsUpPhoneListenerChange { 196 /** 197 * Called when a heads up notification is 'going away' or no longer 'going away'. See 198 * [HeadsUpManager.setHeadsUpAnimatingAway]. 199 */ 200 // TODO(b/325936094) delete this callback, and listen to the flow instead onHeadsUpAnimatingAwayStateChangednull201 fun onHeadsUpAnimatingAwayStateChanged(headsUpAnimatingAway: Boolean) 202 } 203 204 /* No op impl of HeadsUpManager. */ 205 class HeadsUpManagerEmptyImpl @Inject constructor() : HeadsUpManager { 206 override val allEntries = Stream.empty<NotificationEntry>() 207 override fun addHeadsUpPhoneListener(listener: OnHeadsUpPhoneListenerChange) {} 208 override fun addListener(listener: OnHeadsUpChangedListener) {} 209 override fun addSwipedOutNotification(key: String) {} 210 override fun canRemoveImmediately(key: String) = false 211 override fun compare(a: NotificationEntry?, b: NotificationEntry?) = 0 212 override fun dump(pw: PrintWriter, args: Array<out String>) {} 213 override fun extendHeadsUp() {} 214 override fun getEarliestRemovalTime(key: String?) = 0L 215 override fun getTouchableRegion(): Region? = null 216 override fun getTopEntry() = null 217 override fun hasPinnedHeadsUp() = false 218 override fun isHeadsUpEntry(key: String) = false 219 override fun isHeadsUpAnimatingAwayValue() = false 220 override fun isSnoozed(packageName: String) = false 221 override fun isSticky(key: String?) = false 222 override fun isTrackingHeadsUp() = false 223 override fun onExpandingFinished() {} 224 override fun releaseAllImmediately() {} 225 override fun removeListener(listener: OnHeadsUpChangedListener) {} 226 override fun removeNotification(key: String, releaseImmediately: Boolean) = false 227 override fun removeNotification(key: String, releaseImmediately: Boolean, animate: Boolean) = 228 false 229 override fun setAnimationStateHandler(handler: AnimationStateHandler) {} 230 override fun setExpanded(entry: NotificationEntry, expanded: Boolean) {} 231 override fun setGutsShown(entry: NotificationEntry, gutsShown: Boolean) {} 232 override fun setHeadsUpAnimatingAway(headsUpAnimatingAway: Boolean) {} 233 override fun setRemoteInputActive(entry: NotificationEntry, remoteInputActive: Boolean) {} 234 override fun setTrackingHeadsUp(tracking: Boolean) {} 235 override fun setUser(user: Int) {} 236 override fun setUserActionMayIndirectlyRemove(entry: NotificationEntry) {} 237 override fun shouldSwallowClick(key: String): Boolean = false 238 override fun showNotification(entry: NotificationEntry) {} 239 override fun snooze() {} 240 override fun unpinAll(userUnPinned: Boolean) {} 241 override fun updateNotification(key: String, alert: Boolean) {} 242 } 243 244 @Module 245 interface HeadsUpEmptyImplModule { bindsHeadsUpManagernull246 @Binds @SysUISingleton fun bindsHeadsUpManager(noOpHum: HeadsUpManagerEmptyImpl): HeadsUpManager 247 } 248