Loading packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifPipeline.java +12 −3 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.systemui.statusbar.notification.collection; import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeFinalizeFilterListener; import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeRenderListListener; import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeSortListener; import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeTransformGroupsListener; Loading Loading @@ -63,7 +64,7 @@ import javax.inject.Singleton; * 6. Top-level entries are assigned sections by NotifSections ({@link #setSections}) * 7. Top-level entries within the same section are sorted by NotifComparators * ({@link #setComparators}) * 8. Pre-render filters are fired on each notification ({@link #addPreRenderFilter}) * 8. Finalize filters are fired on each notification ({@link #addFinalizeFilter}) * 9. OnBeforeRenderListListeners are fired ({@link #addOnBeforeRenderListListener}) * 9. The list is handed off to the view layer to be rendered */ Loading Loading @@ -168,6 +169,14 @@ public class NotifPipeline implements CommonNotifCollection { mShadeListBuilder.setComparators(comparators); } /** * Called after notifs have been filtered once, grouped, and sorted but before the final * filtering. */ public void addOnBeforeFinalizeFilterListener(OnBeforeFinalizeFilterListener listener) { mShadeListBuilder.addOnBeforeFinalizeFilterListener(listener); } /** * Registers a filter with the pipeline to filter right before rendering the list (after * pre-group filtering, grouping, promoting and sorting occurs). Filters are Loading @@ -175,8 +184,8 @@ public class NotifPipeline implements CommonNotifCollection { * true, the notification is removed from the pipeline (and no other filters are called on that * notif). */ public void addPreRenderFilter(NotifFilter filter) { mShadeListBuilder.addPreRenderFilter(filter); public void addFinalizeFilter(NotifFilter filter) { mShadeListBuilder.addFinalizeFilter(filter); } /** Loading packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java +27 −10 Original line number Diff line number Diff line Loading @@ -18,11 +18,11 @@ package com.android.systemui.statusbar.notification.collection; import static com.android.systemui.statusbar.notification.collection.GroupEntry.ROOT_ENTRY; import static com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState.STATE_BUILD_STARTED; import static com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState.STATE_FINALIZE_FILTERING; import static com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState.STATE_FINALIZING; import static com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState.STATE_GROUPING; import static com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState.STATE_IDLE; import static com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState.STATE_PRE_GROUP_FILTERING; import static com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState.STATE_PRE_RENDER_FILTERING; import static com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState.STATE_RESETTING; import static com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState.STATE_SORTING; import static com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState.STATE_TRANSFORMING; Loading @@ -36,6 +36,7 @@ import androidx.annotation.NonNull; import com.android.systemui.Dumpable; import com.android.systemui.dump.DumpManager; import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeFinalizeFilterListener; import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeRenderListListener; import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeSortListener; import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeTransformGroupsListener; Loading Loading @@ -82,7 +83,7 @@ public class ShadeListBuilder implements Dumpable { private final List<NotifFilter> mNotifPreGroupFilters = new ArrayList<>(); private final List<NotifPromoter> mNotifPromoters = new ArrayList<>(); private final List<NotifFilter> mNotifPreRenderFilters = new ArrayList<>(); private final List<NotifFilter> mNotifFinalizeFilters = new ArrayList<>(); private final List<NotifComparator> mNotifComparators = new ArrayList<>(); private final List<NotifSection> mNotifSections = new ArrayList<>(); Loading @@ -90,6 +91,8 @@ public class ShadeListBuilder implements Dumpable { new ArrayList<>(); private final List<OnBeforeSortListener> mOnBeforeSortListeners = new ArrayList<>(); private final List<OnBeforeFinalizeFilterListener> mOnBeforeFinalizeFilterListeners = new ArrayList<>(); private final List<OnBeforeRenderListListener> mOnBeforeRenderListListeners = new ArrayList<>(); @Nullable private OnRenderListListener mOnRenderListListener; Loading Loading @@ -142,6 +145,13 @@ public class ShadeListBuilder implements Dumpable { mOnBeforeSortListeners.add(listener); } void addOnBeforeFinalizeFilterListener(OnBeforeFinalizeFilterListener listener) { Assert.isMainThread(); mPipelineState.requireState(STATE_IDLE); mOnBeforeFinalizeFilterListeners.add(listener); } void addOnBeforeRenderListListener(OnBeforeRenderListListener listener) { Assert.isMainThread(); Loading @@ -157,12 +167,12 @@ public class ShadeListBuilder implements Dumpable { filter.setInvalidationListener(this::onPreGroupFilterInvalidated); } void addPreRenderFilter(NotifFilter filter) { void addFinalizeFilter(NotifFilter filter) { Assert.isMainThread(); mPipelineState.requireState(STATE_IDLE); mNotifPreRenderFilters.add(filter); filter.setInvalidationListener(this::onPreRenderFilterInvalidated); mNotifFinalizeFilters.add(filter); filter.setInvalidationListener(this::onFinalizeFilterInvalidated); } void addPromoter(NotifPromoter promoter) { Loading Loading @@ -237,12 +247,12 @@ public class ShadeListBuilder implements Dumpable { rebuildListIfBefore(STATE_SORTING); } private void onPreRenderFilterInvalidated(NotifFilter filter) { private void onFinalizeFilterInvalidated(NotifFilter filter) { Assert.isMainThread(); mLogger.logPreRenderFilterInvalidated(filter.getName(), mPipelineState.getState()); mLogger.logFinalizeFilterInvalidated(filter.getName(), mPipelineState.getState()); rebuildListIfBefore(STATE_PRE_RENDER_FILTERING); rebuildListIfBefore(STATE_FINALIZE_FILTERING); } private void onNotifComparatorInvalidated(NotifComparator comparator) { Loading Loading @@ -298,8 +308,9 @@ public class ShadeListBuilder implements Dumpable { // Step 6: Filter out entries after pre-group filtering, grouping, promoting and sorting // Now filters can see grouping information to determine whether to filter or not. mPipelineState.incrementTo(STATE_PRE_RENDER_FILTERING); filterNotifs(mNotifList, mNewNotifList, mNotifPreRenderFilters); dispatchOnBeforeFinalizeFilter(mReadOnlyNotifList); mPipelineState.incrementTo(STATE_FINALIZE_FILTERING); filterNotifs(mNotifList, mNewNotifList, mNotifFinalizeFilters); applyNewNotifList(); pruneIncompleteGroups(mNotifList); Loading Loading @@ -772,6 +783,12 @@ public class ShadeListBuilder implements Dumpable { } } private void dispatchOnBeforeFinalizeFilter(List<ListEntry> entries) { for (int i = 0; i < mOnBeforeFinalizeFilterListeners.size(); i++) { mOnBeforeFinalizeFilterListeners.get(i).onBeforeFinalizeFilter(entries); } } private void dispatchOnBeforeRenderList(List<ListEntry> entries) { for (int i = 0; i < mOnBeforeRenderListListeners.size(); i++) { mOnBeforeRenderListListeners.get(i).onBeforeRenderList(entries); Loading packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/BubbleCoordinator.java +1 −1 Original line number Diff line number Diff line Loading @@ -77,7 +77,7 @@ public class BubbleCoordinator implements Coordinator { public void attach(NotifPipeline pipeline) { mNotifPipeline = pipeline; mNotifPipeline.addNotificationDismissInterceptor(mDismissInterceptor); mNotifPipeline.addPreRenderFilter(mNotifFilter); mNotifPipeline.addFinalizeFilter(mNotifFilter); mBubbleController.addNotifCallback(mNotifCallback); } Loading packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java +1 −1 Original line number Diff line number Diff line Loading @@ -87,7 +87,7 @@ public class KeyguardCoordinator implements Coordinator { @Override public void attach(NotifPipeline pipeline) { setupInvalidateNotifListCallbacks(); pipeline.addPreRenderFilter(mNotifFilter); pipeline.addFinalizeFilter(mNotifFilter); } private final NotifFilter mNotifFilter = new NotifFilter(TAG) { Loading packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java +100 −19 Original line number Diff line number Diff line Loading @@ -16,31 +16,39 @@ package com.android.systemui.statusbar.notification.collection.coordinator; import android.annotation.IntDef; import android.os.RemoteException; import android.service.notification.StatusBarNotification; import android.util.ArrayMap; import com.android.internal.statusbar.IStatusBarService; import com.android.systemui.statusbar.notification.collection.GroupEntry; import com.android.systemui.statusbar.notification.collection.ListEntry; import com.android.systemui.statusbar.notification.collection.NotifInflaterImpl; import com.android.systemui.statusbar.notification.collection.NotifPipeline; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.ShadeListBuilder; import com.android.systemui.statusbar.notification.collection.inflation.NotifInflater; import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeFinalizeFilterListener; import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter; import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener; import com.android.systemui.statusbar.notification.row.NotifInflationErrorManager; import java.util.ArrayList; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.List; import java.util.Map; import java.util.Objects; import javax.inject.Inject; import javax.inject.Singleton; /** * Kicks off notification inflation and view rebinding when a notification is added or updated. * Kicks off core notification inflation and view rebinding when a notification is added or updated. * Aborts inflation when a notification is removed. * * If a notification is not done inflating, this coordinator will filter the notification out * from the {@link ShadeListBuilder}. * If a notification was uninflated, this coordinator will filter the notification out from the * {@link ShadeListBuilder} until it is inflated. */ @Singleton public class PreparationCoordinator implements Coordinator { Loading @@ -49,7 +57,7 @@ public class PreparationCoordinator implements Coordinator { private final PreparationCoordinatorLogger mLogger; private final NotifInflater mNotifInflater; private final NotifInflationErrorManager mNotifErrorManager; private final List<NotificationEntry> mPendingNotifications = new ArrayList<>(); private final Map<NotificationEntry, Integer> mInflationStates = new ArrayMap<>(); private final IStatusBarService mStatusBarService; @Inject Loading @@ -69,27 +77,44 @@ public class PreparationCoordinator implements Coordinator { @Override public void attach(NotifPipeline pipeline) { pipeline.addCollectionListener(mNotifCollectionListener); pipeline.addPreRenderFilter(mNotifInflationErrorFilter); pipeline.addPreRenderFilter(mNotifInflatingFilter); // Inflate after grouping/sorting since that affects what views to inflate. pipeline.addOnBeforeFinalizeFilterListener(mOnBeforeFinalizeFilterListener); pipeline.addFinalizeFilter(mNotifInflationErrorFilter); pipeline.addFinalizeFilter(mNotifInflatingFilter); } private final NotifCollectionListener mNotifCollectionListener = new NotifCollectionListener() { @Override public void onEntryAdded(NotificationEntry entry) { inflateEntry(entry, "entryAdded"); public void onEntryInit(NotificationEntry entry) { mInflationStates.put(entry, STATE_UNINFLATED); } @Override public void onEntryUpdated(NotificationEntry entry) { rebind(entry, "entryUpdated"); @InflationState int state = getInflationState(entry); if (state == STATE_INFLATED) { mInflationStates.put(entry, STATE_INFLATED_INVALID); } else if (state == STATE_ERROR) { // Updated so maybe it won't error out now. mInflationStates.put(entry, STATE_UNINFLATED); } } @Override public void onEntryRemoved(NotificationEntry entry, int reason) { abortInflation(entry, "entryRemoved reason=" + reason); } @Override public void onEntryCleanUp(NotificationEntry entry) { mInflationStates.remove(entry); } }; private final OnBeforeFinalizeFilterListener mOnBeforeFinalizeFilterListener = entries -> inflateAllRequiredViews(entries); private final NotifFilter mNotifInflationErrorFilter = new NotifFilter( TAG + "InflationError") { /** Loading @@ -97,10 +122,7 @@ public class PreparationCoordinator implements Coordinator { */ @Override public boolean shouldFilterOut(NotificationEntry entry, long now) { if (mNotifErrorManager.hasInflationError(entry)) { return true; } return false; return getInflationState(entry) == STATE_ERROR; } }; Loading @@ -110,7 +132,8 @@ public class PreparationCoordinator implements Coordinator { */ @Override public boolean shouldFilterOut(NotificationEntry entry, long now) { return mPendingNotifications.contains(entry); @InflationState int state = getInflationState(entry); return (state != STATE_INFLATED) && (state != STATE_INFLATED_INVALID); } }; Loading @@ -119,7 +142,7 @@ public class PreparationCoordinator implements Coordinator { @Override public void onInflationFinished(NotificationEntry entry) { mLogger.logNotifInflated(entry.getKey()); mPendingNotifications.remove(entry); mInflationStates.put(entry, STATE_INFLATED); mNotifInflatingFilter.invalidateList(); } }; Loading @@ -128,7 +151,7 @@ public class PreparationCoordinator implements Coordinator { new NotifInflationErrorManager.NotifInflationErrorListener() { @Override public void onNotifInflationError(NotificationEntry entry, Exception e) { mPendingNotifications.remove(entry); mInflationStates.put(entry, STATE_ERROR); try { final StatusBarNotification sbn = entry.getSbn(); // report notification inflation errors back up Loading @@ -152,9 +175,41 @@ public class PreparationCoordinator implements Coordinator { } }; private void inflateAllRequiredViews(List<ListEntry> entries) { for (int i = 0, size = entries.size(); i < size; i++) { ListEntry entry = entries.get(i); if (entry instanceof GroupEntry) { GroupEntry groupEntry = (GroupEntry) entry; inflateNotifRequiredViews(groupEntry.getSummary()); List<NotificationEntry> children = groupEntry.getChildren(); for (int j = 0, groupSize = children.size(); j < groupSize; j++) { inflateNotifRequiredViews(children.get(j)); } } else { NotificationEntry notifEntry = (NotificationEntry) entry; inflateNotifRequiredViews(notifEntry); } } } private void inflateNotifRequiredViews(NotificationEntry entry) { @InflationState int state = mInflationStates.get(entry); switch (state) { case STATE_UNINFLATED: inflateEntry(entry, "entryAdded"); break; case STATE_INFLATED_INVALID: rebind(entry, "entryUpdated"); break; case STATE_INFLATED: case STATE_ERROR: default: // Nothing to do. } } private void inflateEntry(NotificationEntry entry, String reason) { abortInflation(entry, reason); mPendingNotifications.add(entry); mNotifInflater.inflateViews(entry); } Loading @@ -165,6 +220,32 @@ public class PreparationCoordinator implements Coordinator { private void abortInflation(NotificationEntry entry, String reason) { mLogger.logInflationAborted(entry.getKey(), reason); entry.abortTask(); mPendingNotifications.remove(entry); } private @InflationState int getInflationState(NotificationEntry entry) { Integer stateObj = mInflationStates.get(entry); Objects.requireNonNull(stateObj, "Asking state of a notification preparation coordinator doesn't know about"); return stateObj; } @Retention(RetentionPolicy.SOURCE) @IntDef(prefix = {"STATE_"}, value = {STATE_UNINFLATED, STATE_INFLATED_INVALID, STATE_INFLATED, STATE_ERROR}) @interface InflationState {} /** The notification has never been inflated before. */ private static final int STATE_UNINFLATED = 0; /** The notification is inflated. */ private static final int STATE_INFLATED = 1; /** * The notification is inflated, but its content may be out-of-date since the notification has * been updated. */ private static final int STATE_INFLATED_INVALID = 2; /** The notification errored out while inflating */ private static final int STATE_ERROR = -1; } Loading
packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifPipeline.java +12 −3 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.systemui.statusbar.notification.collection; import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeFinalizeFilterListener; import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeRenderListListener; import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeSortListener; import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeTransformGroupsListener; Loading Loading @@ -63,7 +64,7 @@ import javax.inject.Singleton; * 6. Top-level entries are assigned sections by NotifSections ({@link #setSections}) * 7. Top-level entries within the same section are sorted by NotifComparators * ({@link #setComparators}) * 8. Pre-render filters are fired on each notification ({@link #addPreRenderFilter}) * 8. Finalize filters are fired on each notification ({@link #addFinalizeFilter}) * 9. OnBeforeRenderListListeners are fired ({@link #addOnBeforeRenderListListener}) * 9. The list is handed off to the view layer to be rendered */ Loading Loading @@ -168,6 +169,14 @@ public class NotifPipeline implements CommonNotifCollection { mShadeListBuilder.setComparators(comparators); } /** * Called after notifs have been filtered once, grouped, and sorted but before the final * filtering. */ public void addOnBeforeFinalizeFilterListener(OnBeforeFinalizeFilterListener listener) { mShadeListBuilder.addOnBeforeFinalizeFilterListener(listener); } /** * Registers a filter with the pipeline to filter right before rendering the list (after * pre-group filtering, grouping, promoting and sorting occurs). Filters are Loading @@ -175,8 +184,8 @@ public class NotifPipeline implements CommonNotifCollection { * true, the notification is removed from the pipeline (and no other filters are called on that * notif). */ public void addPreRenderFilter(NotifFilter filter) { mShadeListBuilder.addPreRenderFilter(filter); public void addFinalizeFilter(NotifFilter filter) { mShadeListBuilder.addFinalizeFilter(filter); } /** Loading
packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java +27 −10 Original line number Diff line number Diff line Loading @@ -18,11 +18,11 @@ package com.android.systemui.statusbar.notification.collection; import static com.android.systemui.statusbar.notification.collection.GroupEntry.ROOT_ENTRY; import static com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState.STATE_BUILD_STARTED; import static com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState.STATE_FINALIZE_FILTERING; import static com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState.STATE_FINALIZING; import static com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState.STATE_GROUPING; import static com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState.STATE_IDLE; import static com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState.STATE_PRE_GROUP_FILTERING; import static com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState.STATE_PRE_RENDER_FILTERING; import static com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState.STATE_RESETTING; import static com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState.STATE_SORTING; import static com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState.STATE_TRANSFORMING; Loading @@ -36,6 +36,7 @@ import androidx.annotation.NonNull; import com.android.systemui.Dumpable; import com.android.systemui.dump.DumpManager; import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeFinalizeFilterListener; import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeRenderListListener; import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeSortListener; import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeTransformGroupsListener; Loading Loading @@ -82,7 +83,7 @@ public class ShadeListBuilder implements Dumpable { private final List<NotifFilter> mNotifPreGroupFilters = new ArrayList<>(); private final List<NotifPromoter> mNotifPromoters = new ArrayList<>(); private final List<NotifFilter> mNotifPreRenderFilters = new ArrayList<>(); private final List<NotifFilter> mNotifFinalizeFilters = new ArrayList<>(); private final List<NotifComparator> mNotifComparators = new ArrayList<>(); private final List<NotifSection> mNotifSections = new ArrayList<>(); Loading @@ -90,6 +91,8 @@ public class ShadeListBuilder implements Dumpable { new ArrayList<>(); private final List<OnBeforeSortListener> mOnBeforeSortListeners = new ArrayList<>(); private final List<OnBeforeFinalizeFilterListener> mOnBeforeFinalizeFilterListeners = new ArrayList<>(); private final List<OnBeforeRenderListListener> mOnBeforeRenderListListeners = new ArrayList<>(); @Nullable private OnRenderListListener mOnRenderListListener; Loading Loading @@ -142,6 +145,13 @@ public class ShadeListBuilder implements Dumpable { mOnBeforeSortListeners.add(listener); } void addOnBeforeFinalizeFilterListener(OnBeforeFinalizeFilterListener listener) { Assert.isMainThread(); mPipelineState.requireState(STATE_IDLE); mOnBeforeFinalizeFilterListeners.add(listener); } void addOnBeforeRenderListListener(OnBeforeRenderListListener listener) { Assert.isMainThread(); Loading @@ -157,12 +167,12 @@ public class ShadeListBuilder implements Dumpable { filter.setInvalidationListener(this::onPreGroupFilterInvalidated); } void addPreRenderFilter(NotifFilter filter) { void addFinalizeFilter(NotifFilter filter) { Assert.isMainThread(); mPipelineState.requireState(STATE_IDLE); mNotifPreRenderFilters.add(filter); filter.setInvalidationListener(this::onPreRenderFilterInvalidated); mNotifFinalizeFilters.add(filter); filter.setInvalidationListener(this::onFinalizeFilterInvalidated); } void addPromoter(NotifPromoter promoter) { Loading Loading @@ -237,12 +247,12 @@ public class ShadeListBuilder implements Dumpable { rebuildListIfBefore(STATE_SORTING); } private void onPreRenderFilterInvalidated(NotifFilter filter) { private void onFinalizeFilterInvalidated(NotifFilter filter) { Assert.isMainThread(); mLogger.logPreRenderFilterInvalidated(filter.getName(), mPipelineState.getState()); mLogger.logFinalizeFilterInvalidated(filter.getName(), mPipelineState.getState()); rebuildListIfBefore(STATE_PRE_RENDER_FILTERING); rebuildListIfBefore(STATE_FINALIZE_FILTERING); } private void onNotifComparatorInvalidated(NotifComparator comparator) { Loading Loading @@ -298,8 +308,9 @@ public class ShadeListBuilder implements Dumpable { // Step 6: Filter out entries after pre-group filtering, grouping, promoting and sorting // Now filters can see grouping information to determine whether to filter or not. mPipelineState.incrementTo(STATE_PRE_RENDER_FILTERING); filterNotifs(mNotifList, mNewNotifList, mNotifPreRenderFilters); dispatchOnBeforeFinalizeFilter(mReadOnlyNotifList); mPipelineState.incrementTo(STATE_FINALIZE_FILTERING); filterNotifs(mNotifList, mNewNotifList, mNotifFinalizeFilters); applyNewNotifList(); pruneIncompleteGroups(mNotifList); Loading Loading @@ -772,6 +783,12 @@ public class ShadeListBuilder implements Dumpable { } } private void dispatchOnBeforeFinalizeFilter(List<ListEntry> entries) { for (int i = 0; i < mOnBeforeFinalizeFilterListeners.size(); i++) { mOnBeforeFinalizeFilterListeners.get(i).onBeforeFinalizeFilter(entries); } } private void dispatchOnBeforeRenderList(List<ListEntry> entries) { for (int i = 0; i < mOnBeforeRenderListListeners.size(); i++) { mOnBeforeRenderListListeners.get(i).onBeforeRenderList(entries); Loading
packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/BubbleCoordinator.java +1 −1 Original line number Diff line number Diff line Loading @@ -77,7 +77,7 @@ public class BubbleCoordinator implements Coordinator { public void attach(NotifPipeline pipeline) { mNotifPipeline = pipeline; mNotifPipeline.addNotificationDismissInterceptor(mDismissInterceptor); mNotifPipeline.addPreRenderFilter(mNotifFilter); mNotifPipeline.addFinalizeFilter(mNotifFilter); mBubbleController.addNotifCallback(mNotifCallback); } Loading
packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java +1 −1 Original line number Diff line number Diff line Loading @@ -87,7 +87,7 @@ public class KeyguardCoordinator implements Coordinator { @Override public void attach(NotifPipeline pipeline) { setupInvalidateNotifListCallbacks(); pipeline.addPreRenderFilter(mNotifFilter); pipeline.addFinalizeFilter(mNotifFilter); } private final NotifFilter mNotifFilter = new NotifFilter(TAG) { Loading
packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java +100 −19 Original line number Diff line number Diff line Loading @@ -16,31 +16,39 @@ package com.android.systemui.statusbar.notification.collection.coordinator; import android.annotation.IntDef; import android.os.RemoteException; import android.service.notification.StatusBarNotification; import android.util.ArrayMap; import com.android.internal.statusbar.IStatusBarService; import com.android.systemui.statusbar.notification.collection.GroupEntry; import com.android.systemui.statusbar.notification.collection.ListEntry; import com.android.systemui.statusbar.notification.collection.NotifInflaterImpl; import com.android.systemui.statusbar.notification.collection.NotifPipeline; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.ShadeListBuilder; import com.android.systemui.statusbar.notification.collection.inflation.NotifInflater; import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeFinalizeFilterListener; import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter; import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener; import com.android.systemui.statusbar.notification.row.NotifInflationErrorManager; import java.util.ArrayList; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.List; import java.util.Map; import java.util.Objects; import javax.inject.Inject; import javax.inject.Singleton; /** * Kicks off notification inflation and view rebinding when a notification is added or updated. * Kicks off core notification inflation and view rebinding when a notification is added or updated. * Aborts inflation when a notification is removed. * * If a notification is not done inflating, this coordinator will filter the notification out * from the {@link ShadeListBuilder}. * If a notification was uninflated, this coordinator will filter the notification out from the * {@link ShadeListBuilder} until it is inflated. */ @Singleton public class PreparationCoordinator implements Coordinator { Loading @@ -49,7 +57,7 @@ public class PreparationCoordinator implements Coordinator { private final PreparationCoordinatorLogger mLogger; private final NotifInflater mNotifInflater; private final NotifInflationErrorManager mNotifErrorManager; private final List<NotificationEntry> mPendingNotifications = new ArrayList<>(); private final Map<NotificationEntry, Integer> mInflationStates = new ArrayMap<>(); private final IStatusBarService mStatusBarService; @Inject Loading @@ -69,27 +77,44 @@ public class PreparationCoordinator implements Coordinator { @Override public void attach(NotifPipeline pipeline) { pipeline.addCollectionListener(mNotifCollectionListener); pipeline.addPreRenderFilter(mNotifInflationErrorFilter); pipeline.addPreRenderFilter(mNotifInflatingFilter); // Inflate after grouping/sorting since that affects what views to inflate. pipeline.addOnBeforeFinalizeFilterListener(mOnBeforeFinalizeFilterListener); pipeline.addFinalizeFilter(mNotifInflationErrorFilter); pipeline.addFinalizeFilter(mNotifInflatingFilter); } private final NotifCollectionListener mNotifCollectionListener = new NotifCollectionListener() { @Override public void onEntryAdded(NotificationEntry entry) { inflateEntry(entry, "entryAdded"); public void onEntryInit(NotificationEntry entry) { mInflationStates.put(entry, STATE_UNINFLATED); } @Override public void onEntryUpdated(NotificationEntry entry) { rebind(entry, "entryUpdated"); @InflationState int state = getInflationState(entry); if (state == STATE_INFLATED) { mInflationStates.put(entry, STATE_INFLATED_INVALID); } else if (state == STATE_ERROR) { // Updated so maybe it won't error out now. mInflationStates.put(entry, STATE_UNINFLATED); } } @Override public void onEntryRemoved(NotificationEntry entry, int reason) { abortInflation(entry, "entryRemoved reason=" + reason); } @Override public void onEntryCleanUp(NotificationEntry entry) { mInflationStates.remove(entry); } }; private final OnBeforeFinalizeFilterListener mOnBeforeFinalizeFilterListener = entries -> inflateAllRequiredViews(entries); private final NotifFilter mNotifInflationErrorFilter = new NotifFilter( TAG + "InflationError") { /** Loading @@ -97,10 +122,7 @@ public class PreparationCoordinator implements Coordinator { */ @Override public boolean shouldFilterOut(NotificationEntry entry, long now) { if (mNotifErrorManager.hasInflationError(entry)) { return true; } return false; return getInflationState(entry) == STATE_ERROR; } }; Loading @@ -110,7 +132,8 @@ public class PreparationCoordinator implements Coordinator { */ @Override public boolean shouldFilterOut(NotificationEntry entry, long now) { return mPendingNotifications.contains(entry); @InflationState int state = getInflationState(entry); return (state != STATE_INFLATED) && (state != STATE_INFLATED_INVALID); } }; Loading @@ -119,7 +142,7 @@ public class PreparationCoordinator implements Coordinator { @Override public void onInflationFinished(NotificationEntry entry) { mLogger.logNotifInflated(entry.getKey()); mPendingNotifications.remove(entry); mInflationStates.put(entry, STATE_INFLATED); mNotifInflatingFilter.invalidateList(); } }; Loading @@ -128,7 +151,7 @@ public class PreparationCoordinator implements Coordinator { new NotifInflationErrorManager.NotifInflationErrorListener() { @Override public void onNotifInflationError(NotificationEntry entry, Exception e) { mPendingNotifications.remove(entry); mInflationStates.put(entry, STATE_ERROR); try { final StatusBarNotification sbn = entry.getSbn(); // report notification inflation errors back up Loading @@ -152,9 +175,41 @@ public class PreparationCoordinator implements Coordinator { } }; private void inflateAllRequiredViews(List<ListEntry> entries) { for (int i = 0, size = entries.size(); i < size; i++) { ListEntry entry = entries.get(i); if (entry instanceof GroupEntry) { GroupEntry groupEntry = (GroupEntry) entry; inflateNotifRequiredViews(groupEntry.getSummary()); List<NotificationEntry> children = groupEntry.getChildren(); for (int j = 0, groupSize = children.size(); j < groupSize; j++) { inflateNotifRequiredViews(children.get(j)); } } else { NotificationEntry notifEntry = (NotificationEntry) entry; inflateNotifRequiredViews(notifEntry); } } } private void inflateNotifRequiredViews(NotificationEntry entry) { @InflationState int state = mInflationStates.get(entry); switch (state) { case STATE_UNINFLATED: inflateEntry(entry, "entryAdded"); break; case STATE_INFLATED_INVALID: rebind(entry, "entryUpdated"); break; case STATE_INFLATED: case STATE_ERROR: default: // Nothing to do. } } private void inflateEntry(NotificationEntry entry, String reason) { abortInflation(entry, reason); mPendingNotifications.add(entry); mNotifInflater.inflateViews(entry); } Loading @@ -165,6 +220,32 @@ public class PreparationCoordinator implements Coordinator { private void abortInflation(NotificationEntry entry, String reason) { mLogger.logInflationAborted(entry.getKey(), reason); entry.abortTask(); mPendingNotifications.remove(entry); } private @InflationState int getInflationState(NotificationEntry entry) { Integer stateObj = mInflationStates.get(entry); Objects.requireNonNull(stateObj, "Asking state of a notification preparation coordinator doesn't know about"); return stateObj; } @Retention(RetentionPolicy.SOURCE) @IntDef(prefix = {"STATE_"}, value = {STATE_UNINFLATED, STATE_INFLATED_INVALID, STATE_INFLATED, STATE_ERROR}) @interface InflationState {} /** The notification has never been inflated before. */ private static final int STATE_UNINFLATED = 0; /** The notification is inflated. */ private static final int STATE_INFLATED = 1; /** * The notification is inflated, but its content may be out-of-date since the notification has * been updated. */ private static final int STATE_INFLATED_INVALID = 2; /** The notification errored out while inflating */ private static final int STATE_ERROR = -1; }