Eliot Courtney | a6d8cf2 | 2017-10-20 13:26:58 +0900 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2017 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 | */ |
Rohan Shah | 20790b8 | 2018-07-02 17:21:04 -0700 | [diff] [blame] | 16 | package com.android.systemui.statusbar.notification; |
Eliot Courtney | a6d8cf2 | 2017-10-20 13:26:58 +0900 | [diff] [blame] | 17 | |
Mady Mellor | c2ff011 | 2019-03-28 14:18:06 -0700 | [diff] [blame] | 18 | import static android.service.notification.NotificationListenerService.REASON_CANCEL; |
| 19 | import static android.service.notification.NotificationListenerService.REASON_ERROR; |
| 20 | |
Kevin Han | f400aee | 2020-01-30 13:10:29 -0800 | [diff] [blame] | 21 | import static com.android.systemui.statusbar.notification.collection.NotifCollection.REASON_UNKNOWN; |
Kevin Han | ec09309 | 2019-12-11 16:47:59 -0800 | [diff] [blame] | 22 | import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationCallback; |
| 23 | |
Evan Laird | 181de62 | 2019-10-24 09:53:02 -0400 | [diff] [blame] | 24 | import android.annotation.NonNull; |
Tony Mak | 628cb93 | 2018-06-19 18:30:41 +0100 | [diff] [blame] | 25 | import android.annotation.Nullable; |
Eliot Courtney | a6d8cf2 | 2017-10-20 13:26:58 +0900 | [diff] [blame] | 26 | import android.app.Notification; |
Evan Laird | ccf5c5e | 2020-02-06 14:01:28 -0500 | [diff] [blame] | 27 | import android.os.SystemClock; |
Eliot Courtney | a6d8cf2 | 2017-10-20 13:26:58 +0900 | [diff] [blame] | 28 | import android.service.notification.NotificationListenerService; |
Ned Burns | e372f32 | 2019-09-24 13:14:08 -0400 | [diff] [blame] | 29 | import android.service.notification.NotificationListenerService.Ranking; |
Evan Laird | 181de62 | 2019-10-24 09:53:02 -0400 | [diff] [blame] | 30 | import android.service.notification.NotificationListenerService.RankingMap; |
Eliot Courtney | a6d8cf2 | 2017-10-20 13:26:58 +0900 | [diff] [blame] | 31 | import android.service.notification.StatusBarNotification; |
Tony Mak | 628cb93 | 2018-06-19 18:30:41 +0100 | [diff] [blame] | 32 | import android.util.ArrayMap; |
Ned Burns | 88aeaf7 | 2020-03-13 20:45:19 -0400 | [diff] [blame] | 33 | import android.util.ArraySet; |
Eliot Courtney | a6d8cf2 | 2017-10-20 13:26:58 +0900 | [diff] [blame] | 34 | import android.util.Log; |
Eliot Courtney | a6d8cf2 | 2017-10-20 13:26:58 +0900 | [diff] [blame] | 35 | |
Julia Reynolds | 9159006 | 2018-04-02 16:24:11 -0400 | [diff] [blame] | 36 | import com.android.internal.annotations.VisibleForTesting; |
Dieter Hsu | d39f0d5 | 2018-04-14 02:08:30 +0800 | [diff] [blame] | 37 | import com.android.internal.statusbar.NotificationVisibility; |
Eliot Courtney | a6d8cf2 | 2017-10-20 13:26:58 +0900 | [diff] [blame] | 38 | import com.android.systemui.Dumpable; |
Beverly | 8b493df | 2019-12-18 14:16:50 -0500 | [diff] [blame] | 39 | import com.android.systemui.statusbar.FeatureFlags; |
Kevin | 38ce6fa | 2018-10-17 16:00:14 -0700 | [diff] [blame] | 40 | import com.android.systemui.statusbar.NotificationLifetimeExtender; |
Ned Burns | 2246b33 | 2019-12-12 14:39:13 -0500 | [diff] [blame] | 41 | import com.android.systemui.statusbar.NotificationListener; |
Ned Burns | e6855d6 | 2019-12-19 16:38:08 -0500 | [diff] [blame] | 42 | import com.android.systemui.statusbar.NotificationListener.NotificationHandler; |
Rohan Shah | 20790b8 | 2018-07-02 17:21:04 -0700 | [diff] [blame] | 43 | import com.android.systemui.statusbar.NotificationPresenter; |
| 44 | import com.android.systemui.statusbar.NotificationRemoteInputManager; |
Mady Mellor | c2ff011 | 2019-03-28 14:18:06 -0700 | [diff] [blame] | 45 | import com.android.systemui.statusbar.NotificationRemoveInterceptor; |
Rohan Shah | 20790b8 | 2018-07-02 17:21:04 -0700 | [diff] [blame] | 46 | import com.android.systemui.statusbar.NotificationUiAdjustment; |
Ned Burns | f81c4c4 | 2019-01-07 14:10:43 -0500 | [diff] [blame] | 47 | import com.android.systemui.statusbar.notification.collection.NotificationEntry; |
Evan Laird | 181de62 | 2019-10-24 09:53:02 -0400 | [diff] [blame] | 48 | import com.android.systemui.statusbar.notification.collection.NotificationRankingManager; |
Ned Burns | 012048d | 2020-01-08 19:57:30 -0500 | [diff] [blame] | 49 | import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinder; |
Kevin Han | f400aee | 2020-01-30 13:10:29 -0800 | [diff] [blame] | 50 | import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection; |
| 51 | import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener; |
Sergey Nikolaienkov | f6ad632 | 2020-02-10 15:46:32 +0100 | [diff] [blame] | 52 | import com.android.systemui.statusbar.notification.dagger.NotificationsModule; |
Gustav Sennton | f892fe9 | 2019-01-22 15:31:42 +0000 | [diff] [blame] | 53 | import com.android.systemui.statusbar.notification.logging.NotificationLogger; |
Evan Laird | 181de62 | 2019-10-24 09:53:02 -0400 | [diff] [blame] | 54 | import com.android.systemui.statusbar.phone.NotificationGroupManager; |
Evan Laird | 181de62 | 2019-10-24 09:53:02 -0400 | [diff] [blame] | 55 | import com.android.systemui.util.Assert; |
Eliot Courtney | a6d8cf2 | 2017-10-20 13:26:58 +0900 | [diff] [blame] | 56 | import com.android.systemui.util.leak.LeakDetector; |
| 57 | |
| 58 | import java.io.FileDescriptor; |
| 59 | import java.io.PrintWriter; |
| 60 | import java.util.ArrayList; |
Ned Burns | 88aeaf7 | 2020-03-13 20:45:19 -0400 | [diff] [blame] | 61 | import java.util.Collection; |
Evan Laird | 181de62 | 2019-10-24 09:53:02 -0400 | [diff] [blame] | 62 | import java.util.Collections; |
Eliot Courtney | a6d8cf2 | 2017-10-20 13:26:58 +0900 | [diff] [blame] | 63 | import java.util.HashMap; |
| 64 | import java.util.List; |
Ned Burns | a5dad55 | 2019-01-29 17:59:10 -0500 | [diff] [blame] | 65 | import java.util.Map; |
Beverly | 6fc9f22 | 2019-10-23 17:56:48 -0400 | [diff] [blame] | 66 | import java.util.Set; |
Eliot Courtney | a6d8cf2 | 2017-10-20 13:26:58 +0900 | [diff] [blame] | 67 | |
Dave Mankoff | 02dcaf5 | 2020-01-08 15:42:06 -0500 | [diff] [blame] | 68 | import dagger.Lazy; |
| 69 | |
Eliot Courtney | a6d8cf2 | 2017-10-20 13:26:58 +0900 | [diff] [blame] | 70 | /** |
Evan Laird | 181de62 | 2019-10-24 09:53:02 -0400 | [diff] [blame] | 71 | * NotificationEntryManager is responsible for the adding, removing, and updating of |
| 72 | * {@link NotificationEntry}s. It also handles tasks such as their inflation and their interaction |
| 73 | * with other Notification.*Manager objects. |
| 74 | * |
| 75 | * We track notification entries through this lifecycle: |
| 76 | * 1. Pending |
| 77 | * 2. Active |
| 78 | * 3. Sorted / filtered (visible) |
| 79 | * |
| 80 | * Every entry spends some amount of time in the pending state, while it is being inflated. Once |
| 81 | * inflated, an entry moves into the active state, where it _could_ potentially be shown to the |
| 82 | * user. After an entry makes its way into the active state, we sort and filter the entire set to |
| 83 | * repopulate the visible set. |
| 84 | * |
| 85 | * There are a few different things that other classes may be interested in, and most of them |
| 86 | * involve the current set of notifications. Here's a brief overview of things you may want to know: |
| 87 | * @see #getVisibleNotifications() for the visible set |
| 88 | * @see #getActiveNotificationUnfiltered(String) to check if a key exists |
| 89 | * @see #getPendingNotificationsIterator() for an iterator over the pending notifications |
| 90 | * @see #getPendingOrActiveNotif(String) to find a notification exists for that key in any list |
Evan Laird | 181de62 | 2019-10-24 09:53:02 -0400 | [diff] [blame] | 91 | * @see #getActiveNotificationsForCurrentUser() to see every notification that the current user owns |
Eliot Courtney | a6d8cf2 | 2017-10-20 13:26:58 +0900 | [diff] [blame] | 92 | */ |
Gus Prevas | 8ba88a8 | 2018-12-18 11:13:44 -0500 | [diff] [blame] | 93 | public class NotificationEntryManager implements |
Kevin Han | f400aee | 2020-01-30 13:10:29 -0800 | [diff] [blame] | 94 | CommonNotifCollection, |
Gus Prevas | 8ba88a8 | 2018-12-18 11:13:44 -0500 | [diff] [blame] | 95 | Dumpable, |
Ned Burns | 01e3821 | 2019-01-03 16:32:52 -0500 | [diff] [blame] | 96 | VisualStabilityManager.Callback { |
Julia Reynolds | fc64001 | 2018-02-21 12:25:27 -0500 | [diff] [blame] | 97 | private static final String TAG = "NotificationEntryMgr"; |
Ned Burns | d35708c | 2019-01-09 15:38:03 -0500 | [diff] [blame] | 98 | private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); |
Eliot Courtney | 6c313d3 | 2017-12-14 19:57:51 +0900 | [diff] [blame] | 99 | |
Mady Mellor | 1a4e86f | 2019-05-03 16:07:23 -0700 | [diff] [blame] | 100 | /** |
| 101 | * Used when a notification is removed and it doesn't have a reason that maps to one of the |
| 102 | * reasons defined in NotificationListenerService |
Evan Laird | 181de62 | 2019-10-24 09:53:02 -0400 | [diff] [blame] | 103 | * (e.g. {@link NotificationListenerService#REASON_CANCEL}) |
Mady Mellor | 1a4e86f | 2019-05-03 16:07:23 -0700 | [diff] [blame] | 104 | */ |
| 105 | public static final int UNDEFINED_DISMISS_REASON = 0; |
| 106 | |
Ned Burns | 88aeaf7 | 2020-03-13 20:45:19 -0400 | [diff] [blame] | 107 | private final Set<NotificationEntry> mAllNotifications = new ArraySet<>(); |
| 108 | private final Set<NotificationEntry> mReadOnlyAllNotifications = |
| 109 | Collections.unmodifiableSet(mAllNotifications); |
| 110 | |
Evan Laird | 181de62 | 2019-10-24 09:53:02 -0400 | [diff] [blame] | 111 | /** Pending notifications are ones awaiting inflation */ |
Ned Burns | d35708c | 2019-01-09 15:38:03 -0500 | [diff] [blame] | 112 | @VisibleForTesting |
Ned Burns | f81c4c4 | 2019-01-07 14:10:43 -0500 | [diff] [blame] | 113 | protected final HashMap<String, NotificationEntry> mPendingNotifications = new HashMap<>(); |
Evan Laird | 181de62 | 2019-10-24 09:53:02 -0400 | [diff] [blame] | 114 | /** |
| 115 | * Active notifications have been inflated / prepared and could become visible, but may get |
| 116 | * filtered out if for instance they are not for the current user |
| 117 | */ |
| 118 | private final ArrayMap<String, NotificationEntry> mActiveNotifications = new ArrayMap<>(); |
| 119 | @VisibleForTesting |
| 120 | /** This is the list of "active notifications for this user in this context" */ |
| 121 | protected final ArrayList<NotificationEntry> mSortedAndFiltered = new ArrayList<>(); |
| 122 | private final List<NotificationEntry> mReadOnlyNotifications = |
| 123 | Collections.unmodifiableList(mSortedAndFiltered); |
Eliot Courtney | a6d8cf2 | 2017-10-20 13:26:58 +0900 | [diff] [blame] | 124 | |
Ned Burns | a5dad55 | 2019-01-29 17:59:10 -0500 | [diff] [blame] | 125 | private final Map<NotificationEntry, NotificationLifetimeExtender> mRetainedNotifications = |
| 126 | new ArrayMap<>(); |
| 127 | |
Ned Burns | afe77bc | 2020-01-30 20:45:07 -0500 | [diff] [blame] | 128 | private final NotificationEntryManagerLogger mLogger; |
| 129 | |
Jason Monk | 297c04e | 2018-08-23 17:16:59 -0400 | [diff] [blame] | 130 | // Lazily retrieved dependencies |
Dave Mankoff | 02dcaf5 | 2020-01-08 15:42:06 -0500 | [diff] [blame] | 131 | private final Lazy<NotificationRowBinder> mNotificationRowBinderLazy; |
| 132 | private final Lazy<NotificationRemoteInputManager> mRemoteInputManagerLazy; |
| 133 | private final LeakDetector mLeakDetector; |
Kevin Han | f400aee | 2020-01-30 13:10:29 -0800 | [diff] [blame] | 134 | private final List<NotifCollectionListener> mNotifCollectionListeners = new ArrayList<>(); |
Eliot Courtney | 6c313d3 | 2017-12-14 19:57:51 +0900 | [diff] [blame] | 135 | |
Evan Laird | 181de62 | 2019-10-24 09:53:02 -0400 | [diff] [blame] | 136 | private final KeyguardEnvironment mKeyguardEnvironment; |
| 137 | private final NotificationGroupManager mGroupManager; |
| 138 | private final NotificationRankingManager mRankingManager; |
Beverly | 8b493df | 2019-12-18 14:16:50 -0500 | [diff] [blame] | 139 | private final FeatureFlags mFeatureFlags; |
Evan Laird | 0437366 | 2020-01-24 17:37:39 -0500 | [diff] [blame] | 140 | private final ForegroundServiceDismissalFeatureController mFgsFeatureController; |
Evan Laird | 181de62 | 2019-10-24 09:53:02 -0400 | [diff] [blame] | 141 | |
Jason Monk | 297c04e | 2018-08-23 17:16:59 -0400 | [diff] [blame] | 142 | private NotificationPresenter mPresenter; |
Evan Laird | 181de62 | 2019-10-24 09:53:02 -0400 | [diff] [blame] | 143 | private RankingMap mLatestRankingMap; |
Ned Burns | f36c625 | 2019-01-09 19:12:33 -0500 | [diff] [blame] | 144 | |
Ned Burns | dc10c95 | 2018-11-21 14:36:21 -0500 | [diff] [blame] | 145 | @VisibleForTesting |
| 146 | final ArrayList<NotificationLifetimeExtender> mNotificationLifetimeExtenders |
Kevin | a5ff1fa | 2018-08-21 16:35:48 -0700 | [diff] [blame] | 147 | = new ArrayList<>(); |
Gus Prevas | d65c2db | 2018-12-18 17:13:38 -0500 | [diff] [blame] | 148 | private final List<NotificationEntryListener> mNotificationEntryListeners = new ArrayList<>(); |
Evan Laird | 0437366 | 2020-01-24 17:37:39 -0500 | [diff] [blame] | 149 | private final List<NotificationRemoveInterceptor> mRemoveInterceptors = new ArrayList<>(); |
Eliot Courtney | a6d8cf2 | 2017-10-20 13:26:58 +0900 | [diff] [blame] | 150 | |
Eliot Courtney | a6d8cf2 | 2017-10-20 13:26:58 +0900 | [diff] [blame] | 151 | @Override |
| 152 | public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { |
| 153 | pw.println("NotificationEntryManager state:"); |
| 154 | pw.print(" mPendingNotifications="); |
| 155 | if (mPendingNotifications.size() == 0) { |
| 156 | pw.println("null"); |
| 157 | } else { |
Ned Burns | f81c4c4 | 2019-01-07 14:10:43 -0500 | [diff] [blame] | 158 | for (NotificationEntry entry : mPendingNotifications.values()) { |
Ned Burns | 00b4b2d | 2019-10-17 22:09:27 -0400 | [diff] [blame] | 159 | pw.println(entry.getSbn()); |
Eliot Courtney | a6d8cf2 | 2017-10-20 13:26:58 +0900 | [diff] [blame] | 160 | } |
| 161 | } |
Evan Laird | 0437366 | 2020-01-24 17:37:39 -0500 | [diff] [blame] | 162 | pw.println(" Remove interceptors registered:"); |
| 163 | for (NotificationRemoveInterceptor interceptor : mRemoveInterceptors) { |
| 164 | pw.println(" " + interceptor.getClass().getSimpleName()); |
| 165 | } |
| 166 | pw.println(" Lifetime extenders registered:"); |
| 167 | for (NotificationLifetimeExtender extender : mNotificationLifetimeExtenders) { |
| 168 | pw.println(" " + extender.getClass().getSimpleName()); |
| 169 | } |
Ned Burns | a5dad55 | 2019-01-29 17:59:10 -0500 | [diff] [blame] | 170 | pw.println(" Lifetime-extended notifications:"); |
| 171 | if (mRetainedNotifications.isEmpty()) { |
| 172 | pw.println(" None"); |
| 173 | } else { |
| 174 | for (Map.Entry<NotificationEntry, NotificationLifetimeExtender> entry |
| 175 | : mRetainedNotifications.entrySet()) { |
Ned Burns | 00b4b2d | 2019-10-17 22:09:27 -0400 | [diff] [blame] | 176 | pw.println(" " + entry.getKey().getSbn() + " retained by " |
Ned Burns | a5dad55 | 2019-01-29 17:59:10 -0500 | [diff] [blame] | 177 | + entry.getValue().getClass().getName()); |
| 178 | } |
| 179 | } |
Eliot Courtney | a6d8cf2 | 2017-10-20 13:26:58 +0900 | [diff] [blame] | 180 | } |
| 181 | |
Sergey Nikolaienkov | f6ad632 | 2020-02-10 15:46:32 +0100 | [diff] [blame] | 182 | /** |
| 183 | * Injected constructor. See {@link NotificationsModule}. |
| 184 | */ |
Steve Elliott | 58adc21 | 2019-10-15 11:07:54 -0400 | [diff] [blame] | 185 | public NotificationEntryManager( |
Ned Burns | afe77bc | 2020-01-30 20:45:07 -0500 | [diff] [blame] | 186 | NotificationEntryManagerLogger logger, |
Evan Laird | 181de62 | 2019-10-24 09:53:02 -0400 | [diff] [blame] | 187 | NotificationGroupManager groupManager, |
| 188 | NotificationRankingManager rankingManager, |
Beverly | 8b493df | 2019-12-18 14:16:50 -0500 | [diff] [blame] | 189 | KeyguardEnvironment keyguardEnvironment, |
Dave Mankoff | 02dcaf5 | 2020-01-08 15:42:06 -0500 | [diff] [blame] | 190 | FeatureFlags featureFlags, |
| 191 | Lazy<NotificationRowBinder> notificationRowBinderLazy, |
| 192 | Lazy<NotificationRemoteInputManager> notificationRemoteInputManagerLazy, |
Evan Laird | 0437366 | 2020-01-24 17:37:39 -0500 | [diff] [blame] | 193 | LeakDetector leakDetector, |
| 194 | ForegroundServiceDismissalFeatureController fgsFeatureController) { |
Ned Burns | afe77bc | 2020-01-30 20:45:07 -0500 | [diff] [blame] | 195 | mLogger = logger; |
Evan Laird | 181de62 | 2019-10-24 09:53:02 -0400 | [diff] [blame] | 196 | mGroupManager = groupManager; |
| 197 | mRankingManager = rankingManager; |
| 198 | mKeyguardEnvironment = keyguardEnvironment; |
Beverly | 8b493df | 2019-12-18 14:16:50 -0500 | [diff] [blame] | 199 | mFeatureFlags = featureFlags; |
Dave Mankoff | 02dcaf5 | 2020-01-08 15:42:06 -0500 | [diff] [blame] | 200 | mNotificationRowBinderLazy = notificationRowBinderLazy; |
| 201 | mRemoteInputManagerLazy = notificationRemoteInputManagerLazy; |
| 202 | mLeakDetector = leakDetector; |
Evan Laird | 0437366 | 2020-01-24 17:37:39 -0500 | [diff] [blame] | 203 | mFgsFeatureController = fgsFeatureController; |
Jason Monk | 297c04e | 2018-08-23 17:16:59 -0400 | [diff] [blame] | 204 | } |
| 205 | |
Ned Burns | 2246b33 | 2019-12-12 14:39:13 -0500 | [diff] [blame] | 206 | /** Once called, the NEM will start processing notification events from system server. */ |
| 207 | public void attach(NotificationListener notificationListener) { |
Ned Burns | e6855d6 | 2019-12-19 16:38:08 -0500 | [diff] [blame] | 208 | notificationListener.addNotificationHandler(mNotifListener); |
Ned Burns | 2246b33 | 2019-12-12 14:39:13 -0500 | [diff] [blame] | 209 | } |
| 210 | |
Gus Prevas | d65c2db | 2018-12-18 17:13:38 -0500 | [diff] [blame] | 211 | /** Adds a {@link NotificationEntryListener}. */ |
| 212 | public void addNotificationEntryListener(NotificationEntryListener listener) { |
| 213 | mNotificationEntryListeners.add(listener); |
Eliot Courtney | a6d8cf2 | 2017-10-20 13:26:58 +0900 | [diff] [blame] | 214 | } |
| 215 | |
Steve Elliott | 984cfec | 2019-10-21 15:28:05 -0400 | [diff] [blame] | 216 | /** |
| 217 | * Removes a {@link NotificationEntryListener} previously registered via |
| 218 | * {@link #addNotificationEntryListener(NotificationEntryListener)}. |
| 219 | */ |
| 220 | public void removeNotificationEntryListener(NotificationEntryListener listener) { |
| 221 | mNotificationEntryListeners.remove(listener); |
| 222 | } |
| 223 | |
Evan Laird | 0437366 | 2020-01-24 17:37:39 -0500 | [diff] [blame] | 224 | /** Add a {@link NotificationRemoveInterceptor}. */ |
| 225 | public void addNotificationRemoveInterceptor(NotificationRemoveInterceptor interceptor) { |
| 226 | mRemoveInterceptors.add(interceptor); |
| 227 | } |
| 228 | |
| 229 | /** Remove a {@link NotificationRemoveInterceptor} */ |
| 230 | public void removeNotificationRemoveInterceptor(NotificationRemoveInterceptor interceptor) { |
| 231 | mRemoveInterceptors.remove(interceptor); |
Mady Mellor | c2ff011 | 2019-03-28 14:18:06 -0700 | [diff] [blame] | 232 | } |
| 233 | |
Beverly | 95a0802ac | 2020-02-10 15:27:40 -0500 | [diff] [blame] | 234 | public void setUpWithPresenter(NotificationPresenter presenter) { |
Eliot Courtney | a6d8cf2 | 2017-10-20 13:26:58 +0900 | [diff] [blame] | 235 | mPresenter = presenter; |
Eliot Courtney | a6d8cf2 | 2017-10-20 13:26:58 +0900 | [diff] [blame] | 236 | } |
| 237 | |
Gus Prevas | 5c84abb | 2018-12-28 16:41:49 -0500 | [diff] [blame] | 238 | /** Adds multiple {@link NotificationLifetimeExtender}s. */ |
| 239 | public void addNotificationLifetimeExtenders(List<NotificationLifetimeExtender> extenders) { |
| 240 | for (NotificationLifetimeExtender extender : extenders) { |
| 241 | addNotificationLifetimeExtender(extender); |
| 242 | } |
| 243 | } |
| 244 | |
| 245 | /** Adds a {@link NotificationLifetimeExtender}. */ |
| 246 | public void addNotificationLifetimeExtender(NotificationLifetimeExtender extender) { |
| 247 | mNotificationLifetimeExtenders.add(extender); |
Mady Mellor | 1a4e86f | 2019-05-03 16:07:23 -0700 | [diff] [blame] | 248 | extender.setCallback(key -> removeNotification(key, mLatestRankingMap, |
| 249 | UNDEFINED_DISMISS_REASON)); |
Gus Prevas | 5c84abb | 2018-12-28 16:41:49 -0500 | [diff] [blame] | 250 | } |
| 251 | |
Eliot Courtney | 2b4c3a0 | 2017-11-27 13:27:46 +0900 | [diff] [blame] | 252 | @Override |
Selim Cinek | ba069ae | 2020-04-01 19:45:16 -0700 | [diff] [blame] | 253 | public void onChangeAllowed() { |
Beverly | 85d4c19 | 2019-09-30 11:40:39 -0400 | [diff] [blame] | 254 | updateNotifications("reordering is now allowed"); |
Eliot Courtney | 2b4c3a0 | 2017-11-27 13:27:46 +0900 | [diff] [blame] | 255 | } |
| 256 | |
Mady Mellor | c2ff011 | 2019-03-28 14:18:06 -0700 | [diff] [blame] | 257 | /** |
| 258 | * Requests a notification to be removed. |
| 259 | * |
| 260 | * @param n the notification to remove. |
| 261 | * @param reason why it is being removed e.g. {@link NotificationListenerService#REASON_CANCEL}, |
| 262 | * or 0 if unknown. |
| 263 | */ |
| 264 | public void performRemoveNotification(StatusBarNotification n, int reason) { |
Selim Cinek | 7bc9be7 | 2019-03-06 18:42:05 -0800 | [diff] [blame] | 265 | final NotificationVisibility nv = obtainVisibility(n.getKey()); |
Gus Prevas | ca1b6f7 | 2018-12-28 10:53:11 -0500 | [diff] [blame] | 266 | removeNotificationInternal( |
Mady Mellor | c2ff011 | 2019-03-28 14:18:06 -0700 | [diff] [blame] | 267 | n.getKey(), null, nv, false /* forceRemove */, true /* removedByUser */, |
| 268 | reason); |
Eliot Courtney | a6d8cf2 | 2017-10-20 13:26:58 +0900 | [diff] [blame] | 269 | } |
| 270 | |
Selim Cinek | 7bc9be7 | 2019-03-06 18:42:05 -0800 | [diff] [blame] | 271 | private NotificationVisibility obtainVisibility(String key) { |
Evan Laird | 181de62 | 2019-10-24 09:53:02 -0400 | [diff] [blame] | 272 | NotificationEntry e = mActiveNotifications.get(key); |
| 273 | final int rank; |
| 274 | if (e != null) { |
| 275 | rank = e.getRanking().getRank(); |
| 276 | } else { |
| 277 | rank = 0; |
| 278 | } |
| 279 | |
| 280 | final int count = mActiveNotifications.size(); |
Selim Cinek | 7bc9be7 | 2019-03-06 18:42:05 -0800 | [diff] [blame] | 281 | NotificationVisibility.NotificationLocation location = |
Evan Laird | 181de62 | 2019-10-24 09:53:02 -0400 | [diff] [blame] | 282 | NotificationLogger.getNotificationLocation(getActiveNotificationUnfiltered(key)); |
Selim Cinek | 7bc9be7 | 2019-03-06 18:42:05 -0800 | [diff] [blame] | 283 | return NotificationVisibility.obtain(key, rank, count, true, location); |
| 284 | } |
| 285 | |
Beverly | 85d4c19 | 2019-09-30 11:40:39 -0400 | [diff] [blame] | 286 | private void abortExistingInflation(String key, String reason) { |
Eliot Courtney | a6d8cf2 | 2017-10-20 13:26:58 +0900 | [diff] [blame] | 287 | if (mPendingNotifications.containsKey(key)) { |
Ned Burns | f81c4c4 | 2019-01-07 14:10:43 -0500 | [diff] [blame] | 288 | NotificationEntry entry = mPendingNotifications.get(key); |
Eliot Courtney | a6d8cf2 | 2017-10-20 13:26:58 +0900 | [diff] [blame] | 289 | entry.abortTask(); |
| 290 | mPendingNotifications.remove(key); |
Kevin Han | d5ca459 | 2020-02-10 15:18:46 -0800 | [diff] [blame] | 291 | for (NotifCollectionListener listener : mNotifCollectionListeners) { |
| 292 | listener.onEntryCleanUp(entry); |
| 293 | } |
Ned Burns | afe77bc | 2020-01-30 20:45:07 -0500 | [diff] [blame] | 294 | mLogger.logInflationAborted(key, "pending", reason); |
Eliot Courtney | a6d8cf2 | 2017-10-20 13:26:58 +0900 | [diff] [blame] | 295 | } |
Evan Laird | 181de62 | 2019-10-24 09:53:02 -0400 | [diff] [blame] | 296 | NotificationEntry addedEntry = getActiveNotificationUnfiltered(key); |
Eliot Courtney | a6d8cf2 | 2017-10-20 13:26:58 +0900 | [diff] [blame] | 297 | if (addedEntry != null) { |
| 298 | addedEntry.abortTask(); |
Ned Burns | afe77bc | 2020-01-30 20:45:07 -0500 | [diff] [blame] | 299 | mLogger.logInflationAborted(key, "active", reason); |
Eliot Courtney | a6d8cf2 | 2017-10-20 13:26:58 +0900 | [diff] [blame] | 300 | } |
| 301 | } |
| 302 | |
Ned Burns | dc10c95 | 2018-11-21 14:36:21 -0500 | [diff] [blame] | 303 | /** |
| 304 | * Cancel this notification and tell the StatusBarManagerService / NotificationManagerService |
| 305 | * about the failure. |
| 306 | * |
| 307 | * WARNING: this will call back into us. Don't hold any locks. |
| 308 | */ |
Kevin Han | bd14293 | 2020-03-10 18:27:50 -0700 | [diff] [blame] | 309 | private void handleInflationException(StatusBarNotification n, Exception e) { |
Gus Prevas | dca2be5 | 2018-12-21 11:25:10 -0500 | [diff] [blame] | 310 | removeNotificationInternal( |
Mady Mellor | c2ff011 | 2019-03-28 14:18:06 -0700 | [diff] [blame] | 311 | n.getKey(), null, null, true /* forceRemove */, false /* removedByUser */, |
| 312 | REASON_ERROR); |
Gus Prevas | ca1b6f7 | 2018-12-28 10:53:11 -0500 | [diff] [blame] | 313 | for (NotificationEntryListener listener : mNotificationEntryListeners) { |
| 314 | listener.onInflationError(n, e); |
Ned Burns | dc10c95 | 2018-11-21 14:36:21 -0500 | [diff] [blame] | 315 | } |
Eliot Courtney | a6d8cf2 | 2017-10-20 13:26:58 +0900 | [diff] [blame] | 316 | } |
| 317 | |
Kevin Han | bd14293 | 2020-03-10 18:27:50 -0700 | [diff] [blame] | 318 | private final InflationCallback mInflationCallback = new InflationCallback() { |
| 319 | @Override |
| 320 | public void handleInflationException(NotificationEntry entry, Exception e) { |
| 321 | NotificationEntryManager.this.handleInflationException(entry.getSbn(), e); |
| 322 | } |
| 323 | |
| 324 | @Override |
| 325 | public void onAsyncInflationFinished(NotificationEntry entry) { |
| 326 | mPendingNotifications.remove(entry.getKey()); |
| 327 | // If there was an async task started after the removal, we don't want to add it back to |
| 328 | // the list, otherwise we might get leaks. |
| 329 | if (!entry.isRowRemoved()) { |
| 330 | boolean isNew = getActiveNotificationUnfiltered(entry.getKey()) == null; |
| 331 | mLogger.logNotifInflated(entry.getKey(), isNew); |
| 332 | if (isNew) { |
| 333 | for (NotificationEntryListener listener : mNotificationEntryListeners) { |
| 334 | listener.onEntryInflated(entry); |
| 335 | } |
| 336 | addActiveNotification(entry); |
| 337 | updateNotifications("onAsyncInflationFinished"); |
| 338 | for (NotificationEntryListener listener : mNotificationEntryListeners) { |
| 339 | listener.onNotificationAdded(entry); |
| 340 | } |
| 341 | } else { |
| 342 | for (NotificationEntryListener listener : mNotificationEntryListeners) { |
| 343 | listener.onEntryReinflated(entry); |
| 344 | } |
Ned Burns | 3d6b396 | 2018-12-07 21:26:00 -0500 | [diff] [blame] | 345 | } |
Kevin | 01a53cb | 2018-11-09 18:19:54 -0800 | [diff] [blame] | 346 | } |
Eliot Courtney | a6d8cf2 | 2017-10-20 13:26:58 +0900 | [diff] [blame] | 347 | } |
Kevin Han | bd14293 | 2020-03-10 18:27:50 -0700 | [diff] [blame] | 348 | }; |
Eliot Courtney | a6d8cf2 | 2017-10-20 13:26:58 +0900 | [diff] [blame] | 349 | |
Ned Burns | e6855d6 | 2019-12-19 16:38:08 -0500 | [diff] [blame] | 350 | private final NotificationHandler mNotifListener = new NotificationHandler() { |
Ned Burns | 2246b33 | 2019-12-12 14:39:13 -0500 | [diff] [blame] | 351 | @Override |
| 352 | public void onNotificationPosted(StatusBarNotification sbn, RankingMap rankingMap) { |
| 353 | final boolean isUpdate = mActiveNotifications.containsKey(sbn.getKey()); |
| 354 | if (isUpdate) { |
| 355 | updateNotification(sbn, rankingMap); |
| 356 | } else { |
| 357 | addNotification(sbn, rankingMap); |
| 358 | } |
| 359 | } |
| 360 | |
| 361 | @Override |
| 362 | public void onNotificationRemoved(StatusBarNotification sbn, RankingMap rankingMap) { |
| 363 | removeNotification(sbn.getKey(), rankingMap, UNDEFINED_DISMISS_REASON); |
| 364 | } |
| 365 | |
| 366 | @Override |
| 367 | public void onNotificationRemoved( |
| 368 | StatusBarNotification sbn, |
| 369 | RankingMap rankingMap, |
| 370 | int reason) { |
| 371 | removeNotification(sbn.getKey(), rankingMap, reason); |
| 372 | } |
| 373 | |
| 374 | @Override |
| 375 | public void onNotificationRankingUpdate(RankingMap rankingMap) { |
| 376 | updateNotificationRanking(rankingMap); |
| 377 | } |
| 378 | }; |
| 379 | |
Evan Laird | 181de62 | 2019-10-24 09:53:02 -0400 | [diff] [blame] | 380 | /** |
| 381 | * Equivalent to the old NotificationData#add |
| 382 | * @param entry - an entry which is prepared for display |
| 383 | */ |
| 384 | private void addActiveNotification(NotificationEntry entry) { |
| 385 | Assert.isMainThread(); |
| 386 | |
| 387 | mActiveNotifications.put(entry.getKey(), entry); |
| 388 | mGroupManager.onEntryAdded(entry); |
| 389 | updateRankingAndSort(mRankingManager.getRankingMap(), "addEntryInternalInternal"); |
| 390 | } |
| 391 | |
| 392 | /** |
| 393 | * Available so that tests can directly manipulate the list of active notifications easily |
| 394 | * |
| 395 | * @param entry the entry to add directly to the visible notification map |
| 396 | */ |
| 397 | @VisibleForTesting |
| 398 | public void addActiveNotificationForTest(NotificationEntry entry) { |
| 399 | mActiveNotifications.put(entry.getKey(), entry); |
| 400 | mGroupManager.onEntryAdded(entry); |
| 401 | |
| 402 | reapplyFilterAndSort("addVisibleNotification"); |
| 403 | } |
| 404 | |
| 405 | |
Evan Laird | 181de62 | 2019-10-24 09:53:02 -0400 | [diff] [blame] | 406 | public void removeNotification(String key, RankingMap ranking, |
Mady Mellor | c2ff011 | 2019-03-28 14:18:06 -0700 | [diff] [blame] | 407 | int reason) { |
Selim Cinek | 7bc9be7 | 2019-03-06 18:42:05 -0800 | [diff] [blame] | 408 | removeNotificationInternal(key, ranking, obtainVisibility(key), false /* forceRemove */, |
Mady Mellor | c2ff011 | 2019-03-28 14:18:06 -0700 | [diff] [blame] | 409 | false /* removedByUser */, reason); |
Kevin | a5ff1fa | 2018-08-21 16:35:48 -0700 | [diff] [blame] | 410 | } |
| 411 | |
Gus Prevas | dca2be5 | 2018-12-21 11:25:10 -0500 | [diff] [blame] | 412 | private void removeNotificationInternal( |
| 413 | String key, |
Evan Laird | 181de62 | 2019-10-24 09:53:02 -0400 | [diff] [blame] | 414 | @Nullable RankingMap ranking, |
Gus Prevas | ca1b6f7 | 2018-12-28 10:53:11 -0500 | [diff] [blame] | 415 | @Nullable NotificationVisibility visibility, |
Gus Prevas | dca2be5 | 2018-12-21 11:25:10 -0500 | [diff] [blame] | 416 | boolean forceRemove, |
Mady Mellor | c2ff011 | 2019-03-28 14:18:06 -0700 | [diff] [blame] | 417 | boolean removedByUser, |
| 418 | int reason) { |
| 419 | |
Evan Laird | 0437366 | 2020-01-24 17:37:39 -0500 | [diff] [blame] | 420 | final NotificationEntry entry = getActiveNotificationUnfiltered(key); |
| 421 | |
| 422 | for (NotificationRemoveInterceptor interceptor : mRemoveInterceptors) { |
| 423 | if (interceptor.onNotificationRemoveRequested(key, entry, reason)) { |
| 424 | // Remove intercepted; log and skip |
Ned Burns | afe77bc | 2020-01-30 20:45:07 -0500 | [diff] [blame] | 425 | mLogger.logRemovalIntercepted(key); |
Evan Laird | 0437366 | 2020-01-24 17:37:39 -0500 | [diff] [blame] | 426 | return; |
| 427 | } |
Mady Mellor | c2ff011 | 2019-03-28 14:18:06 -0700 | [diff] [blame] | 428 | } |
| 429 | |
Gus Prevas | f37435a | 2018-12-20 15:40:01 -0500 | [diff] [blame] | 430 | boolean lifetimeExtended = false; |
| 431 | |
Evan Laird | 3ceaa9b | 2019-08-05 17:11:54 -0400 | [diff] [blame] | 432 | // Notification was canceled before it got inflated |
| 433 | if (entry == null) { |
| 434 | NotificationEntry pendingEntry = mPendingNotifications.get(key); |
| 435 | if (pendingEntry != null) { |
| 436 | for (NotificationLifetimeExtender extender : mNotificationLifetimeExtenders) { |
| 437 | if (extender.shouldExtendLifetimeForPendingNotification(pendingEntry)) { |
| 438 | extendLifetime(pendingEntry, extender); |
| 439 | lifetimeExtended = true; |
Ned Burns | afe77bc | 2020-01-30 20:45:07 -0500 | [diff] [blame] | 440 | mLogger.logLifetimeExtended(key, extender.getClass().getName(), "pending"); |
Evan Laird | 3ceaa9b | 2019-08-05 17:11:54 -0400 | [diff] [blame] | 441 | } |
| 442 | } |
Beverly | 8ca664b | 2020-05-07 14:46:50 -0400 | [diff] [blame] | 443 | if (!lifetimeExtended) { |
| 444 | // At this point, we are guaranteed the notification will be removed |
| 445 | mAllNotifications.remove(pendingEntry); |
| 446 | } |
Evan Laird | 3ceaa9b | 2019-08-05 17:11:54 -0400 | [diff] [blame] | 447 | } |
| 448 | } |
| 449 | |
| 450 | if (!lifetimeExtended) { |
Beverly | 85d4c19 | 2019-09-30 11:40:39 -0400 | [diff] [blame] | 451 | abortExistingInflation(key, "removeNotification"); |
Evan Laird | 3ceaa9b | 2019-08-05 17:11:54 -0400 | [diff] [blame] | 452 | } |
| 453 | |
Gus Prevas | d65c2db | 2018-12-18 17:13:38 -0500 | [diff] [blame] | 454 | if (entry != null) { |
Gus Prevas | f37435a | 2018-12-20 15:40:01 -0500 | [diff] [blame] | 455 | // If a manager needs to keep the notification around for whatever reason, we |
| 456 | // keep the notification |
Selim Cinek | 7bc9be7 | 2019-03-06 18:42:05 -0800 | [diff] [blame] | 457 | boolean entryDismissed = entry.isRowDismissed(); |
| 458 | if (!forceRemove && !entryDismissed) { |
Gus Prevas | f37435a | 2018-12-20 15:40:01 -0500 | [diff] [blame] | 459 | for (NotificationLifetimeExtender extender : mNotificationLifetimeExtenders) { |
| 460 | if (extender.shouldExtendLifetime(entry)) { |
| 461 | mLatestRankingMap = ranking; |
Ned Burns | a5dad55 | 2019-01-29 17:59:10 -0500 | [diff] [blame] | 462 | extendLifetime(entry, extender); |
Gus Prevas | f37435a | 2018-12-20 15:40:01 -0500 | [diff] [blame] | 463 | lifetimeExtended = true; |
Ned Burns | afe77bc | 2020-01-30 20:45:07 -0500 | [diff] [blame] | 464 | mLogger.logLifetimeExtended(key, extender.getClass().getName(), "active"); |
Gus Prevas | f37435a | 2018-12-20 15:40:01 -0500 | [diff] [blame] | 465 | break; |
| 466 | } |
Kevin | a5ff1fa | 2018-08-21 16:35:48 -0700 | [diff] [blame] | 467 | } |
| 468 | } |
Gus Prevas | f37435a | 2018-12-20 15:40:01 -0500 | [diff] [blame] | 469 | |
| 470 | if (!lifetimeExtended) { |
| 471 | // At this point, we are guaranteed the notification will be removed |
| 472 | |
| 473 | // Ensure any managers keeping the lifetime extended stop managing the entry |
Ned Burns | a5dad55 | 2019-01-29 17:59:10 -0500 | [diff] [blame] | 474 | cancelLifetimeExtension(entry); |
Gus Prevas | f37435a | 2018-12-20 15:40:01 -0500 | [diff] [blame] | 475 | |
Gus Prevas | f37435a | 2018-12-20 15:40:01 -0500 | [diff] [blame] | 476 | if (entry.rowExists()) { |
| 477 | entry.removeRow(); |
Gus Prevas | f37435a | 2018-12-20 15:40:01 -0500 | [diff] [blame] | 478 | } |
| 479 | |
Ned Burns | 88aeaf7 | 2020-03-13 20:45:19 -0400 | [diff] [blame] | 480 | mAllNotifications.remove(entry); |
| 481 | |
Gus Prevas | f37435a | 2018-12-20 15:40:01 -0500 | [diff] [blame] | 482 | // Let's remove the children if this was a summary |
| 483 | handleGroupSummaryRemoved(key); |
Evan Laird | 181de62 | 2019-10-24 09:53:02 -0400 | [diff] [blame] | 484 | removeVisibleNotification(key); |
Beverly | 85d4c19 | 2019-09-30 11:40:39 -0400 | [diff] [blame] | 485 | updateNotifications("removeNotificationInternal"); |
Dave Mankoff | 02dcaf5 | 2020-01-08 15:42:06 -0500 | [diff] [blame] | 486 | mLeakDetector.trackGarbage(entry); |
Selim Cinek | 7bc9be7 | 2019-03-06 18:42:05 -0800 | [diff] [blame] | 487 | removedByUser |= entryDismissed; |
Eliot Courtney | a6d8cf2 | 2017-10-20 13:26:58 +0900 | [diff] [blame] | 488 | |
Ned Burns | afe77bc | 2020-01-30 20:45:07 -0500 | [diff] [blame] | 489 | mLogger.logNotifRemoved(entry.getKey(), removedByUser); |
Ned Burns | ef2ef6c | 2019-01-02 16:48:08 -0500 | [diff] [blame] | 490 | for (NotificationEntryListener listener : mNotificationEntryListeners) { |
Julia Reynolds | 138111f | 2020-02-26 11:17:39 -0500 | [diff] [blame] | 491 | listener.onEntryRemoved(entry, visibility, removedByUser, reason); |
Ned Burns | ef2ef6c | 2019-01-02 16:48:08 -0500 | [diff] [blame] | 492 | } |
Kevin Han | f400aee | 2020-01-30 13:10:29 -0800 | [diff] [blame] | 493 | for (NotifCollectionListener listener : mNotifCollectionListeners) { |
| 494 | // NEM doesn't have a good knowledge of reasons so defaulting to unknown. |
| 495 | listener.onEntryRemoved(entry, REASON_UNKNOWN); |
| 496 | } |
| 497 | for (NotifCollectionListener listener : mNotifCollectionListeners) { |
| 498 | listener.onEntryCleanUp(entry); |
| 499 | } |
Ned Burns | ef2ef6c | 2019-01-02 16:48:08 -0500 | [diff] [blame] | 500 | } |
Gus Prevas | 8621bd2 | 2018-12-20 15:04:25 -0500 | [diff] [blame] | 501 | } |
Eliot Courtney | a6d8cf2 | 2017-10-20 13:26:58 +0900 | [diff] [blame] | 502 | } |
| 503 | |
Eliot Courtney | a6d8cf2 | 2017-10-20 13:26:58 +0900 | [diff] [blame] | 504 | /** |
| 505 | * Ensures that the group children are cancelled immediately when the group summary is cancelled |
| 506 | * instead of waiting for the notification manager to send all cancels. Otherwise this could |
| 507 | * lead to flickers. |
| 508 | * |
| 509 | * This also ensures that the animation looks nice and only consists of a single disappear |
| 510 | * animation instead of multiple. |
| 511 | * @param key the key of the notification was removed |
| 512 | * |
| 513 | */ |
| 514 | private void handleGroupSummaryRemoved(String key) { |
Evan Laird | 181de62 | 2019-10-24 09:53:02 -0400 | [diff] [blame] | 515 | NotificationEntry entry = getActiveNotificationUnfiltered(key); |
Evan Laird | 9449285 | 2018-10-25 13:43:01 -0400 | [diff] [blame] | 516 | if (entry != null && entry.rowExists() && entry.isSummaryWithChildren()) { |
Ned Burns | 00b4b2d | 2019-10-17 22:09:27 -0400 | [diff] [blame] | 517 | if (entry.getSbn().getOverrideGroupKey() != null && !entry.isRowDismissed()) { |
Eliot Courtney | a6d8cf2 | 2017-10-20 13:26:58 +0900 | [diff] [blame] | 518 | // We don't want to remove children for autobundled notifications as they are not |
| 519 | // always cancelled. We only remove them if they were dismissed by the user. |
| 520 | return; |
| 521 | } |
Kevin Han | 43077f9 | 2020-02-28 12:51:53 -0800 | [diff] [blame] | 522 | List<NotificationEntry> childEntries = entry.getAttachedNotifChildren(); |
Evan Laird | 9449285 | 2018-10-25 13:43:01 -0400 | [diff] [blame] | 523 | if (childEntries == null) { |
| 524 | return; |
| 525 | } |
| 526 | for (int i = 0; i < childEntries.size(); i++) { |
Ned Burns | f81c4c4 | 2019-01-07 14:10:43 -0500 | [diff] [blame] | 527 | NotificationEntry childEntry = childEntries.get(i); |
Ned Burns | 00b4b2d | 2019-10-17 22:09:27 -0400 | [diff] [blame] | 528 | boolean isForeground = (entry.getSbn().getNotification().flags |
Selim Cinek | 038e259 | 2018-08-16 16:30:45 -0700 | [diff] [blame] | 529 | & Notification.FLAG_FOREGROUND_SERVICE) != 0; |
Kevin | a5ff1fa | 2018-08-21 16:35:48 -0700 | [diff] [blame] | 530 | boolean keepForReply = |
Dave Mankoff | 02dcaf5 | 2020-01-08 15:42:06 -0500 | [diff] [blame] | 531 | mRemoteInputManagerLazy.get().shouldKeepForRemoteInputHistory(childEntry) |
| 532 | || mRemoteInputManagerLazy.get().shouldKeepForSmartReplyHistory(childEntry); |
Selim Cinek | 038e259 | 2018-08-16 16:30:45 -0700 | [diff] [blame] | 533 | if (isForeground || keepForReply) { |
| 534 | // the child is a foreground service notification which we can't remove or it's |
| 535 | // a child we're keeping around for reply! |
Eliot Courtney | a6d8cf2 | 2017-10-20 13:26:58 +0900 | [diff] [blame] | 536 | continue; |
| 537 | } |
Evan Laird | ce2d1af | 2019-05-30 16:00:22 -0400 | [diff] [blame] | 538 | childEntry.setKeepInParent(true); |
Eliot Courtney | a6d8cf2 | 2017-10-20 13:26:58 +0900 | [diff] [blame] | 539 | // we need to set this state earlier as otherwise we might generate some weird |
| 540 | // animations |
Evan Laird | ce2d1af | 2019-05-30 16:00:22 -0400 | [diff] [blame] | 541 | childEntry.removeRow(); |
Eliot Courtney | a6d8cf2 | 2017-10-20 13:26:58 +0900 | [diff] [blame] | 542 | } |
| 543 | } |
| 544 | } |
| 545 | |
Ned Burns | c411107 | 2020-04-03 01:46:55 -0400 | [diff] [blame] | 546 | private void addNotificationInternal( |
| 547 | StatusBarNotification notification, |
Evan Laird | 181de62 | 2019-10-24 09:53:02 -0400 | [diff] [blame] | 548 | RankingMap rankingMap) throws InflationException { |
Eliot Courtney | a6d8cf2 | 2017-10-20 13:26:58 +0900 | [diff] [blame] | 549 | String key = notification.getKey(); |
Kevin | a97ea05 | 2018-09-11 13:53:18 -0700 | [diff] [blame] | 550 | if (DEBUG) { |
| 551 | Log.d(TAG, "addNotification key=" + key); |
| 552 | } |
Eliot Courtney | a6d8cf2 | 2017-10-20 13:26:58 +0900 | [diff] [blame] | 553 | |
Evan Laird | 181de62 | 2019-10-24 09:53:02 -0400 | [diff] [blame] | 554 | updateRankingAndSort(rankingMap, "addNotificationInternal"); |
| 555 | |
Ned Burns | e372f32 | 2019-09-24 13:14:08 -0400 | [diff] [blame] | 556 | Ranking ranking = new Ranking(); |
Tony Mak | 628cb93 | 2018-06-19 18:30:41 +0100 | [diff] [blame] | 557 | rankingMap.getRanking(key, ranking); |
Ned Burns | 6976087 | 2019-01-03 15:36:38 -0500 | [diff] [blame] | 558 | |
Evan Laird | 0437366 | 2020-01-24 17:37:39 -0500 | [diff] [blame] | 559 | NotificationEntry entry = new NotificationEntry( |
| 560 | notification, |
| 561 | ranking, |
Evan Laird | ccf5c5e | 2020-02-06 14:01:28 -0500 | [diff] [blame] | 562 | mFgsFeatureController.isForegroundServiceDismissalEnabled(), |
| 563 | SystemClock.uptimeMillis()); |
Kevin Han | 3742322 | 2020-03-10 16:05:07 -0700 | [diff] [blame] | 564 | for (NotifCollectionListener listener : mNotifCollectionListeners) { |
| 565 | listener.onEntryBind(entry, notification); |
| 566 | } |
| 567 | mAllNotifications.add(entry); |
Ned Burns | 6976087 | 2019-01-03 15:36:38 -0500 | [diff] [blame] | 568 | |
Dave Mankoff | 02dcaf5 | 2020-01-08 15:42:06 -0500 | [diff] [blame] | 569 | mLeakDetector.trackInstance(entry); |
Beverly | 8b493df | 2019-12-18 14:16:50 -0500 | [diff] [blame] | 570 | |
Kevin Han | f400aee | 2020-01-30 13:10:29 -0800 | [diff] [blame] | 571 | for (NotifCollectionListener listener : mNotifCollectionListeners) { |
| 572 | listener.onEntryInit(entry); |
| 573 | } |
| 574 | |
Ned Burns | 6976087 | 2019-01-03 15:36:38 -0500 | [diff] [blame] | 575 | // Construct the expanded view. |
Beverly | 8b493df | 2019-12-18 14:16:50 -0500 | [diff] [blame] | 576 | if (!mFeatureFlags.isNewNotifPipelineRenderingEnabled()) { |
Dave Mankoff | 02dcaf5 | 2020-01-08 15:42:06 -0500 | [diff] [blame] | 577 | mNotificationRowBinderLazy.get() |
Kevin Han | bd14293 | 2020-03-10 18:27:50 -0700 | [diff] [blame] | 578 | .inflateViews( |
| 579 | entry, |
| 580 | () -> performRemoveNotification(notification, REASON_CANCEL), |
| 581 | mInflationCallback); |
Beverly | 8b493df | 2019-12-18 14:16:50 -0500 | [diff] [blame] | 582 | } |
Ned Burns | 6976087 | 2019-01-03 15:36:38 -0500 | [diff] [blame] | 583 | |
Beverly | 85d4c19 | 2019-09-30 11:40:39 -0400 | [diff] [blame] | 584 | abortExistingInflation(key, "addNotification"); |
Gus Prevas | d65c2db | 2018-12-18 17:13:38 -0500 | [diff] [blame] | 585 | mPendingNotifications.put(key, entry); |
Ned Burns | afe77bc | 2020-01-30 20:45:07 -0500 | [diff] [blame] | 586 | mLogger.logNotifAdded(entry.getKey()); |
Gus Prevas | d65c2db | 2018-12-18 17:13:38 -0500 | [diff] [blame] | 587 | for (NotificationEntryListener listener : mNotificationEntryListeners) { |
| 588 | listener.onPendingEntryAdded(entry); |
Ned Burns | 3d6b396 | 2018-12-07 21:26:00 -0500 | [diff] [blame] | 589 | } |
Kevin Han | f400aee | 2020-01-30 13:10:29 -0800 | [diff] [blame] | 590 | for (NotifCollectionListener listener : mNotifCollectionListeners) { |
| 591 | listener.onEntryAdded(entry); |
| 592 | } |
Ned Burns | c411107 | 2020-04-03 01:46:55 -0400 | [diff] [blame] | 593 | for (NotifCollectionListener listener : mNotifCollectionListeners) { |
| 594 | listener.onRankingApplied(); |
| 595 | } |
Eliot Courtney | a6d8cf2 | 2017-10-20 13:26:58 +0900 | [diff] [blame] | 596 | } |
| 597 | |
Evan Laird | 181de62 | 2019-10-24 09:53:02 -0400 | [diff] [blame] | 598 | public void addNotification(StatusBarNotification notification, RankingMap ranking) { |
Eliot Courtney | a6d8cf2 | 2017-10-20 13:26:58 +0900 | [diff] [blame] | 599 | try { |
| 600 | addNotificationInternal(notification, ranking); |
| 601 | } catch (InflationException e) { |
| 602 | handleInflationException(notification, e); |
| 603 | } |
| 604 | } |
| 605 | |
Eliot Courtney | a6d8cf2 | 2017-10-20 13:26:58 +0900 | [diff] [blame] | 606 | private void updateNotificationInternal(StatusBarNotification notification, |
Evan Laird | 181de62 | 2019-10-24 09:53:02 -0400 | [diff] [blame] | 607 | RankingMap ranking) throws InflationException { |
Eliot Courtney | a6d8cf2 | 2017-10-20 13:26:58 +0900 | [diff] [blame] | 608 | if (DEBUG) Log.d(TAG, "updateNotification(" + notification + ")"); |
| 609 | |
| 610 | final String key = notification.getKey(); |
Beverly | 85d4c19 | 2019-09-30 11:40:39 -0400 | [diff] [blame] | 611 | abortExistingInflation(key, "updateNotification"); |
Evan Laird | 181de62 | 2019-10-24 09:53:02 -0400 | [diff] [blame] | 612 | NotificationEntry entry = getActiveNotificationUnfiltered(key); |
Eliot Courtney | a6d8cf2 | 2017-10-20 13:26:58 +0900 | [diff] [blame] | 613 | if (entry == null) { |
| 614 | return; |
| 615 | } |
Eliot Courtney | a6d8cf2 | 2017-10-20 13:26:58 +0900 | [diff] [blame] | 616 | |
Kevin | a5ff1fa | 2018-08-21 16:35:48 -0700 | [diff] [blame] | 617 | // Notification is updated so it is essentially re-added and thus alive again. Don't need |
Kevin | e9e938c | 2018-09-06 13:38:11 -0700 | [diff] [blame] | 618 | // to keep its lifetime extended. |
Ned Burns | a5dad55 | 2019-01-29 17:59:10 -0500 | [diff] [blame] | 619 | cancelLifetimeExtension(entry); |
Eliot Courtney | a6d8cf2 | 2017-10-20 13:26:58 +0900 | [diff] [blame] | 620 | |
Evan Laird | 181de62 | 2019-10-24 09:53:02 -0400 | [diff] [blame] | 621 | updateRankingAndSort(ranking, "updateNotificationInternal"); |
| 622 | StatusBarNotification oldSbn = entry.getSbn(); |
| 623 | entry.setSbn(notification); |
Kevin Han | 3742322 | 2020-03-10 16:05:07 -0700 | [diff] [blame] | 624 | for (NotifCollectionListener listener : mNotifCollectionListeners) { |
| 625 | listener.onEntryBind(entry, notification); |
Kevin Han | f69b71e | 2020-04-13 15:46:14 -0700 | [diff] [blame] | 626 | } |
| 627 | mGroupManager.onEntryUpdated(entry, oldSbn); |
Evan Laird | 181de62 | 2019-10-24 09:53:02 -0400 | [diff] [blame] | 628 | |
Ned Burns | afe77bc | 2020-01-30 20:45:07 -0500 | [diff] [blame] | 629 | mLogger.logNotifUpdated(entry.getKey()); |
Mady Mellor | 0ad5b9d | 2019-01-08 14:59:55 -0800 | [diff] [blame] | 630 | for (NotificationEntryListener listener : mNotificationEntryListeners) { |
| 631 | listener.onPreEntryUpdated(entry); |
| 632 | } |
Kevin Han | f400aee | 2020-01-30 13:10:29 -0800 | [diff] [blame] | 633 | for (NotifCollectionListener listener : mNotifCollectionListeners) { |
| 634 | listener.onEntryUpdated(entry); |
| 635 | } |
Mady Mellor | 0ad5b9d | 2019-01-08 14:59:55 -0800 | [diff] [blame] | 636 | |
Beverly | 8b493df | 2019-12-18 14:16:50 -0500 | [diff] [blame] | 637 | if (!mFeatureFlags.isNewNotifPipelineRenderingEnabled()) { |
Dave Mankoff | 02dcaf5 | 2020-01-08 15:42:06 -0500 | [diff] [blame] | 638 | mNotificationRowBinderLazy.get() |
Kevin Han | bd14293 | 2020-03-10 18:27:50 -0700 | [diff] [blame] | 639 | .inflateViews( |
| 640 | entry, |
| 641 | () -> performRemoveNotification(notification, REASON_CANCEL), |
| 642 | mInflationCallback); |
Beverly | 8b493df | 2019-12-18 14:16:50 -0500 | [diff] [blame] | 643 | } |
| 644 | |
Beverly | 85d4c19 | 2019-09-30 11:40:39 -0400 | [diff] [blame] | 645 | updateNotifications("updateNotificationInternal"); |
Eliot Courtney | a6d8cf2 | 2017-10-20 13:26:58 +0900 | [diff] [blame] | 646 | |
Eliot Courtney | a6d8cf2 | 2017-10-20 13:26:58 +0900 | [diff] [blame] | 647 | if (DEBUG) { |
| 648 | // Is this for you? |
Dave Mankoff | 02dcaf5 | 2020-01-08 15:42:06 -0500 | [diff] [blame] | 649 | boolean isForCurrentUser = mKeyguardEnvironment |
Jason Monk | 297c04e | 2018-08-23 17:16:59 -0400 | [diff] [blame] | 650 | .isNotificationForCurrentProfiles(notification); |
Eliot Courtney | a6d8cf2 | 2017-10-20 13:26:58 +0900 | [diff] [blame] | 651 | Log.d(TAG, "notification is " + (isForCurrentUser ? "" : "not ") + "for you"); |
| 652 | } |
| 653 | |
Gus Prevas | b43dc65 | 2018-12-20 13:11:45 -0500 | [diff] [blame] | 654 | for (NotificationEntryListener listener : mNotificationEntryListeners) { |
Mady Mellor | 0ad5b9d | 2019-01-08 14:59:55 -0800 | [diff] [blame] | 655 | listener.onPostEntryUpdated(entry); |
Gus Prevas | b43dc65 | 2018-12-20 13:11:45 -0500 | [diff] [blame] | 656 | } |
Ned Burns | c411107 | 2020-04-03 01:46:55 -0400 | [diff] [blame] | 657 | for (NotifCollectionListener listener : mNotifCollectionListeners) { |
| 658 | listener.onRankingApplied(); |
| 659 | } |
Eliot Courtney | a6d8cf2 | 2017-10-20 13:26:58 +0900 | [diff] [blame] | 660 | } |
| 661 | |
Evan Laird | 181de62 | 2019-10-24 09:53:02 -0400 | [diff] [blame] | 662 | public void updateNotification(StatusBarNotification notification, RankingMap ranking) { |
Eliot Courtney | a6d8cf2 | 2017-10-20 13:26:58 +0900 | [diff] [blame] | 663 | try { |
| 664 | updateNotificationInternal(notification, ranking); |
| 665 | } catch (InflationException e) { |
| 666 | handleInflationException(notification, e); |
| 667 | } |
| 668 | } |
| 669 | |
Beverly | 85d4c19 | 2019-09-30 11:40:39 -0400 | [diff] [blame] | 670 | /** |
| 671 | * Update the notifications |
| 672 | * @param reason why the notifications are updating |
| 673 | */ |
| 674 | public void updateNotifications(String reason) { |
Evan Laird | 181de62 | 2019-10-24 09:53:02 -0400 | [diff] [blame] | 675 | reapplyFilterAndSort(reason); |
Kevin Han | 4943b86 | 2020-03-23 17:14:39 -0700 | [diff] [blame] | 676 | if (mPresenter != null && !mFeatureFlags.isNewNotifPipelineRenderingEnabled()) { |
Steve Elliott | 1ba1b7c | 2020-05-05 14:16:32 -0400 | [diff] [blame] | 677 | mPresenter.updateNotificationViews(reason); |
Ned Burns | f36c625 | 2019-01-09 19:12:33 -0500 | [diff] [blame] | 678 | } |
Eliot Courtney | a6d8cf2 | 2017-10-20 13:26:58 +0900 | [diff] [blame] | 679 | } |
| 680 | |
Evan Laird | 181de62 | 2019-10-24 09:53:02 -0400 | [diff] [blame] | 681 | public void updateNotificationRanking(RankingMap rankingMap) { |
Ned Burns | f81c4c4 | 2019-01-07 14:10:43 -0500 | [diff] [blame] | 682 | List<NotificationEntry> entries = new ArrayList<>(); |
Evan Laird | 181de62 | 2019-10-24 09:53:02 -0400 | [diff] [blame] | 683 | entries.addAll(getVisibleNotifications()); |
Tony Mak | 628cb93 | 2018-06-19 18:30:41 +0100 | [diff] [blame] | 684 | entries.addAll(mPendingNotifications.values()); |
| 685 | |
| 686 | // Has a copy of the current UI adjustments. |
| 687 | ArrayMap<String, NotificationUiAdjustment> oldAdjustments = new ArrayMap<>(); |
Gus Prevas | 33fbc15 | 2018-12-04 13:17:32 -0500 | [diff] [blame] | 688 | ArrayMap<String, Integer> oldImportances = new ArrayMap<>(); |
Ned Burns | f81c4c4 | 2019-01-07 14:10:43 -0500 | [diff] [blame] | 689 | for (NotificationEntry entry : entries) { |
Tony Mak | 628cb93 | 2018-06-19 18:30:41 +0100 | [diff] [blame] | 690 | NotificationUiAdjustment adjustment = |
| 691 | NotificationUiAdjustment.extractFromNotificationEntry(entry); |
Ned Burns | 00b4b2d | 2019-10-17 22:09:27 -0400 | [diff] [blame] | 692 | oldAdjustments.put(entry.getKey(), adjustment); |
| 693 | oldImportances.put(entry.getKey(), entry.getImportance()); |
Tony Mak | 628cb93 | 2018-06-19 18:30:41 +0100 | [diff] [blame] | 694 | } |
| 695 | |
| 696 | // Populate notification entries from the new rankings. |
Evan Laird | 181de62 | 2019-10-24 09:53:02 -0400 | [diff] [blame] | 697 | updateRankingAndSort(rankingMap, "updateNotificationRanking"); |
Tony Mak | 628cb93 | 2018-06-19 18:30:41 +0100 | [diff] [blame] | 698 | updateRankingOfPendingNotifications(rankingMap); |
| 699 | |
| 700 | // By comparing the old and new UI adjustments, reinflate the view accordingly. |
Ned Burns | f81c4c4 | 2019-01-07 14:10:43 -0500 | [diff] [blame] | 701 | for (NotificationEntry entry : entries) { |
Dave Mankoff | 02dcaf5 | 2020-01-08 15:42:06 -0500 | [diff] [blame] | 702 | mNotificationRowBinderLazy.get() |
| 703 | .onNotificationRankingUpdated( |
| 704 | entry, |
| 705 | oldImportances.get(entry.getKey()), |
| 706 | oldAdjustments.get(entry.getKey()), |
Kevin Han | 1390930 | 2020-04-15 14:53:17 -0700 | [diff] [blame] | 707 | NotificationUiAdjustment.extractFromNotificationEntry(entry), |
| 708 | mInflationCallback); |
Tony Mak | 628cb93 | 2018-06-19 18:30:41 +0100 | [diff] [blame] | 709 | } |
| 710 | |
Beverly | 85d4c19 | 2019-09-30 11:40:39 -0400 | [diff] [blame] | 711 | updateNotifications("updateNotificationRanking"); |
Mark Renouf | bbcf07f | 2019-05-09 10:42:43 -0400 | [diff] [blame] | 712 | |
| 713 | for (NotificationEntryListener listener : mNotificationEntryListeners) { |
| 714 | listener.onNotificationRankingUpdated(rankingMap); |
| 715 | } |
Kevin Han | f400aee | 2020-01-30 13:10:29 -0800 | [diff] [blame] | 716 | for (NotifCollectionListener listener : mNotifCollectionListeners) { |
| 717 | listener.onRankingUpdate(rankingMap); |
| 718 | } |
Ned Burns | c411107 | 2020-04-03 01:46:55 -0400 | [diff] [blame] | 719 | for (NotifCollectionListener listener : mNotifCollectionListeners) { |
| 720 | listener.onRankingApplied(); |
| 721 | } |
Eliot Courtney | a6d8cf2 | 2017-10-20 13:26:58 +0900 | [diff] [blame] | 722 | } |
| 723 | |
Evan Laird | 181de62 | 2019-10-24 09:53:02 -0400 | [diff] [blame] | 724 | private void updateRankingOfPendingNotifications(@Nullable RankingMap rankingMap) { |
Tony Mak | 628cb93 | 2018-06-19 18:30:41 +0100 | [diff] [blame] | 725 | if (rankingMap == null) { |
| 726 | return; |
| 727 | } |
Ned Burns | f81c4c4 | 2019-01-07 14:10:43 -0500 | [diff] [blame] | 728 | for (NotificationEntry pendingNotification : mPendingNotifications.values()) { |
Ned Burns | e372f32 | 2019-09-24 13:14:08 -0400 | [diff] [blame] | 729 | Ranking ranking = new Ranking(); |
Evan Laird | 9afe766 | 2019-10-16 17:16:39 -0400 | [diff] [blame] | 730 | if (rankingMap.getRanking(pendingNotification.getKey(), ranking)) { |
Ned Burns | e372f32 | 2019-09-24 13:14:08 -0400 | [diff] [blame] | 731 | pendingNotification.setRanking(ranking); |
| 732 | } |
Tony Mak | 628cb93 | 2018-06-19 18:30:41 +0100 | [diff] [blame] | 733 | } |
| 734 | } |
| 735 | |
Eliot Courtney | a6d8cf2 | 2017-10-20 13:26:58 +0900 | [diff] [blame] | 736 | /** |
Ned Burns | 3d6b396 | 2018-12-07 21:26:00 -0500 | [diff] [blame] | 737 | * @return An iterator for all "pending" notifications. Pending notifications are newly-posted |
| 738 | * notifications whose views have not yet been inflated. In general, the system pretends like |
| 739 | * these don't exist, although there are a couple exceptions. |
| 740 | */ |
Ned Burns | f81c4c4 | 2019-01-07 14:10:43 -0500 | [diff] [blame] | 741 | public Iterable<NotificationEntry> getPendingNotificationsIterator() { |
Ned Burns | 3d6b396 | 2018-12-07 21:26:00 -0500 | [diff] [blame] | 742 | return mPendingNotifications.values(); |
| 743 | } |
Ned Burns | a5dad55 | 2019-01-29 17:59:10 -0500 | [diff] [blame] | 744 | |
Beverly | 201cdd5 | 2019-10-18 14:30:46 -0400 | [diff] [blame] | 745 | /** |
Evan Laird | 181de62 | 2019-10-24 09:53:02 -0400 | [diff] [blame] | 746 | * Use this method to retrieve a notification entry that has been prepared for presentation. |
| 747 | * Note that the notification may be filtered out and never shown to the user. |
| 748 | * |
| 749 | * @see #getVisibleNotifications() for the currently sorted and filtered list |
| 750 | * |
| 751 | * @return a {@link NotificationEntry} if it has been prepared, else null |
| 752 | */ |
| 753 | public NotificationEntry getActiveNotificationUnfiltered(String key) { |
| 754 | return mActiveNotifications.get(key); |
| 755 | } |
| 756 | |
| 757 | /** |
Beverly | 201cdd5 | 2019-10-18 14:30:46 -0400 | [diff] [blame] | 758 | * Gets the pending or visible notification entry with the given key. Returns null if |
| 759 | * notification doesn't exist. |
| 760 | */ |
Evan Laird | 181de62 | 2019-10-24 09:53:02 -0400 | [diff] [blame] | 761 | public NotificationEntry getPendingOrActiveNotif(String key) { |
Beverly | 201cdd5 | 2019-10-18 14:30:46 -0400 | [diff] [blame] | 762 | if (mPendingNotifications.containsKey(key)) { |
| 763 | return mPendingNotifications.get(key); |
| 764 | } else { |
Evan Laird | 181de62 | 2019-10-24 09:53:02 -0400 | [diff] [blame] | 765 | return mActiveNotifications.get(key); |
Beverly | 201cdd5 | 2019-10-18 14:30:46 -0400 | [diff] [blame] | 766 | } |
| 767 | } |
| 768 | |
Ned Burns | a5dad55 | 2019-01-29 17:59:10 -0500 | [diff] [blame] | 769 | private void extendLifetime(NotificationEntry entry, NotificationLifetimeExtender extender) { |
| 770 | NotificationLifetimeExtender activeExtender = mRetainedNotifications.get(entry); |
| 771 | if (activeExtender != null && activeExtender != extender) { |
| 772 | activeExtender.setShouldManageLifetime(entry, false); |
| 773 | } |
| 774 | mRetainedNotifications.put(entry, extender); |
| 775 | extender.setShouldManageLifetime(entry, true); |
| 776 | } |
| 777 | |
| 778 | private void cancelLifetimeExtension(NotificationEntry entry) { |
| 779 | NotificationLifetimeExtender activeExtender = mRetainedNotifications.remove(entry); |
| 780 | if (activeExtender != null) { |
| 781 | activeExtender.setShouldManageLifetime(entry, false); |
| 782 | } |
| 783 | } |
Ned Burns | c586467 | 2019-02-20 12:57:29 -0500 | [diff] [blame] | 784 | |
Evan Laird | 181de62 | 2019-10-24 09:53:02 -0400 | [diff] [blame] | 785 | /* |
| 786 | * ----- |
| 787 | * Annexed from NotificationData below: |
| 788 | * Some of these methods may be redundant but require some reworking to remove. For now |
| 789 | * we'll try to keep the behavior the same and can simplify these interfaces in another pass |
| 790 | */ |
| 791 | |
| 792 | /** Internalization of NotificationData#remove */ |
| 793 | private void removeVisibleNotification(String key) { |
| 794 | // no need to synchronize if we're on the main thread dawg |
| 795 | Assert.isMainThread(); |
| 796 | |
| 797 | NotificationEntry removed = mActiveNotifications.remove(key); |
| 798 | |
| 799 | if (removed == null) return; |
| 800 | mGroupManager.onEntryRemoved(removed); |
| 801 | } |
| 802 | |
| 803 | /** @return list of active notifications filtered for the current user */ |
| 804 | public List<NotificationEntry> getActiveNotificationsForCurrentUser() { |
| 805 | Assert.isMainThread(); |
| 806 | ArrayList<NotificationEntry> filtered = new ArrayList<>(); |
| 807 | |
| 808 | final int len = mActiveNotifications.size(); |
| 809 | for (int i = 0; i < len; i++) { |
| 810 | NotificationEntry entry = mActiveNotifications.valueAt(i); |
| 811 | final StatusBarNotification sbn = entry.getSbn(); |
| 812 | if (!mKeyguardEnvironment.isNotificationForCurrentProfiles(sbn)) { |
| 813 | continue; |
| 814 | } |
| 815 | filtered.add(entry); |
| 816 | } |
| 817 | |
| 818 | return filtered; |
| 819 | } |
| 820 | |
| 821 | //TODO: Get rid of this in favor of NotificationUpdateHandler#updateNotificationRanking |
| 822 | /** |
| 823 | * @param rankingMap the {@link RankingMap} to apply to the current notification list |
Ned Burns | afe77bc | 2020-01-30 20:45:07 -0500 | [diff] [blame] | 824 | * @param reason the reason for calling this method, which will be logged |
Evan Laird | 181de62 | 2019-10-24 09:53:02 -0400 | [diff] [blame] | 825 | */ |
| 826 | public void updateRanking(RankingMap rankingMap, String reason) { |
| 827 | updateRankingAndSort(rankingMap, reason); |
Ned Burns | c411107 | 2020-04-03 01:46:55 -0400 | [diff] [blame] | 828 | for (NotifCollectionListener listener : mNotifCollectionListeners) { |
| 829 | listener.onRankingApplied(); |
| 830 | } |
Evan Laird | 181de62 | 2019-10-24 09:53:02 -0400 | [diff] [blame] | 831 | } |
| 832 | |
| 833 | /** Resorts / filters the current notification set with the current RankingMap */ |
| 834 | public void reapplyFilterAndSort(String reason) { |
| 835 | updateRankingAndSort(mRankingManager.getRankingMap(), reason); |
| 836 | } |
| 837 | |
| 838 | /** Calls to NotificationRankingManager and updates mSortedAndFiltered */ |
| 839 | private void updateRankingAndSort(@NonNull RankingMap rankingMap, String reason) { |
| 840 | mSortedAndFiltered.clear(); |
| 841 | mSortedAndFiltered.addAll(mRankingManager.updateRanking( |
| 842 | rankingMap, mActiveNotifications.values(), reason)); |
| 843 | } |
| 844 | |
| 845 | /** dump the current active notification list. Called from StatusBar */ |
| 846 | public void dump(PrintWriter pw, String indent) { |
| 847 | pw.println("NotificationEntryManager"); |
| 848 | int filteredLen = mSortedAndFiltered.size(); |
| 849 | pw.print(indent); |
| 850 | pw.println("active notifications: " + filteredLen); |
| 851 | int active; |
| 852 | for (active = 0; active < filteredLen; active++) { |
| 853 | NotificationEntry e = mSortedAndFiltered.get(active); |
| 854 | dumpEntry(pw, indent, active, e); |
| 855 | } |
| 856 | synchronized (mActiveNotifications) { |
| 857 | int totalLen = mActiveNotifications.size(); |
| 858 | pw.print(indent); |
| 859 | pw.println("inactive notifications: " + (totalLen - active)); |
| 860 | int inactiveCount = 0; |
| 861 | for (int i = 0; i < totalLen; i++) { |
| 862 | NotificationEntry entry = mActiveNotifications.valueAt(i); |
| 863 | if (!mSortedAndFiltered.contains(entry)) { |
| 864 | dumpEntry(pw, indent, inactiveCount, entry); |
| 865 | inactiveCount++; |
| 866 | } |
| 867 | } |
| 868 | } |
| 869 | } |
| 870 | |
| 871 | private void dumpEntry(PrintWriter pw, String indent, int i, NotificationEntry e) { |
| 872 | pw.print(indent); |
Ned Burns | d8b5154 | 2020-03-13 20:52:43 -0400 | [diff] [blame] | 873 | pw.println(" [" + i + "] key=" + e.getKey() + " icon=" + e.getIcons().getStatusBarIcon()); |
Evan Laird | 181de62 | 2019-10-24 09:53:02 -0400 | [diff] [blame] | 874 | StatusBarNotification n = e.getSbn(); |
| 875 | pw.print(indent); |
| 876 | pw.println(" pkg=" + n.getPackageName() + " id=" + n.getId() + " importance=" |
| 877 | + e.getRanking().getImportance()); |
| 878 | pw.print(indent); |
| 879 | pw.println(" notification=" + n.getNotification()); |
| 880 | } |
| 881 | |
| 882 | /** |
| 883 | * This is the answer to the question "what notifications should the user be seeing right now?" |
| 884 | * These are sorted and filtered, and directly inform the notification shade what to show |
| 885 | * |
| 886 | * @return A read-only list of the currently active notifications |
| 887 | */ |
| 888 | public List<NotificationEntry> getVisibleNotifications() { |
| 889 | return mReadOnlyNotifications; |
| 890 | } |
| 891 | |
Ned Burns | 88aeaf7 | 2020-03-13 20:45:19 -0400 | [diff] [blame] | 892 | /** |
| 893 | * Returns a collections containing ALL notifications we know about, including ones that are |
| 894 | * hidden or for other users. See {@link CommonNotifCollection#getAllNotifs()}. |
| 895 | */ |
| 896 | @Override |
| 897 | public Collection<NotificationEntry> getAllNotifs() { |
| 898 | return mReadOnlyAllNotifications; |
| 899 | } |
| 900 | |
Evan Laird | 181de62 | 2019-10-24 09:53:02 -0400 | [diff] [blame] | 901 | /** @return A count of the active notifications */ |
| 902 | public int getActiveNotificationsCount() { |
| 903 | return mReadOnlyNotifications.size(); |
| 904 | } |
| 905 | |
| 906 | /** |
| 907 | * @return {@code true} if there is at least one notification that should be visible right now |
| 908 | */ |
| 909 | public boolean hasActiveNotifications() { |
| 910 | return mReadOnlyNotifications.size() != 0; |
| 911 | } |
| 912 | |
Kevin Han | f400aee | 2020-01-30 13:10:29 -0800 | [diff] [blame] | 913 | @Override |
| 914 | public void addCollectionListener(NotifCollectionListener listener) { |
| 915 | mNotifCollectionListeners.add(listener); |
| 916 | } |
| 917 | |
Evan Laird | 181de62 | 2019-10-24 09:53:02 -0400 | [diff] [blame] | 918 | /* |
| 919 | * End annexation |
| 920 | * ----- |
| 921 | */ |
| 922 | |
| 923 | |
| 924 | /** |
| 925 | * Provides access to keyguard state and user settings dependent data. |
| 926 | */ |
| 927 | public interface KeyguardEnvironment { |
| 928 | /** true if the device is provisioned (should always be true in practice) */ |
| 929 | boolean isDeviceProvisioned(); |
| 930 | /** true if the notification is for the current profiles */ |
| 931 | boolean isNotificationForCurrentProfiles(StatusBarNotification sbn); |
| 932 | } |
Eliot Courtney | a6d8cf2 | 2017-10-20 13:26:58 +0900 | [diff] [blame] | 933 | } |