Loading packages/SystemUI/src/com/android/systemui/statusbar/HeadsUpStatusBarView.java +17 −6 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ import com.android.keyguard.AlphaOptimizedLinearLayout; import com.android.systemui.R; import com.android.systemui.plugins.DarkIconDispatcher; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.NotificationEntry.OnSensitivityChangedListener; import java.util.List; Loading Loading @@ -159,20 +160,30 @@ public class HeadsUpStatusBarView extends AlphaOptimizedLinearLayout { } public void setEntry(NotificationEntry entry) { if (entry != null) { if (mShowingEntry != null) { mShowingEntry.removeOnSensitivityChangedListener(mOnSensitivityChangedListener); } mShowingEntry = entry; if (mShowingEntry != null) { CharSequence text = entry.headsUpStatusBarText; if (entry.isSensitive()) { text = entry.headsUpStatusBarTextPublic; } mTextView.setText(text); mShowingEntry.setOnSensitiveChangedListener(() -> setEntry(entry)); } else if (mShowingEntry != null){ mShowingEntry.setOnSensitiveChangedListener(null); mShowingEntry = null; mShowingEntry.addOnSensitivityChangedListener(mOnSensitivityChangedListener); } } private final OnSensitivityChangedListener mOnSensitivityChangedListener = entry -> { if (entry != mShowingEntry) { throw new IllegalStateException("Got a sensitivity change for " + entry + " but mShowingEntry is " + mShowingEntry); } // Update the text setEntry(entry); }; @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); Loading packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java +4 −4 Original line number Diff line number Diff line Loading @@ -70,6 +70,7 @@ import java.io.FileDescriptor; import java.io.PrintWriter; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Set; Loading Loading @@ -262,11 +263,11 @@ public class NotificationMediaManager implements Dumpable { synchronized (mEntryManager) { NotificationEntry entry = mEntryManager .getActiveNotificationUnfiltered(mMediaNotificationKey); if (entry == null || entry.expandedIcon == null) { if (entry == null || entry.getIcons().getShelfIcon() == null) { return null; } return entry.expandedIcon.getSourceIcon(); return entry.getIcons().getShelfIcon().getSourceIcon(); } } Loading @@ -284,8 +285,7 @@ public class NotificationMediaManager implements Dumpable { boolean metaDataChanged = false; synchronized (mEntryManager) { Set<NotificationEntry> allNotifications = mEntryManager.getPendingAndActiveNotifications(); Collection<NotificationEntry> allNotifications = mEntryManager.getAllNotifs(); // Promote the media notification with a controller in 'playing' state, if any. NotificationEntry mediaNotification = null; Loading packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java +3 −3 Original line number Diff line number Diff line Loading @@ -329,7 +329,7 @@ public class NotificationShelf extends ActivatableNotificationView implements expandableRow.setAboveShelf(false); } if (notGoneIndex == 0) { StatusBarIconView icon = expandableRow.getEntry().expandedIcon; StatusBarIconView icon = expandableRow.getEntry().getIcons().getShelfIcon(); NotificationIconContainer.IconState iconState = getIconState(icon); // The icon state might be null in rare cases where the notification is actually // added to the layout, but not to the shelf. An example are replied messages, Loading Loading @@ -432,7 +432,7 @@ public class NotificationShelf extends ActivatableNotificationView implements // if the shelf is clipped, lets make sure we also clip the icon maxTop = Math.max(maxTop, getTranslationY() + getClipTopAmount()); } StatusBarIconView icon = row.getEntry().expandedIcon; StatusBarIconView icon = row.getEntry().getIcons().getShelfIcon(); float shelfIconPosition = getTranslationY() + icon.getTop() + icon.getTranslationY(); if (shelfIconPosition < maxTop && !mAmbientState.isFullyHidden()) { int top = (int) (maxTop - shelfIconPosition); Loading @@ -444,7 +444,7 @@ public class NotificationShelf extends ActivatableNotificationView implements } private void updateContinuousClipping(final ExpandableNotificationRow row) { StatusBarIconView icon = row.getEntry().expandedIcon; StatusBarIconView icon = row.getEntry().getIcons().getShelfIcon(); boolean needsContinuousClipping = ViewState.isAnimatingY(icon) && !mAmbientState.isDozing(); boolean isContinuousClipping = icon.getTag(TAG_CONTINUOUS_CLIPPING) != null; if (needsContinuousClipping && !isContinuousClipping) { Loading packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java +19 −11 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ import android.service.notification.NotificationListenerService.Ranking; import android.service.notification.NotificationListenerService.RankingMap; import android.service.notification.StatusBarNotification; import android.util.ArrayMap; import android.util.ArraySet; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; Loading Loading @@ -56,9 +57,9 @@ import com.android.systemui.util.leak.LeakDetector; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; Loading Loading @@ -105,6 +106,10 @@ public class NotificationEntryManager implements */ public static final int UNDEFINED_DISMISS_REASON = 0; private final Set<NotificationEntry> mAllNotifications = new ArraySet<>(); private final Set<NotificationEntry> mReadOnlyAllNotifications = Collections.unmodifiableSet(mAllNotifications); /** Pending notifications are ones awaiting inflation */ @VisibleForTesting protected final HashMap<String, NotificationEntry> mPendingNotifications = new HashMap<>(); Loading Loading @@ -468,6 +473,8 @@ public class NotificationEntryManager implements entry.removeRow(); } mAllNotifications.remove(entry); // Let's remove the children if this was a summary handleGroupSummaryRemoved(key); removeVisibleNotification(key); Loading Loading @@ -548,6 +555,7 @@ public class NotificationEntryManager implements notification, ranking, mFgsFeatureController.isForegroundServiceDismissalEnabled()); mAllNotifications.add(entry); mLeakDetector.trackInstance(entry); Loading Loading @@ -708,15 +716,6 @@ public class NotificationEntryManager implements return mPendingNotifications.values(); } /** * @return all notifications we're currently aware of (both pending and active notifications) */ public Set<NotificationEntry> getPendingAndActiveNotifications() { Set<NotificationEntry> allNotifs = new HashSet<>(mPendingNotifications.values()); allNotifs.addAll(mSortedAndFiltered); return allNotifs; } /** * Use this method to retrieve a notification entry that has been prepared for presentation. * Note that the notification may be filtered out and never shown to the user. Loading Loading @@ -842,7 +841,7 @@ public class NotificationEntryManager implements private void dumpEntry(PrintWriter pw, String indent, int i, NotificationEntry e) { pw.print(indent); pw.println(" [" + i + "] key=" + e.getKey() + " icon=" + e.icon); pw.println(" [" + i + "] key=" + e.getKey() + " icon=" + e.getIcons().getStatusBarIcon()); StatusBarNotification n = e.getSbn(); pw.print(indent); pw.println(" pkg=" + n.getPackageName() + " id=" + n.getId() + " importance=" Loading @@ -861,6 +860,15 @@ public class NotificationEntryManager implements return mReadOnlyNotifications; } /** * Returns a collections containing ALL notifications we know about, including ones that are * hidden or for other users. See {@link CommonNotifCollection#getAllNotifs()}. */ @Override public Collection<NotificationEntry> getAllNotifs() { return mReadOnlyAllNotifications; } /** @return A count of the active notifications */ public int getActiveNotificationsCount() { return mReadOnlyNotifications.size(); Loading packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java +49 −83 Original line number Diff line number Diff line Loading @@ -64,24 +64,34 @@ import com.android.systemui.statusbar.FeatureFlags; import com.android.systemui.statusbar.notification.collection.coalescer.CoalescedEvent; import com.android.systemui.statusbar.notification.collection.coalescer.GroupCoalescer; import com.android.systemui.statusbar.notification.collection.coalescer.GroupCoalescer.BatchableNotificationHandler; import com.android.systemui.statusbar.notification.collection.notifcollection.CleanUpEntryEvent; import com.android.systemui.statusbar.notification.collection.notifcollection.CollectionReadyForBuildListener; import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats; import com.android.systemui.statusbar.notification.collection.notifcollection.EntryAddedEvent; import com.android.systemui.statusbar.notification.collection.notifcollection.EntryRemovedEvent; import com.android.systemui.statusbar.notification.collection.notifcollection.EntryUpdatedEvent; import com.android.systemui.statusbar.notification.collection.notifcollection.InitEntryEvent; import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener; import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionLogger; import com.android.systemui.statusbar.notification.collection.notifcollection.NotifDismissInterceptor; import com.android.systemui.statusbar.notification.collection.notifcollection.NotifEvent; import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender; import com.android.systemui.statusbar.notification.collection.notifcollection.RankingAppliedEvent; import com.android.systemui.statusbar.notification.collection.notifcollection.RankingUpdatedEvent; import com.android.systemui.util.Assert; import java.io.FileDescriptor; import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Queue; import javax.inject.Inject; import javax.inject.Singleton; Loading Loading @@ -124,6 +134,8 @@ public class NotifCollection implements Dumpable { private final List<NotifLifetimeExtender> mLifetimeExtenders = new ArrayList<>(); private final List<NotifDismissInterceptor> mDismissInterceptors = new ArrayList<>(); private Queue<NotifEvent> mEventQueue = new ArrayDeque<>(); private boolean mAttached = false; private boolean mAmDispatchingToOtherCode; Loading Loading @@ -160,8 +172,8 @@ public class NotifCollection implements Dumpable { mBuildListener = buildListener; } /** @see NotifPipeline#getActiveNotifs() */ Collection<NotificationEntry> getActiveNotifs() { /** @see NotifPipeline#getAllNotifs() */ Collection<NotificationEntry> getAllNotifs() { Assert.isMainThread(); return mReadOnlyNotificationSet; } Loading Loading @@ -242,7 +254,7 @@ public class NotifCollection implements Dumpable { } locallyDismissNotifications(entriesToLocallyDismiss); rebuildList(); dispatchEventsAndRebuildList(); } /** Loading @@ -251,8 +263,7 @@ public class NotifCollection implements Dumpable { public void dismissNotification( NotificationEntry entry, @NonNull DismissedByUserStats stats) { dismissNotifications(List.of( new Pair<NotificationEntry, DismissedByUserStats>(entry, stats))); dismissNotifications(List.of(new Pair<>(entry, stats))); } /** Loading @@ -268,7 +279,7 @@ public class NotifCollection implements Dumpable { // system process is dead if we're here. } final List<NotificationEntry> entries = new ArrayList(getActiveNotifs()); final List<NotificationEntry> entries = new ArrayList<>(getAllNotifs()); for (int i = entries.size() - 1; i >= 0; i--) { NotificationEntry entry = entries.get(i); if (!shouldDismissOnClearAll(entry, userId)) { Loading @@ -283,7 +294,7 @@ public class NotifCollection implements Dumpable { } locallyDismissNotifications(entries); rebuildList(); dispatchEventsAndRebuildList(); } /** Loading Loading @@ -326,8 +337,9 @@ public class NotifCollection implements Dumpable { private void onNotificationPosted(StatusBarNotification sbn, RankingMap rankingMap) { Assert.isMainThread(); postNotification(sbn, requireRanking(rankingMap, sbn.getKey()), rankingMap); rebuildList(); postNotification(sbn, requireRanking(rankingMap, sbn.getKey())); applyRanking(rankingMap); dispatchEventsAndRebuildList(); } private void onNotificationGroupPosted(List<CoalescedEvent> batch) { Loading @@ -336,9 +348,9 @@ public class NotifCollection implements Dumpable { mLogger.logNotifGroupPosted(batch.get(0).getSbn().getGroupKey(), batch.size()); for (CoalescedEvent event : batch) { postNotification(event.getSbn(), event.getRanking(), null); postNotification(event.getSbn(), event.getRanking()); } rebuildList(); dispatchEventsAndRebuildList(); } private void onNotificationRemoved( Loading @@ -354,55 +366,49 @@ public class NotifCollection implements Dumpable { throw new IllegalStateException("No notification to remove with key " + sbn.getKey()); } entry.mCancellationReason = reason; applyRanking(rankingMap); tryRemoveNotification(entry); rebuildList(); applyRanking(rankingMap); dispatchEventsAndRebuildList(); } private void onNotificationRankingUpdate(RankingMap rankingMap) { Assert.isMainThread(); mEventQueue.add(new RankingUpdatedEvent(rankingMap)); applyRanking(rankingMap); dispatchNotificationRankingUpdate(rankingMap); rebuildList(); dispatchEventsAndRebuildList(); } private void postNotification( StatusBarNotification sbn, Ranking ranking, @Nullable RankingMap rankingMap) { Ranking ranking) { NotificationEntry entry = mNotificationSet.get(sbn.getKey()); if (entry == null) { // A new notification! mLogger.logNotifPosted(sbn.getKey()); entry = new NotificationEntry(sbn, ranking); mNotificationSet.put(sbn.getKey(), entry); dispatchOnEntryInit(entry); if (rankingMap != null) { applyRanking(rankingMap); } dispatchOnEntryAdded(entry); mLogger.logNotifPosted(sbn.getKey()); mEventQueue.add(new InitEntryEvent(entry)); mEventQueue.add(new EntryAddedEvent(entry)); } else { // Update to an existing entry mLogger.logNotifUpdated(sbn.getKey()); // Notification is updated so it is essentially re-added and thus alive again, so we // can reset its state. // TODO: If a coalesced event ever gets here, it's possible to lose track of children, // since their rankings might have been updated earlier (and thus we may no longer // think a child is associated with this locally-dismissed entry). cancelLocalDismissal(entry); cancelLifetimeExtension(entry); cancelDismissInterception(entry); entry.mCancellationReason = REASON_NOT_CANCELED; entry.setSbn(sbn); if (rankingMap != null) { applyRanking(rankingMap); } dispatchOnEntryUpdated(entry); mLogger.logNotifUpdated(sbn.getKey()); mEventQueue.add(new EntryUpdatedEvent(entry)); } } Loading Loading @@ -432,8 +438,8 @@ public class NotifCollection implements Dumpable { if (!isLifetimeExtended(entry)) { mNotificationSet.remove(entry.getKey()); cancelDismissInterception(entry); dispatchOnEntryRemoved(entry, entry.mCancellationReason); dispatchOnEntryCleanUp(entry); mEventQueue.add(new EntryRemovedEvent(entry, entry.mCancellationReason)); mEventQueue.add(new CleanUpEntryEvent(entry)); return true; } else { return false; Loading Loading @@ -466,9 +472,16 @@ public class NotifCollection implements Dumpable { } } } mEventQueue.add(new RankingAppliedEvent()); } private void dispatchEventsAndRebuildList() { mAmDispatchingToOtherCode = true; while (!mEventQueue.isEmpty()) { mEventQueue.remove().dispatchTo(mNotifCollectionListeners); } mAmDispatchingToOtherCode = false; private void rebuildList() { if (mBuildListener != null) { mBuildListener.onBuildList(mReadOnlyNotificationSet); } Loading @@ -491,7 +504,7 @@ public class NotifCollection implements Dumpable { if (!isLifetimeExtended(entry)) { if (tryRemoveNotification(entry)) { rebuildList(); dispatchEventsAndRebuildList(); } } } Loading Loading @@ -660,57 +673,9 @@ public class NotifCollection implements Dumpable { || entry.getSbn().getUser().getIdentifier() == userId; } private void dispatchOnEntryInit(NotificationEntry entry) { mAmDispatchingToOtherCode = true; for (NotifCollectionListener listener : mNotifCollectionListeners) { listener.onEntryInit(entry); } mAmDispatchingToOtherCode = false; } private void dispatchOnEntryAdded(NotificationEntry entry) { mAmDispatchingToOtherCode = true; for (NotifCollectionListener listener : mNotifCollectionListeners) { listener.onEntryAdded(entry); } mAmDispatchingToOtherCode = false; } private void dispatchOnEntryUpdated(NotificationEntry entry) { mAmDispatchingToOtherCode = true; for (NotifCollectionListener listener : mNotifCollectionListeners) { listener.onEntryUpdated(entry); } mAmDispatchingToOtherCode = false; } private void dispatchNotificationRankingUpdate(RankingMap map) { mAmDispatchingToOtherCode = true; for (NotifCollectionListener listener : mNotifCollectionListeners) { listener.onRankingUpdate(map); } mAmDispatchingToOtherCode = false; } private void dispatchOnEntryRemoved(NotificationEntry entry, @CancellationReason int reason) { mAmDispatchingToOtherCode = true; for (NotifCollectionListener listener : mNotifCollectionListeners) { listener.onEntryRemoved(entry, reason); } mAmDispatchingToOtherCode = false; } private void dispatchOnEntryCleanUp(NotificationEntry entry) { mAmDispatchingToOtherCode = true; for (NotifCollectionListener listener : mNotifCollectionListeners) { listener.onEntryCleanUp(entry); } mAmDispatchingToOtherCode = false; } @Override public void dump(@NonNull FileDescriptor fd, PrintWriter pw, @NonNull String[] args) { final List<NotificationEntry> entries = new ArrayList<>(getActiveNotifs()); final List<NotificationEntry> entries = new ArrayList<>(getAllNotifs()); pw.println("\t" + TAG + " unsorted/unfiltered notifications:"); if (entries.size() == 0) { Loading Loading @@ -754,6 +719,7 @@ public class NotifCollection implements Dumpable { private static final String TAG = "NotifCollection"; @IntDef(prefix = { "REASON_" }, value = { REASON_NOT_CANCELED, REASON_UNKNOWN, REASON_CLICK, REASON_CANCEL_ALL, Loading Loading
packages/SystemUI/src/com/android/systemui/statusbar/HeadsUpStatusBarView.java +17 −6 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ import com.android.keyguard.AlphaOptimizedLinearLayout; import com.android.systemui.R; import com.android.systemui.plugins.DarkIconDispatcher; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.NotificationEntry.OnSensitivityChangedListener; import java.util.List; Loading Loading @@ -159,20 +160,30 @@ public class HeadsUpStatusBarView extends AlphaOptimizedLinearLayout { } public void setEntry(NotificationEntry entry) { if (entry != null) { if (mShowingEntry != null) { mShowingEntry.removeOnSensitivityChangedListener(mOnSensitivityChangedListener); } mShowingEntry = entry; if (mShowingEntry != null) { CharSequence text = entry.headsUpStatusBarText; if (entry.isSensitive()) { text = entry.headsUpStatusBarTextPublic; } mTextView.setText(text); mShowingEntry.setOnSensitiveChangedListener(() -> setEntry(entry)); } else if (mShowingEntry != null){ mShowingEntry.setOnSensitiveChangedListener(null); mShowingEntry = null; mShowingEntry.addOnSensitivityChangedListener(mOnSensitivityChangedListener); } } private final OnSensitivityChangedListener mOnSensitivityChangedListener = entry -> { if (entry != mShowingEntry) { throw new IllegalStateException("Got a sensitivity change for " + entry + " but mShowingEntry is " + mShowingEntry); } // Update the text setEntry(entry); }; @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); Loading
packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java +4 −4 Original line number Diff line number Diff line Loading @@ -70,6 +70,7 @@ import java.io.FileDescriptor; import java.io.PrintWriter; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Set; Loading Loading @@ -262,11 +263,11 @@ public class NotificationMediaManager implements Dumpable { synchronized (mEntryManager) { NotificationEntry entry = mEntryManager .getActiveNotificationUnfiltered(mMediaNotificationKey); if (entry == null || entry.expandedIcon == null) { if (entry == null || entry.getIcons().getShelfIcon() == null) { return null; } return entry.expandedIcon.getSourceIcon(); return entry.getIcons().getShelfIcon().getSourceIcon(); } } Loading @@ -284,8 +285,7 @@ public class NotificationMediaManager implements Dumpable { boolean metaDataChanged = false; synchronized (mEntryManager) { Set<NotificationEntry> allNotifications = mEntryManager.getPendingAndActiveNotifications(); Collection<NotificationEntry> allNotifications = mEntryManager.getAllNotifs(); // Promote the media notification with a controller in 'playing' state, if any. NotificationEntry mediaNotification = null; Loading
packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java +3 −3 Original line number Diff line number Diff line Loading @@ -329,7 +329,7 @@ public class NotificationShelf extends ActivatableNotificationView implements expandableRow.setAboveShelf(false); } if (notGoneIndex == 0) { StatusBarIconView icon = expandableRow.getEntry().expandedIcon; StatusBarIconView icon = expandableRow.getEntry().getIcons().getShelfIcon(); NotificationIconContainer.IconState iconState = getIconState(icon); // The icon state might be null in rare cases where the notification is actually // added to the layout, but not to the shelf. An example are replied messages, Loading Loading @@ -432,7 +432,7 @@ public class NotificationShelf extends ActivatableNotificationView implements // if the shelf is clipped, lets make sure we also clip the icon maxTop = Math.max(maxTop, getTranslationY() + getClipTopAmount()); } StatusBarIconView icon = row.getEntry().expandedIcon; StatusBarIconView icon = row.getEntry().getIcons().getShelfIcon(); float shelfIconPosition = getTranslationY() + icon.getTop() + icon.getTranslationY(); if (shelfIconPosition < maxTop && !mAmbientState.isFullyHidden()) { int top = (int) (maxTop - shelfIconPosition); Loading @@ -444,7 +444,7 @@ public class NotificationShelf extends ActivatableNotificationView implements } private void updateContinuousClipping(final ExpandableNotificationRow row) { StatusBarIconView icon = row.getEntry().expandedIcon; StatusBarIconView icon = row.getEntry().getIcons().getShelfIcon(); boolean needsContinuousClipping = ViewState.isAnimatingY(icon) && !mAmbientState.isDozing(); boolean isContinuousClipping = icon.getTag(TAG_CONTINUOUS_CLIPPING) != null; if (needsContinuousClipping && !isContinuousClipping) { Loading
packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java +19 −11 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ import android.service.notification.NotificationListenerService.Ranking; import android.service.notification.NotificationListenerService.RankingMap; import android.service.notification.StatusBarNotification; import android.util.ArrayMap; import android.util.ArraySet; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; Loading Loading @@ -56,9 +57,9 @@ import com.android.systemui.util.leak.LeakDetector; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; Loading Loading @@ -105,6 +106,10 @@ public class NotificationEntryManager implements */ public static final int UNDEFINED_DISMISS_REASON = 0; private final Set<NotificationEntry> mAllNotifications = new ArraySet<>(); private final Set<NotificationEntry> mReadOnlyAllNotifications = Collections.unmodifiableSet(mAllNotifications); /** Pending notifications are ones awaiting inflation */ @VisibleForTesting protected final HashMap<String, NotificationEntry> mPendingNotifications = new HashMap<>(); Loading Loading @@ -468,6 +473,8 @@ public class NotificationEntryManager implements entry.removeRow(); } mAllNotifications.remove(entry); // Let's remove the children if this was a summary handleGroupSummaryRemoved(key); removeVisibleNotification(key); Loading Loading @@ -548,6 +555,7 @@ public class NotificationEntryManager implements notification, ranking, mFgsFeatureController.isForegroundServiceDismissalEnabled()); mAllNotifications.add(entry); mLeakDetector.trackInstance(entry); Loading Loading @@ -708,15 +716,6 @@ public class NotificationEntryManager implements return mPendingNotifications.values(); } /** * @return all notifications we're currently aware of (both pending and active notifications) */ public Set<NotificationEntry> getPendingAndActiveNotifications() { Set<NotificationEntry> allNotifs = new HashSet<>(mPendingNotifications.values()); allNotifs.addAll(mSortedAndFiltered); return allNotifs; } /** * Use this method to retrieve a notification entry that has been prepared for presentation. * Note that the notification may be filtered out and never shown to the user. Loading Loading @@ -842,7 +841,7 @@ public class NotificationEntryManager implements private void dumpEntry(PrintWriter pw, String indent, int i, NotificationEntry e) { pw.print(indent); pw.println(" [" + i + "] key=" + e.getKey() + " icon=" + e.icon); pw.println(" [" + i + "] key=" + e.getKey() + " icon=" + e.getIcons().getStatusBarIcon()); StatusBarNotification n = e.getSbn(); pw.print(indent); pw.println(" pkg=" + n.getPackageName() + " id=" + n.getId() + " importance=" Loading @@ -861,6 +860,15 @@ public class NotificationEntryManager implements return mReadOnlyNotifications; } /** * Returns a collections containing ALL notifications we know about, including ones that are * hidden or for other users. See {@link CommonNotifCollection#getAllNotifs()}. */ @Override public Collection<NotificationEntry> getAllNotifs() { return mReadOnlyAllNotifications; } /** @return A count of the active notifications */ public int getActiveNotificationsCount() { return mReadOnlyNotifications.size(); Loading
packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java +49 −83 Original line number Diff line number Diff line Loading @@ -64,24 +64,34 @@ import com.android.systemui.statusbar.FeatureFlags; import com.android.systemui.statusbar.notification.collection.coalescer.CoalescedEvent; import com.android.systemui.statusbar.notification.collection.coalescer.GroupCoalescer; import com.android.systemui.statusbar.notification.collection.coalescer.GroupCoalescer.BatchableNotificationHandler; import com.android.systemui.statusbar.notification.collection.notifcollection.CleanUpEntryEvent; import com.android.systemui.statusbar.notification.collection.notifcollection.CollectionReadyForBuildListener; import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats; import com.android.systemui.statusbar.notification.collection.notifcollection.EntryAddedEvent; import com.android.systemui.statusbar.notification.collection.notifcollection.EntryRemovedEvent; import com.android.systemui.statusbar.notification.collection.notifcollection.EntryUpdatedEvent; import com.android.systemui.statusbar.notification.collection.notifcollection.InitEntryEvent; import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener; import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionLogger; import com.android.systemui.statusbar.notification.collection.notifcollection.NotifDismissInterceptor; import com.android.systemui.statusbar.notification.collection.notifcollection.NotifEvent; import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender; import com.android.systemui.statusbar.notification.collection.notifcollection.RankingAppliedEvent; import com.android.systemui.statusbar.notification.collection.notifcollection.RankingUpdatedEvent; import com.android.systemui.util.Assert; import java.io.FileDescriptor; import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Queue; import javax.inject.Inject; import javax.inject.Singleton; Loading Loading @@ -124,6 +134,8 @@ public class NotifCollection implements Dumpable { private final List<NotifLifetimeExtender> mLifetimeExtenders = new ArrayList<>(); private final List<NotifDismissInterceptor> mDismissInterceptors = new ArrayList<>(); private Queue<NotifEvent> mEventQueue = new ArrayDeque<>(); private boolean mAttached = false; private boolean mAmDispatchingToOtherCode; Loading Loading @@ -160,8 +172,8 @@ public class NotifCollection implements Dumpable { mBuildListener = buildListener; } /** @see NotifPipeline#getActiveNotifs() */ Collection<NotificationEntry> getActiveNotifs() { /** @see NotifPipeline#getAllNotifs() */ Collection<NotificationEntry> getAllNotifs() { Assert.isMainThread(); return mReadOnlyNotificationSet; } Loading Loading @@ -242,7 +254,7 @@ public class NotifCollection implements Dumpable { } locallyDismissNotifications(entriesToLocallyDismiss); rebuildList(); dispatchEventsAndRebuildList(); } /** Loading @@ -251,8 +263,7 @@ public class NotifCollection implements Dumpable { public void dismissNotification( NotificationEntry entry, @NonNull DismissedByUserStats stats) { dismissNotifications(List.of( new Pair<NotificationEntry, DismissedByUserStats>(entry, stats))); dismissNotifications(List.of(new Pair<>(entry, stats))); } /** Loading @@ -268,7 +279,7 @@ public class NotifCollection implements Dumpable { // system process is dead if we're here. } final List<NotificationEntry> entries = new ArrayList(getActiveNotifs()); final List<NotificationEntry> entries = new ArrayList<>(getAllNotifs()); for (int i = entries.size() - 1; i >= 0; i--) { NotificationEntry entry = entries.get(i); if (!shouldDismissOnClearAll(entry, userId)) { Loading @@ -283,7 +294,7 @@ public class NotifCollection implements Dumpable { } locallyDismissNotifications(entries); rebuildList(); dispatchEventsAndRebuildList(); } /** Loading Loading @@ -326,8 +337,9 @@ public class NotifCollection implements Dumpable { private void onNotificationPosted(StatusBarNotification sbn, RankingMap rankingMap) { Assert.isMainThread(); postNotification(sbn, requireRanking(rankingMap, sbn.getKey()), rankingMap); rebuildList(); postNotification(sbn, requireRanking(rankingMap, sbn.getKey())); applyRanking(rankingMap); dispatchEventsAndRebuildList(); } private void onNotificationGroupPosted(List<CoalescedEvent> batch) { Loading @@ -336,9 +348,9 @@ public class NotifCollection implements Dumpable { mLogger.logNotifGroupPosted(batch.get(0).getSbn().getGroupKey(), batch.size()); for (CoalescedEvent event : batch) { postNotification(event.getSbn(), event.getRanking(), null); postNotification(event.getSbn(), event.getRanking()); } rebuildList(); dispatchEventsAndRebuildList(); } private void onNotificationRemoved( Loading @@ -354,55 +366,49 @@ public class NotifCollection implements Dumpable { throw new IllegalStateException("No notification to remove with key " + sbn.getKey()); } entry.mCancellationReason = reason; applyRanking(rankingMap); tryRemoveNotification(entry); rebuildList(); applyRanking(rankingMap); dispatchEventsAndRebuildList(); } private void onNotificationRankingUpdate(RankingMap rankingMap) { Assert.isMainThread(); mEventQueue.add(new RankingUpdatedEvent(rankingMap)); applyRanking(rankingMap); dispatchNotificationRankingUpdate(rankingMap); rebuildList(); dispatchEventsAndRebuildList(); } private void postNotification( StatusBarNotification sbn, Ranking ranking, @Nullable RankingMap rankingMap) { Ranking ranking) { NotificationEntry entry = mNotificationSet.get(sbn.getKey()); if (entry == null) { // A new notification! mLogger.logNotifPosted(sbn.getKey()); entry = new NotificationEntry(sbn, ranking); mNotificationSet.put(sbn.getKey(), entry); dispatchOnEntryInit(entry); if (rankingMap != null) { applyRanking(rankingMap); } dispatchOnEntryAdded(entry); mLogger.logNotifPosted(sbn.getKey()); mEventQueue.add(new InitEntryEvent(entry)); mEventQueue.add(new EntryAddedEvent(entry)); } else { // Update to an existing entry mLogger.logNotifUpdated(sbn.getKey()); // Notification is updated so it is essentially re-added and thus alive again, so we // can reset its state. // TODO: If a coalesced event ever gets here, it's possible to lose track of children, // since their rankings might have been updated earlier (and thus we may no longer // think a child is associated with this locally-dismissed entry). cancelLocalDismissal(entry); cancelLifetimeExtension(entry); cancelDismissInterception(entry); entry.mCancellationReason = REASON_NOT_CANCELED; entry.setSbn(sbn); if (rankingMap != null) { applyRanking(rankingMap); } dispatchOnEntryUpdated(entry); mLogger.logNotifUpdated(sbn.getKey()); mEventQueue.add(new EntryUpdatedEvent(entry)); } } Loading Loading @@ -432,8 +438,8 @@ public class NotifCollection implements Dumpable { if (!isLifetimeExtended(entry)) { mNotificationSet.remove(entry.getKey()); cancelDismissInterception(entry); dispatchOnEntryRemoved(entry, entry.mCancellationReason); dispatchOnEntryCleanUp(entry); mEventQueue.add(new EntryRemovedEvent(entry, entry.mCancellationReason)); mEventQueue.add(new CleanUpEntryEvent(entry)); return true; } else { return false; Loading Loading @@ -466,9 +472,16 @@ public class NotifCollection implements Dumpable { } } } mEventQueue.add(new RankingAppliedEvent()); } private void dispatchEventsAndRebuildList() { mAmDispatchingToOtherCode = true; while (!mEventQueue.isEmpty()) { mEventQueue.remove().dispatchTo(mNotifCollectionListeners); } mAmDispatchingToOtherCode = false; private void rebuildList() { if (mBuildListener != null) { mBuildListener.onBuildList(mReadOnlyNotificationSet); } Loading @@ -491,7 +504,7 @@ public class NotifCollection implements Dumpable { if (!isLifetimeExtended(entry)) { if (tryRemoveNotification(entry)) { rebuildList(); dispatchEventsAndRebuildList(); } } } Loading Loading @@ -660,57 +673,9 @@ public class NotifCollection implements Dumpable { || entry.getSbn().getUser().getIdentifier() == userId; } private void dispatchOnEntryInit(NotificationEntry entry) { mAmDispatchingToOtherCode = true; for (NotifCollectionListener listener : mNotifCollectionListeners) { listener.onEntryInit(entry); } mAmDispatchingToOtherCode = false; } private void dispatchOnEntryAdded(NotificationEntry entry) { mAmDispatchingToOtherCode = true; for (NotifCollectionListener listener : mNotifCollectionListeners) { listener.onEntryAdded(entry); } mAmDispatchingToOtherCode = false; } private void dispatchOnEntryUpdated(NotificationEntry entry) { mAmDispatchingToOtherCode = true; for (NotifCollectionListener listener : mNotifCollectionListeners) { listener.onEntryUpdated(entry); } mAmDispatchingToOtherCode = false; } private void dispatchNotificationRankingUpdate(RankingMap map) { mAmDispatchingToOtherCode = true; for (NotifCollectionListener listener : mNotifCollectionListeners) { listener.onRankingUpdate(map); } mAmDispatchingToOtherCode = false; } private void dispatchOnEntryRemoved(NotificationEntry entry, @CancellationReason int reason) { mAmDispatchingToOtherCode = true; for (NotifCollectionListener listener : mNotifCollectionListeners) { listener.onEntryRemoved(entry, reason); } mAmDispatchingToOtherCode = false; } private void dispatchOnEntryCleanUp(NotificationEntry entry) { mAmDispatchingToOtherCode = true; for (NotifCollectionListener listener : mNotifCollectionListeners) { listener.onEntryCleanUp(entry); } mAmDispatchingToOtherCode = false; } @Override public void dump(@NonNull FileDescriptor fd, PrintWriter pw, @NonNull String[] args) { final List<NotificationEntry> entries = new ArrayList<>(getActiveNotifs()); final List<NotificationEntry> entries = new ArrayList<>(getAllNotifs()); pw.println("\t" + TAG + " unsorted/unfiltered notifications:"); if (entries.size() == 0) { Loading Loading @@ -754,6 +719,7 @@ public class NotifCollection implements Dumpable { private static final String TAG = "NotifCollection"; @IntDef(prefix = { "REASON_" }, value = { REASON_NOT_CANCELED, REASON_UNKNOWN, REASON_CLICK, REASON_CANCEL_ALL, Loading