diff options
6 files changed, 197 insertions, 222 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java index 95867957f648..a816eccebe33 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java @@ -516,6 +516,7 @@ public class NotificationRemoteInputManager implements Dumpable { return mLifetimeExtenders; } + @Nullable public RemoteInputController getController() { return mRemoteInputController; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt index 44a5c958c408..c1a63e969d8e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt @@ -65,13 +65,11 @@ class ShadeViewManager constructor( return root } - private fun buildNotifNode(entry: ListEntry, parent: NodeSpec): NodeSpec { - return when (entry) { - is NotificationEntry -> NodeSpecImpl(parent, viewBarn.requireView(entry)) - is GroupEntry -> NodeSpecImpl(parent, viewBarn.requireView(checkNotNull(entry.summary))) - .apply { entry.children.forEach { children.add(buildNotifNode(it, this)) } } - else -> throw RuntimeException("Unexpected entry: $entry") - } + private fun buildNotifNode(entry: ListEntry, parent: NodeSpec): NodeSpec = when (entry) { + is NotificationEntry -> NodeSpecImpl(parent, viewBarn.requireView(entry)) + is GroupEntry -> NodeSpecImpl(parent, viewBarn.requireView(checkNotNull(entry.summary))) + .apply { entry.children.forEach { children.add(buildNotifNode(it, this)) } } + else -> throw RuntimeException("Unexpected entry: $entry") } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java index b33aa5739273..419d0a34c6bd 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java @@ -16,14 +16,10 @@ package com.android.systemui.statusbar.notification.stack; -import static android.service.notification.NotificationStats.DISMISSAL_SHADE; -import static android.service.notification.NotificationStats.DISMISS_SENTIMENT_NEUTRAL; - import static com.android.systemui.statusbar.notification.ActivityLaunchAnimator.ExpandAnimationParameters; import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManagerKt.BUCKET_SILENT; import static com.android.systemui.statusbar.notification.stack.StackScrollAlgorithm.ANCHOR_SCROLLING; import static com.android.systemui.statusbar.notification.stack.StackStateAnimator.ANIMATION_DURATION_SWIPE; -import static com.android.systemui.statusbar.phone.NotificationIconAreaController.HIGH_PRIORITY; import static com.android.systemui.util.InjectionInflationController.VIEW_CONTEXT; import static java.lang.annotation.RetentionPolicy.SOURCE; @@ -49,10 +45,8 @@ import android.graphics.PorterDuff; import android.graphics.PorterDuffXfermode; import android.graphics.Rect; import android.os.Bundle; -import android.os.ServiceManager; import android.os.UserHandle; import android.provider.Settings; -import android.service.notification.NotificationListenerService; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.util.Log; @@ -83,8 +77,6 @@ import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.UiEvent; import com.android.internal.logging.UiEventLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; -import com.android.internal.statusbar.IStatusBarService; -import com.android.internal.statusbar.NotificationVisibility; import com.android.keyguard.KeyguardSliceView; import com.android.settingslib.Utils; import com.android.systemui.Dependency; @@ -96,27 +88,21 @@ import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.DragDownHelper.DragDownCallback; import com.android.systemui.statusbar.EmptyShadeView; -import com.android.systemui.statusbar.FeatureFlags; import com.android.systemui.statusbar.NotificationRemoteInputManager; import com.android.systemui.statusbar.NotificationShelf; import com.android.systemui.statusbar.NotificationShelfController; +import com.android.systemui.statusbar.RemoteInputController; import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.SysuiStatusBarStateController; import com.android.systemui.statusbar.notification.DynamicPrivacyController; import com.android.systemui.statusbar.notification.FakeShadowView; import com.android.systemui.statusbar.notification.ForegroundServiceDismissalFeatureController; import com.android.systemui.statusbar.notification.NotificationActivityStarter; -import com.android.systemui.statusbar.notification.NotificationEntryListener; -import com.android.systemui.statusbar.notification.NotificationEntryManager; import com.android.systemui.statusbar.notification.NotificationUtils; import com.android.systemui.statusbar.notification.ShadeViewRefactor; import com.android.systemui.statusbar.notification.ShadeViewRefactor.RefactorComponent; -import com.android.systemui.statusbar.notification.collection.NotifCollection; -import com.android.systemui.statusbar.notification.collection.NotifPipeline; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager; -import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats; -import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener; import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManager; import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager; import com.android.systemui.statusbar.notification.logging.NotificationLogger; @@ -136,7 +122,6 @@ import com.android.systemui.statusbar.phone.ShadeController; import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.policy.HeadsUpUtil; import com.android.systemui.statusbar.policy.ScrollAdapter; -import com.android.systemui.tuner.TunerService; import com.android.systemui.util.Assert; import java.io.FileDescriptor; @@ -225,7 +210,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable private int mBottomMargin; private int mBottomInset = 0; private float mQsExpansionFraction; - private int mCurrentUserId; /** * The algorithm which calculates the properties for our children @@ -468,12 +452,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable private int mHeadsUpInset; private HeadsUpAppearanceController mHeadsUpAppearanceController; private final Rect mTmpRect = new Rect(); - private final FeatureFlags mFeatureFlags; - private final NotifPipeline mNotifPipeline; - private final NotifCollection mNotifCollection; - private final NotificationEntryManager mEntryManager; - private final IStatusBarService mBarService = IStatusBarService.Stub.asInterface( - ServiceManager.getService(Context.STATUS_BAR_SERVICE)); + private DismissAllAnimationListener mDismissAllAnimationListener; @VisibleForTesting protected final MetricsLogger mMetricsLogger = Dependency.get(MetricsLogger.class); protected final UiEventLogger mUiEventLogger; @@ -558,13 +537,9 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable NotificationSectionsManager notificationSectionsManager, ForegroundServiceSectionController fgsSectionController, ForegroundServiceDismissalFeatureController fgsFeatureController, - FeatureFlags featureFlags, - NotifPipeline notifPipeline, - NotificationEntryManager entryManager, - NotifCollection notifCollection, - UiEventLogger uiEventLogger, GroupMembershipManager groupMembershipManager, - GroupExpansionManager groupExpansionManager + GroupExpansionManager groupExpansionManager, + UiEventLogger uiEventLogger ) { super(context, attrs, 0, 0); Resources res = getResources(); @@ -613,36 +588,8 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable mDebugPaint.setTextSize(25f); } mClearAllEnabled = res.getBoolean(R.bool.config_enableNotificationsClearAll); - - TunerService tunerService = Dependency.get(TunerService.class); - tunerService.addTunable((key, newValue) -> { - if (key.equals(HIGH_PRIORITY)) { - mHighPriorityBeforeSpeedBump = "1".equals(newValue); - } - }, HIGH_PRIORITY); - - mFeatureFlags = featureFlags; - mNotifPipeline = notifPipeline; - mEntryManager = entryManager; - mNotifCollection = notifCollection; - if (mFeatureFlags.isNewNotifPipelineRenderingEnabled()) { - mNotifPipeline.addCollectionListener(new NotifCollectionListener() { - @Override - public void onEntryUpdated(NotificationEntry entry) { - NotificationStackScrollLayout.this.onEntryUpdated(entry); - } - }); - } else { - mEntryManager.addNotificationEntryListener(new NotificationEntryListener() { - @Override - public void onPreEntryUpdated(NotificationEntry entry) { - NotificationStackScrollLayout.this.onEntryUpdated(entry); - } - }); - } mGroupMembershipManager = groupMembershipManager; mGroupExpansionManager = groupExpansionManager; - mDynamicPrivacyController = dynamicPrivacyController; mStatusbarStateController = statusbarStateController; initializeForegroundServiceSection(fgsFeatureController); @@ -707,10 +654,12 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable if (mFooterView == null) { return; } + // TODO: move this logic to controller, which will invoke updateFooterView directly boolean showDismissView = mClearAllEnabled && hasActiveClearableNotifications(ROWS_ALL); - boolean showFooterView = (showDismissView || hasActiveNotifications()) + RemoteInputController remoteInputController = mRemoteInputManager.getController(); + boolean showFooterView = (showDismissView || mController.hasActiveNotifications()) && mStatusBarState != StatusBarState.KEYGUARD - && !mRemoteInputManager.getController().isRemoteInputActive(); + && (remoteInputController == null || !remoteInputController.isRemoteInputActive()); boolean showHistory = Settings.Secure.getIntForUser(mContext.getContentResolver(), Settings.Secure.NOTIFICATION_HISTORY_ENABLED, 0, UserHandle.USER_CURRENT) == 1; @@ -5292,8 +5241,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable updateFooter(); requestChildrenUpdate(); onUpdateRowStates(); - - mEntryManager.updateNotifications("StatusBar state changed"); updateVisibility(); } @@ -5697,10 +5644,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable return mController; } - void setCurrentUserid(int userId) { - mCurrentUserId = userId; - } - void addSwipedOutView(View v) { mSwipedOutViews.add(v); } @@ -5774,6 +5717,14 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable return mCheckForLeavebehind; } + void setDismissAllAnimationListener(DismissAllAnimationListener dismissAllAnimationListener) { + mDismissAllAnimationListener = dismissAllAnimationListener; + } + + public void setHighPriorityBeforeSpeedBump(boolean highPriorityBeforeSpeedBump) { + mHighPriorityBeforeSpeedBump = highPriorityBeforeSpeedBump; + } + /** * A listener that is notified when the empty space below the notifications is clicked on */ @@ -6127,7 +6078,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable // --------------------- NotificationEntryManager/NotifPipeline methods ------------------------ - private void onEntryUpdated(NotificationEntry entry) { + void onEntryUpdated(NotificationEntry entry) { // If the row already exists, the user may have performed a dismiss action on the // notification. Since it's not clearable we should snap it back. if (entry.rowExists() && !entry.getSbn().isClearable()) { @@ -6135,73 +6086,17 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable } } - private boolean hasActiveNotifications() { - if (mFeatureFlags.isNewNotifPipelineRenderingEnabled()) { - return !mNotifPipeline.getShadeList().isEmpty(); - } else { - return mEntryManager.hasActiveNotifications(); - } - } - /** * Called after the animations for a "clear all notifications" action has ended. */ private void onDismissAllAnimationsEnd( List<ExpandableNotificationRow> viewsToRemove, @SelectedRows int selectedRows) { - if (mFeatureFlags.isNewNotifPipelineRenderingEnabled()) { - if (selectedRows == ROWS_ALL) { - mNotifCollection.dismissAllNotifications(mCurrentUserId); - } else { - final List<Pair<NotificationEntry, DismissedByUserStats>> - entriesWithRowsDismissedFromShade = new ArrayList<>(); - final int numVisibleEntries = mNotifPipeline.getShadeListCount(); - for (int i = 0; i < viewsToRemove.size(); i++) { - final NotificationEntry entry = viewsToRemove.get(i).getEntry(); - entriesWithRowsDismissedFromShade.add( - new Pair<NotificationEntry, DismissedByUserStats>( - entry, - getDismissedByUserStats(entry, numVisibleEntries))); - } - mNotifCollection.dismissNotifications(entriesWithRowsDismissedFromShade); - } - } else { - for (ExpandableNotificationRow rowToRemove : viewsToRemove) { - if (canChildBeDismissed(rowToRemove)) { - mEntryManager.performRemoveNotification( - rowToRemove.getEntry().getSbn(), - getDismissedByUserStats( - rowToRemove.getEntry(), - mEntryManager.getActiveNotificationsCount()), - NotificationListenerService.REASON_CANCEL_ALL); - } else { - rowToRemove.resetTranslation(); - } - } - if (selectedRows == ROWS_ALL) { - try { - mBarService.onClearAllNotifications(mCurrentUserId); - } catch (Exception ex) { - } - } + if (mDismissAllAnimationListener != null) { + mDismissAllAnimationListener.onAnimationEnd(viewsToRemove, selectedRows); } } - private DismissedByUserStats getDismissedByUserStats( - NotificationEntry entry, - int numVisibleEntries - ) { - return new DismissedByUserStats( - DISMISSAL_SHADE, - DISMISS_SENTIMENT_NEUTRAL, - NotificationVisibility.obtain( - entry.getKey(), - entry.getRanking().getRank(), - numVisibleEntries, - true, - NotificationLogger.getNotificationLocation(entry))); - } - public void setKeyguardMediaControllorVisible(boolean keyguardMediaControllorVisible) { mKeyguardMediaControllorVisible = keyguardMediaControllorVisible; } @@ -6218,7 +6113,8 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable /* Only ever called as a consequence of a lockscreen expansion gesture. */ @Override public boolean onDraggedDown(View startingChild, int dragLengthY) { - boolean canDragDown = hasActiveNotifications() || mKeyguardMediaControllorVisible; + boolean canDragDown = + mController.hasActiveNotifications() || mKeyguardMediaControllorVisible; if (mStatusBarState == StatusBarState.KEYGUARD && canDragDown) { mLockscreenGestureLogger.write( MetricsEvent.ACTION_LS_SHADE, @@ -6424,7 +6320,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable /** Enum for selecting some or all notification rows (does not included non-notif views). */ @Retention(SOURCE) @IntDef({ROWS_ALL, ROWS_HIGH_PRIORITY, ROWS_GENTLE}) - public @interface SelectedRows {} + @interface SelectedRows {} /** All rows representing notifs. */ public static final int ROWS_ALL = 0; /** Only rows where entry.isHighPriority() is true. */ @@ -6466,4 +6362,9 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable interface KeyguardBypassEnabledProvider { boolean getBypassEnabled(); } + + interface DismissAllAnimationListener { + void onAnimationEnd( + List<ExpandableNotificationRow> viewsToRemove, @SelectedRows int selectedRows); + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java index c10362d00a13..718bfba5811b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java @@ -16,17 +16,28 @@ package com.android.systemui.statusbar.notification.stack; +import static android.service.notification.NotificationStats.DISMISSAL_SHADE; +import static android.service.notification.NotificationStats.DISMISS_SENTIMENT_NEUTRAL; + import static com.android.systemui.Dependency.ALLOW_NOTIFICATION_LONG_PRESS_NAME; import static com.android.systemui.statusbar.StatusBarState.KEYGUARD; import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.ROWS_GENTLE; import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.ROWS_HIGH_PRIORITY; +import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.OnEmptySpaceClickListener; +import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.OnOverscrollTopChangedListener; +import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.ROWS_ALL; +import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.SelectedRows; +import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.canChildBeDismissed; +import static com.android.systemui.statusbar.phone.NotificationIconAreaController.HIGH_PRIORITY; import android.content.res.Resources; import android.graphics.Point; import android.graphics.PointF; import android.provider.Settings; +import android.service.notification.NotificationListenerService; import android.service.notification.StatusBarNotification; import android.util.Log; +import android.util.Pair; import android.view.Display; import android.view.MotionEvent; import android.view.View; @@ -37,6 +48,8 @@ import android.widget.FrameLayout; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; +import com.android.internal.statusbar.IStatusBarService; +import com.android.internal.statusbar.NotificationVisibility; import com.android.systemui.ExpandHelper; import com.android.systemui.Gefingerpoken; import com.android.systemui.R; @@ -49,6 +62,7 @@ import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin; import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.OnMenuEventListener; import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper; import com.android.systemui.plugins.statusbar.StatusBarStateController; +import com.android.systemui.statusbar.FeatureFlags; import com.android.systemui.statusbar.NotificationLockscreenUserManager; import com.android.systemui.statusbar.NotificationLockscreenUserManager.UserChangedListener; import com.android.systemui.statusbar.NotificationShelfController; @@ -58,10 +72,16 @@ import com.android.systemui.statusbar.SysuiStatusBarStateController; import com.android.systemui.statusbar.notification.ActivityLaunchAnimator; import com.android.systemui.statusbar.notification.DynamicPrivacyController; import com.android.systemui.statusbar.notification.NotificationActivityStarter; +import com.android.systemui.statusbar.notification.NotificationEntryListener; +import com.android.systemui.statusbar.notification.NotificationEntryManager; +import com.android.systemui.statusbar.notification.collection.NotifCollection; +import com.android.systemui.statusbar.notification.collection.NotifPipeline; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy; import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy.NotificationGroup; import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy.OnGroupChangeListener; +import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats; +import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener; import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManager; import com.android.systemui.statusbar.notification.collection.render.SectionHeaderController; import com.android.systemui.statusbar.notification.dagger.SilentHeader; @@ -86,6 +106,8 @@ import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener; import com.android.systemui.statusbar.policy.ZenModeController; import com.android.systemui.tuner.TunerService; +import java.util.ArrayList; +import java.util.List; import java.util.function.BiConsumer; import javax.inject.Inject; @@ -114,6 +136,11 @@ public class NotificationStackScrollLayoutController { private final Resources mResources; private final NotificationSwipeHelper.Builder mNotificationSwipeHelperBuilder; private final ScrimController mScrimController; + private final FeatureFlags mFeatureFlags; + private final NotifPipeline mNotifPipeline; + private final NotifCollection mNotifCollection; + private final NotificationEntryManager mNotificationEntryManager; + private final IStatusBarService mIStatusBarService; private final KeyguardMediaController mKeyguardMediaController; private final SysuiStatusBarStateController mStatusBarStateController; private final KeyguardBypassController mKeyguardBypassController; @@ -211,13 +238,13 @@ public class NotificationStackScrollLayoutController { mView.updateSensitiveness(mStatusBarStateController.goingToFullShade(), mLockscreenUserManager.isAnyProfilePublicMode()); mView.onStatePostChange(mStatusBarStateController.fromShadeLocked()); + mNotificationEntryManager.updateNotifications("StatusBar state changed"); } }; private final UserChangedListener mLockscreenUserChangeListener = new UserChangedListener() { @Override public void onUserChanged(int userId) { - mView.setCurrentUserid(userId); mView.updateSensitiveness(false, mLockscreenUserManager.isAnyProfilePublicMode()); } }; @@ -525,7 +552,12 @@ public class NotificationStackScrollLayoutController { ScrimController scrimController, NotificationGroupManagerLegacy legacyGroupManager, GroupExpansionManager groupManager, - @SilentHeader SectionHeaderController silentHeaderController) { + @SilentHeader SectionHeaderController silentHeaderController, + FeatureFlags featureFlags, + NotifPipeline notifPipeline, + NotifCollection notifCollection, + NotificationEntryManager notificationEntryManager, + IStatusBarService iStatusBarService) { mAllowLongPress = allowLongPress; mNotificationGutsManager = notificationGutsManager; mHeadsUpManager = headsUpManager; @@ -549,7 +581,6 @@ public class NotificationStackScrollLayoutController { groupManager.registerGroupExpansionChangeListener((changedRow, expanded) -> { mView.onGroupExpandChanged(changedRow, expanded); }); - legacyGroupManager.registerGroupChangeListener(new OnGroupChangeListener() { @Override public void onGroupCreatedFromChildren(NotificationGroup group) { @@ -562,6 +593,11 @@ public class NotificationStackScrollLayoutController { } }); mSilentHeaderController = silentHeaderController; + mFeatureFlags = featureFlags; + mNotifPipeline = notifPipeline; + mNotifCollection = notifCollection; + mNotificationEntryManager = notificationEntryManager; + mIStatusBarService = iStatusBarService; } public void attach(NotificationStackScrollLayout view) { @@ -569,6 +605,7 @@ public class NotificationStackScrollLayoutController { mView.setController(this); mView.setTouchHandler(new TouchHandler()); mView.setStatusBar(mStatusBar); + mView.setDismissAllAnimationListener(this::onAnimationEnd); mSwipeHelper = mNotificationSwipeHelperBuilder .setSwipeDirection(SwipeHelper.X) @@ -576,6 +613,22 @@ public class NotificationStackScrollLayoutController { .setOnMenuEventListener(mMenuEventListener) .build(); + if (mFeatureFlags.isNewNotifPipelineRenderingEnabled()) { + mNotifPipeline.addCollectionListener(new NotifCollectionListener() { + @Override + public void onEntryUpdated(NotificationEntry entry) { + mView.onEntryUpdated(entry); + } + }); + } else { + mNotificationEntryManager.addNotificationEntryListener(new NotificationEntryListener() { + @Override + public void onPreEntryUpdated(NotificationEntry entry) { + mView.onEntryUpdated(entry); + } + }); + } + mView.initView(mView.getContext(), mKeyguardBypassController::getBypassEnabled, mSwipeHelper); @@ -587,7 +640,6 @@ public class NotificationStackScrollLayoutController { mScrimController.setScrimBehindChangeRunnable(mView::updateBackgroundDimming); mLockscreenUserManager.addUserChangedListener(mLockscreenUserChangeListener); - mView.setCurrentUserid(mLockscreenUserManager.getCurrentUserId()); mFadeNotificationsOnDismiss = // TODO: this should probably be injected directly mResources.getBoolean(R.bool.config_fadeNotificationsOnDismiss); @@ -597,12 +649,19 @@ public class NotificationStackScrollLayoutController { mTunerService.addTunable( (key, newValue) -> { - if (key.equals(Settings.Secure.NOTIFICATION_DISMISS_RTL)) { - mView.updateDismissRtlSetting("1".equals(newValue)); - } else if (key.equals(Settings.Secure.NOTIFICATION_HISTORY_ENABLED)) { - updateFooter(); + switch (key) { + case Settings.Secure.NOTIFICATION_DISMISS_RTL: + mView.updateDismissRtlSetting("1".equals(newValue)); + break; + case Settings.Secure.NOTIFICATION_HISTORY_ENABLED: + updateFooter(); + break; + case HIGH_PRIORITY: + mView.setHighPriorityBeforeSpeedBump("1".equals(newValue)); + break; } }, + HIGH_PRIORITY, Settings.Secure.NOTIFICATION_DISMISS_RTL, Settings.Secure.NOTIFICATION_HISTORY_ENABLED); @@ -684,12 +743,12 @@ public class NotificationStackScrollLayoutController { } public void setOverscrollTopChangedListener( - NotificationStackScrollLayout.OnOverscrollTopChangedListener listener) { + OnOverscrollTopChangedListener listener) { mView.setOverscrollTopChangedListener(listener); } public void setOnEmptySpaceClickListener( - NotificationStackScrollLayout.OnEmptySpaceClickListener listener) { + OnEmptySpaceClickListener listener) { mView.setOnEmptySpaceClickListener(listener); } @@ -1008,7 +1067,7 @@ public class NotificationStackScrollLayoutController { } public boolean hasActiveClearableNotifications( - @NotificationStackScrollLayout.SelectedRows int selection) { + @SelectedRows int selection) { return mView.hasActiveClearableNotifications(selection); } @@ -1120,6 +1179,29 @@ public class NotificationStackScrollLayoutController { mView.resetCheckSnoozeLeavebehind(); } + private DismissedByUserStats getDismissedByUserStats( + NotificationEntry entry, + int numVisibleEntries + ) { + return new DismissedByUserStats( + DISMISSAL_SHADE, + DISMISS_SENTIMENT_NEUTRAL, + NotificationVisibility.obtain( + entry.getKey(), + entry.getRanking().getRank(), + numVisibleEntries, + true, + NotificationLogger.getNotificationLocation(entry))); + } + + boolean hasActiveNotifications() { + if (mFeatureFlags.isNewNotifPipelineRenderingEnabled()) { + return !mNotifPipeline.getShadeList().isEmpty(); + } else { + return mNotificationEntryManager.hasActiveNotifications(); + } + } + public void closeControlsIfOutsideTouch(MotionEvent ev) { NotificationGuts guts = mNotificationGutsManager.getExposedGuts(); NotificationMenuRowPlugin menuRow = mSwipeHelper.getCurrentMenuRow(); @@ -1148,6 +1230,47 @@ public class NotificationStackScrollLayoutController { mView.clearNotifications(ROWS_GENTLE, closeShade); } + private void onAnimationEnd(List<ExpandableNotificationRow> viewsToRemove, int selectedRows) { + if (mFeatureFlags.isNewNotifPipelineRenderingEnabled()) { + if (selectedRows == ROWS_ALL) { + mNotifCollection.dismissAllNotifications( + mLockscreenUserManager.getCurrentUserId()); + } else { + final List<Pair<NotificationEntry, DismissedByUserStats>> + entriesWithRowsDismissedFromShade = new ArrayList<>(); + final int numVisibleEntries = mNotifPipeline.getShadeListCount(); + for (ExpandableNotificationRow row : viewsToRemove) { + final NotificationEntry entry = row.getEntry(); + entriesWithRowsDismissedFromShade.add( + new Pair<>( + entry, + getDismissedByUserStats(entry, numVisibleEntries))); + } + mNotifCollection.dismissNotifications(entriesWithRowsDismissedFromShade); + } + } else { + for (ExpandableNotificationRow rowToRemove : viewsToRemove) { + if (canChildBeDismissed(rowToRemove)) { + mNotificationEntryManager.performRemoveNotification( + rowToRemove.getEntry().getSbn(), + getDismissedByUserStats( + rowToRemove.getEntry(), + mNotificationEntryManager.getActiveNotificationsCount()), + NotificationListenerService.REASON_CANCEL_ALL); + } else { + rowToRemove.resetTranslation(); + } + } + if (selectedRows == ROWS_ALL) { + try { + mIStatusBarService.onClearAllNotifications( + mLockscreenUserManager.getCurrentUserId()); + } catch (Exception ignored) { + } + } + } + } + private class NotificationListContainerImpl implements NotificationListContainer { @Override diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java index de59ac319bd9..ecbd339409a4 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java @@ -43,14 +43,10 @@ import androidx.test.filters.SmallTest; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.testing.UiEventLoggerFake; -import com.android.internal.statusbar.IStatusBarService; import com.android.systemui.ExpandHelper; import com.android.systemui.R; import com.android.systemui.SysuiTestCase; import com.android.systemui.statusbar.EmptyShadeView; -import com.android.systemui.statusbar.FeatureFlags; -import com.android.systemui.statusbar.NotificationMediaManager; -import com.android.systemui.statusbar.NotificationPresenter; import com.android.systemui.statusbar.NotificationRemoteInputManager; import com.android.systemui.statusbar.NotificationShelf; import com.android.systemui.statusbar.NotificationShelfController; @@ -59,28 +55,15 @@ import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.SysuiStatusBarStateController; import com.android.systemui.statusbar.notification.DynamicPrivacyController; import com.android.systemui.statusbar.notification.ForegroundServiceDismissalFeatureController; -import com.android.systemui.statusbar.notification.NotificationEntryManager; -import com.android.systemui.statusbar.notification.NotificationEntryManagerLogger; -import com.android.systemui.statusbar.notification.NotificationFilter; -import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager; -import com.android.systemui.statusbar.notification.collection.NotifCollection; -import com.android.systemui.statusbar.notification.collection.NotifPipeline; import com.android.systemui.statusbar.notification.collection.NotificationEntry; -import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder; -import com.android.systemui.statusbar.notification.collection.NotificationRankingManager; -import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinder; import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy; import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager; -import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider; -import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import com.android.systemui.statusbar.notification.row.FooterView; import com.android.systemui.statusbar.notification.row.NotificationBlockingHelperManager; import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.KeyguardBypassEnabledProvider; -import com.android.systemui.statusbar.phone.HeadsUpManagerPhone; import com.android.systemui.statusbar.phone.ShadeController; import com.android.systemui.statusbar.phone.StatusBar; -import com.android.systemui.util.leak.LeakDetector; import org.junit.After; import org.junit.Before; @@ -92,9 +75,6 @@ import org.mockito.Mock; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; -import java.util.ArrayList; -import java.util.List; - /** * Tests for {@link NotificationStackScrollLayout}. */ @@ -109,7 +89,6 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { @Rule public MockitoRule mockito = MockitoJUnit.rule(); @Mock private StatusBar mBar; @Mock private SysuiStatusBarStateController mBarState; - @Mock private HeadsUpManagerPhone mHeadsUpManager; @Mock private NotificationBlockingHelperManager mBlockingHelperManager; @Mock private NotificationGroupManagerLegacy mGroupMembershipManger; @Mock private NotificationGroupManagerLegacy mGroupExpansionManager; @@ -122,11 +101,9 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { @Mock private KeyguardBypassEnabledProvider mKeyguardBypassEnabledProvider; @Mock private NotificationSectionsManager mNotificationSectionsManager; @Mock private NotificationSection mNotificationSection; - @Mock private FeatureFlags mFeatureFlags; @Mock private SysuiStatusBarStateController mStatusBarStateController; @Mock private NotificationSwipeHelper mNotificationSwipeHelper; - @Mock NotificationStackScrollLayoutController mStackScrollLayoutController; - private NotificationEntryManager mEntryManager; + @Mock private NotificationStackScrollLayoutController mStackScrollLayoutController; private int mOriginalInterruptionModelSetting; private UiEventLoggerFake mUiEventLoggerFake = new UiEventLoggerFake(); @@ -154,31 +131,6 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { mRemoteInputManager); mDependency.injectMockDependency(ShadeController.class); when(mRemoteInputManager.getController()).thenReturn(mRemoteInputController); - - mEntryManager = new NotificationEntryManager( - mock(NotificationEntryManagerLogger.class), - mock(NotificationGroupManagerLegacy.class), - new NotificationRankingManager( - () -> mock(NotificationMediaManager.class), - mGroupMembershipManger, - mHeadsUpManager, - mock(NotificationFilter.class), - mock(NotificationEntryManagerLogger.class), - mock(NotificationSectionsFeatureManager.class), - mock(PeopleNotificationIdentifier.class), - mock(HighPriorityProvider.class) - ), - mock(NotificationEntryManager.KeyguardEnvironment.class), - mock(FeatureFlags.class), - () -> mock(NotificationRowBinder.class), - () -> mRemoteInputManager, - mock(LeakDetector.class), - mock(ForegroundServiceDismissalFeatureController.class), - mock(IStatusBarService.class) - ); - mEntryManager.setUpWithPresenter(mock(NotificationPresenter.class)); - when(mFeatureFlags.isNewNotifPipelineRenderingEnabled()).thenReturn(false); - NotificationShelfController notificationShelfController = mock(NotificationShelfController.class); NotificationShelf notificationShelf = mock(NotificationShelf.class); @@ -201,13 +153,9 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { mNotificationSectionsManager, mock(ForegroundServiceSectionController.class), mock(ForegroundServiceDismissalFeatureController.class), - mFeatureFlags, - mock(NotifPipeline.class), - mEntryManager, - mock(NotifCollection.class), - mUiEventLoggerFake, mGroupMembershipManger, - mGroupExpansionManager + mGroupExpansionManager, + mUiEventLoggerFake ); mStackScrollerInternal.initView(getContext(), mKeyguardBypassEnabledProvider, mNotificationSwipeHelper); @@ -216,9 +164,9 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { mStackScroller.setStatusBar(mBar); mStackScroller.setEmptyShadeView(mEmptyShadeView); when(mStackScrollLayoutController.getNoticationRoundessManager()) - .thenReturn(mock(NotificationRoundnessManager.class)); + .thenReturn(mNotificationRoundnessManager); mStackScroller.setController(mStackScrollLayoutController); - + // Stub out functionality that isn't necessary to test. doNothing().when(mBar) .executeRunnableDismissingKeyguard(any(Runnable.class), @@ -323,8 +271,6 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { @Test public void testUpdateFooter_noNotifications() { setBarStateForTest(StatusBarState.SHADE); - assertEquals(0, mEntryManager.getActiveNotificationsCount()); - FooterView view = mock(FooterView.class); mStackScroller.setFooterView(view); mStackScroller.updateFooter(); @@ -334,15 +280,13 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { @Test public void testUpdateFooter_remoteInput() { setBarStateForTest(StatusBarState.SHADE); - ArrayList<NotificationEntry> entries = new ArrayList<>(); - entries.add(new NotificationEntryBuilder().build()); - addEntriesToEntryManager(entries); ExpandableNotificationRow row = mock(ExpandableNotificationRow.class); when(row.canViewBeDismissed()).thenReturn(true); when(mStackScroller.getChildCount()).thenReturn(1); when(mStackScroller.getChildAt(anyInt())).thenReturn(row); when(mRemoteInputController.isRemoteInputActive()).thenReturn(true); + when(mStackScrollLayoutController.hasActiveNotifications()).thenReturn(true); FooterView view = mock(FooterView.class); mStackScroller.setFooterView(view); @@ -354,14 +298,11 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { public void testUpdateFooter_oneClearableNotification() { setBarStateForTest(StatusBarState.SHADE); - ArrayList<NotificationEntry> entries = new ArrayList<>(); - entries.add(new NotificationEntryBuilder().build()); - addEntriesToEntryManager(entries); - ExpandableNotificationRow row = mock(ExpandableNotificationRow.class); when(row.canViewBeDismissed()).thenReturn(true); when(mStackScroller.getChildCount()).thenReturn(1); when(mStackScroller.getChildAt(anyInt())).thenReturn(row); + when(mStackScrollLayoutController.hasActiveNotifications()).thenReturn(true); FooterView view = mock(FooterView.class); mStackScroller.setFooterView(view); @@ -373,9 +314,11 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { public void testUpdateFooter_oneNonClearableNotification() { setBarStateForTest(StatusBarState.SHADE); - ArrayList<NotificationEntry> entries = new ArrayList<>(); - entries.add(new NotificationEntryBuilder().build()); - addEntriesToEntryManager(entries); + ExpandableNotificationRow row = mock(ExpandableNotificationRow.class); + when(row.canViewBeDismissed()).thenReturn(false); + when(mStackScroller.getChildCount()).thenReturn(1); + when(mStackScroller.getChildAt(anyInt())).thenReturn(row); + when(mStackScrollLayoutController.hasActiveNotifications()).thenReturn(true); FooterView view = mock(FooterView.class); mStackScroller.setFooterView(view); @@ -508,10 +451,4 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { // rather than the mock because the spy just coppied the anonymous inner /shruggie. mStackScroller.setStatusBarState(state); } - - private void addEntriesToEntryManager(List<NotificationEntry> entries) { - for (NotificationEntry e : entries) { - mEntryManager.addActiveNotificationForTest(e); - } - } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollerControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollerControllerTest.java index ef11f81971b3..60d6c530998a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollerControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollerControllerTest.java @@ -37,6 +37,7 @@ import androidx.test.filters.SmallTest; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto; +import com.android.internal.statusbar.IStatusBarService; import com.android.systemui.SysuiTestCase; import com.android.systemui.colorextraction.SysuiColorExtractor; import com.android.systemui.media.KeyguardMediaController; @@ -44,10 +45,14 @@ import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin; import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.OnMenuEventListener; import com.android.systemui.plugins.statusbar.StatusBarStateController; +import com.android.systemui.statusbar.FeatureFlags; import com.android.systemui.statusbar.NotificationLockscreenUserManager; import com.android.systemui.statusbar.NotificationLockscreenUserManager.UserChangedListener; import com.android.systemui.statusbar.SysuiStatusBarStateController; import com.android.systemui.statusbar.notification.DynamicPrivacyController; +import com.android.systemui.statusbar.notification.NotificationEntryManager; +import com.android.systemui.statusbar.notification.collection.NotifCollection; +import com.android.systemui.statusbar.notification.collection.NotifPipeline; import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy; import com.android.systemui.statusbar.notification.collection.render.SectionHeaderController; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; @@ -101,9 +106,14 @@ public class NotificationStackScrollerControllerTest extends SysuiTestCase { @Mock private ScrimController mScrimController; @Mock private NotificationGroupManagerLegacy mLegacyGroupManager; @Mock private SectionHeaderController mSilentHeaderController; + @Mock private FeatureFlags mFeatureFlags; + @Mock private NotifPipeline mNotifPipeline; + @Mock private NotifCollection mNotifCollection; + @Mock private NotificationEntryManager mEntryManager; + @Mock private IStatusBarService mIStatusBarService; @Captor - ArgumentCaptor<StatusBarStateController.StateListener> mStateListenerArgumentCaptor; + private ArgumentCaptor<StatusBarStateController.StateListener> mStateListenerArgumentCaptor; private NotificationStackScrollLayoutController mController; @@ -112,6 +122,7 @@ public class NotificationStackScrollerControllerTest extends SysuiTestCase { MockitoAnnotations.initMocks(this); when(mNotificationSwipeHelperBuilder.build()).thenReturn(mNotificationSwipeHelper); + when(mFeatureFlags.isNewNotifPipelineRenderingEnabled()).thenReturn(false); mController = new NotificationStackScrollLayoutController( true, @@ -136,7 +147,12 @@ public class NotificationStackScrollerControllerTest extends SysuiTestCase { mScrimController, mLegacyGroupManager, mLegacyGroupManager, - mSilentHeaderController + mSilentHeaderController, + mFeatureFlags, + mNotifPipeline, + mNotifCollection, + mEntryManager, + mIStatusBarService ); when(mNotificationStackScrollLayout.isAttachedToWindow()).thenReturn(true); @@ -236,7 +252,6 @@ public class NotificationStackScrollerControllerTest extends SysuiTestCase { UserChangedListener changedListener = userChangedCaptor.getValue(); changedListener.onUserChanged(0); - verify(mNotificationStackScrollLayout).setCurrentUserid(0); verify(mNotificationStackScrollLayout).updateSensitiveness(false, true); } |