Merge changes Ifcf66d9e,I9709e3f6

* changes:
  Move DynamicPrivacyController from NSSL
  Move NotifEntryMan and NotifPipeline from NSSL
This commit is contained in:
TreeHugger Robot
2020-09-11 02:17:23 +00:00
committed by Android (Google) Code Review
6 changed files with 239 additions and 256 deletions

View File

@@ -516,6 +516,7 @@ public class NotificationRemoteInputManager implements Dumpable {
return mLifetimeExtenders; return mLifetimeExtenders;
} }
@Nullable
public RemoteInputController getController() { public RemoteInputController getController() {
return mRemoteInputController; return mRemoteInputController;
} }

View File

@@ -65,14 +65,12 @@ class ShadeViewManager constructor(
return root return root
} }
private fun buildNotifNode(entry: ListEntry, parent: NodeSpec): NodeSpec { private fun buildNotifNode(entry: ListEntry, parent: NodeSpec): NodeSpec = when (entry) {
return when (entry) {
is NotificationEntry -> NodeSpecImpl(parent, viewBarn.requireView(entry)) is NotificationEntry -> NodeSpecImpl(parent, viewBarn.requireView(entry))
is GroupEntry -> NodeSpecImpl(parent, viewBarn.requireView(checkNotNull(entry.summary))) is GroupEntry -> NodeSpecImpl(parent, viewBarn.requireView(checkNotNull(entry.summary)))
.apply { entry.children.forEach { children.add(buildNotifNode(it, this)) } } .apply { entry.children.forEach { children.add(buildNotifNode(it, this)) } }
else -> throw RuntimeException("Unexpected entry: $entry") else -> throw RuntimeException("Unexpected entry: $entry")
} }
}
} }
class ShadeViewManagerFactory @Inject constructor( class ShadeViewManagerFactory @Inject constructor(

View File

@@ -16,14 +16,10 @@
package com.android.systemui.statusbar.notification.stack; 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.ActivityLaunchAnimator.ExpandAnimationParameters;
import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManagerKt.BUCKET_SILENT; 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.StackScrollAlgorithm.ANCHOR_SCROLLING;
import static com.android.systemui.statusbar.notification.stack.StackStateAnimator.ANIMATION_DURATION_SWIPE; 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 com.android.systemui.util.InjectionInflationController.VIEW_CONTEXT;
import static java.lang.annotation.RetentionPolicy.SOURCE; import static java.lang.annotation.RetentionPolicy.SOURCE;
@@ -49,10 +45,8 @@ import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode; import android.graphics.PorterDuffXfermode;
import android.graphics.Rect; import android.graphics.Rect;
import android.os.Bundle; import android.os.Bundle;
import android.os.ServiceManager;
import android.os.UserHandle; import android.os.UserHandle;
import android.provider.Settings; import android.provider.Settings;
import android.service.notification.NotificationListenerService;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.util.DisplayMetrics; import android.util.DisplayMetrics;
import android.util.Log; 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.UiEvent;
import com.android.internal.logging.UiEventLogger; import com.android.internal.logging.UiEventLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent; 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.keyguard.KeyguardSliceView;
import com.android.settingslib.Utils; import com.android.settingslib.Utils;
import com.android.systemui.Dependency; import com.android.systemui.Dependency;
@@ -96,27 +88,20 @@ import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.DragDownHelper.DragDownCallback; import com.android.systemui.statusbar.DragDownHelper.DragDownCallback;
import com.android.systemui.statusbar.EmptyShadeView; import com.android.systemui.statusbar.EmptyShadeView;
import com.android.systemui.statusbar.FeatureFlags;
import com.android.systemui.statusbar.NotificationRemoteInputManager; import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.NotificationShelf; import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.NotificationShelfController; import com.android.systemui.statusbar.NotificationShelfController;
import com.android.systemui.statusbar.RemoteInputController;
import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.SysuiStatusBarStateController; 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.FakeShadowView;
import com.android.systemui.statusbar.notification.ForegroundServiceDismissalFeatureController; import com.android.systemui.statusbar.notification.ForegroundServiceDismissalFeatureController;
import com.android.systemui.statusbar.notification.NotificationActivityStarter; 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.NotificationUtils;
import com.android.systemui.statusbar.notification.ShadeViewRefactor; import com.android.systemui.statusbar.notification.ShadeViewRefactor;
import com.android.systemui.statusbar.notification.ShadeViewRefactor.RefactorComponent; 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.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager; 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.GroupExpansionManager;
import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager; import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
import com.android.systemui.statusbar.notification.logging.NotificationLogger; import com.android.systemui.statusbar.notification.logging.NotificationLogger;
@@ -136,7 +121,6 @@ import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.policy.HeadsUpUtil; import com.android.systemui.statusbar.policy.HeadsUpUtil;
import com.android.systemui.statusbar.policy.ScrollAdapter; import com.android.systemui.statusbar.policy.ScrollAdapter;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.util.Assert; import com.android.systemui.util.Assert;
import java.io.FileDescriptor; import java.io.FileDescriptor;
@@ -173,7 +157,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
*/ */
private static final int DISTANCE_BETWEEN_ADJACENT_SECTIONS_PX = 1; private static final int DISTANCE_BETWEEN_ADJACENT_SECTIONS_PX = 1;
private KeyguardBypassEnabledProvider mKeyguardBypassEnabledProvider; private KeyguardBypassEnabledProvider mKeyguardBypassEnabledProvider;
private final DynamicPrivacyController mDynamicPrivacyController;
private final SysuiStatusBarStateController mStatusbarStateController; private final SysuiStatusBarStateController mStatusbarStateController;
private ExpandHelper mExpandHelper; private ExpandHelper mExpandHelper;
@@ -225,7 +208,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
private int mBottomMargin; private int mBottomMargin;
private int mBottomInset = 0; private int mBottomInset = 0;
private float mQsExpansionFraction; private float mQsExpansionFraction;
private int mCurrentUserId;
/** /**
* The algorithm which calculates the properties for our children * The algorithm which calculates the properties for our children
@@ -468,12 +450,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
private int mHeadsUpInset; private int mHeadsUpInset;
private HeadsUpAppearanceController mHeadsUpAppearanceController; private HeadsUpAppearanceController mHeadsUpAppearanceController;
private final Rect mTmpRect = new Rect(); private final Rect mTmpRect = new Rect();
private final FeatureFlags mFeatureFlags; private DismissAllAnimationListener mDismissAllAnimationListener;
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));
@VisibleForTesting @VisibleForTesting
protected final MetricsLogger mMetricsLogger = Dependency.get(MetricsLogger.class); protected final MetricsLogger mMetricsLogger = Dependency.get(MetricsLogger.class);
protected final UiEventLogger mUiEventLogger; protected final UiEventLogger mUiEventLogger;
@@ -553,18 +530,13 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
@Named(VIEW_CONTEXT) Context context, @Named(VIEW_CONTEXT) Context context,
AttributeSet attrs, AttributeSet attrs,
NotificationRoundnessManager notificationRoundnessManager, NotificationRoundnessManager notificationRoundnessManager,
DynamicPrivacyController dynamicPrivacyController,
SysuiStatusBarStateController statusbarStateController, SysuiStatusBarStateController statusbarStateController,
NotificationSectionsManager notificationSectionsManager, NotificationSectionsManager notificationSectionsManager,
ForegroundServiceSectionController fgsSectionController, ForegroundServiceSectionController fgsSectionController,
ForegroundServiceDismissalFeatureController fgsFeatureController, ForegroundServiceDismissalFeatureController fgsFeatureController,
FeatureFlags featureFlags,
NotifPipeline notifPipeline,
NotificationEntryManager entryManager,
NotifCollection notifCollection,
UiEventLogger uiEventLogger,
GroupMembershipManager groupMembershipManager, GroupMembershipManager groupMembershipManager,
GroupExpansionManager groupExpansionManager GroupExpansionManager groupExpansionManager,
UiEventLogger uiEventLogger
) { ) {
super(context, attrs, 0, 0); super(context, attrs, 0, 0);
Resources res = getResources(); Resources res = getResources();
@@ -576,7 +548,8 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
mSectionsManager.initialize(this, LayoutInflater.from(context)); mSectionsManager.initialize(this, LayoutInflater.from(context));
mSectionsManager.setOnClearSilentNotifsClickListener(v -> { mSectionsManager.setOnClearSilentNotifsClickListener(v -> {
// Leave the shade open if there will be other notifs left over to clear // Leave the shade open if there will be other notifs left over to clear
final boolean closeShade = !hasActiveClearableNotifications(ROWS_HIGH_PRIORITY); final boolean closeShade =
!mController.hasActiveClearableNotifications(ROWS_HIGH_PRIORITY);
clearNotifications(ROWS_GENTLE, closeShade); clearNotifications(ROWS_GENTLE, closeShade);
}); });
mSections = mSectionsManager.createSectionsForBuckets(); mSections = mSectionsManager.createSectionsForBuckets();
@@ -613,37 +586,8 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
mDebugPaint.setTextSize(25f); mDebugPaint.setTextSize(25f);
} }
mClearAllEnabled = res.getBoolean(R.bool.config_enableNotificationsClearAll); 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; mGroupMembershipManager = groupMembershipManager;
mGroupExpansionManager = groupExpansionManager; mGroupExpansionManager = groupExpansionManager;
mDynamicPrivacyController = dynamicPrivacyController;
mStatusbarStateController = statusbarStateController; mStatusbarStateController = statusbarStateController;
initializeForegroundServiceSection(fgsFeatureController); initializeForegroundServiceSection(fgsFeatureController);
mUiEventLogger = uiEventLogger; mUiEventLogger = uiEventLogger;
@@ -707,10 +651,13 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
if (mFooterView == null) { if (mFooterView == null) {
return; return;
} }
boolean showDismissView = mClearAllEnabled && hasActiveClearableNotifications(ROWS_ALL); // TODO: move this logic to controller, which will invoke updateFooterView directly
boolean showFooterView = (showDismissView || hasActiveNotifications()) boolean showDismissView = mClearAllEnabled &&
mController.hasActiveClearableNotifications(ROWS_ALL);
RemoteInputController remoteInputController = mRemoteInputManager.getController();
boolean showFooterView = (showDismissView || mController.hasActiveNotifications())
&& mStatusBarState != StatusBarState.KEYGUARD && mStatusBarState != StatusBarState.KEYGUARD
&& !mRemoteInputManager.getController().isRemoteInputActive(); && (remoteInputController == null || !remoteInputController.isRemoteInputActive());
boolean showHistory = Settings.Secure.getIntForUser(mContext.getContentResolver(), boolean showHistory = Settings.Secure.getIntForUser(mContext.getContentResolver(),
Settings.Secure.NOTIFICATION_HISTORY_ENABLED, 0, UserHandle.USER_CURRENT) == 1; Settings.Secure.NOTIFICATION_HISTORY_ENABLED, 0, UserHandle.USER_CURRENT) == 1;
@@ -721,22 +668,8 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
* Return whether there are any clearable notifications * Return whether there are any clearable notifications
*/ */
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW) @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
public boolean hasActiveClearableNotifications(@SelectedRows int selection) { boolean hasActiveClearableNotifications(@SelectedRows int selection) {
if (mDynamicPrivacyController.isInLockedDownShade()) { return mController.hasActiveClearableNotifications(selection);
return false;
}
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
if (!(child instanceof ExpandableNotificationRow)) {
continue;
}
final ExpandableNotificationRow row = (ExpandableNotificationRow) child;
if (row.canViewBeDismissed() && matchesSelection(row, selection)) {
return true;
}
}
return false;
} }
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW) @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
@@ -5292,8 +5225,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
updateFooter(); updateFooter();
requestChildrenUpdate(); requestChildrenUpdate();
onUpdateRowStates(); onUpdateRowStates();
mEntryManager.updateNotifications("StatusBar state changed");
updateVisibility(); updateVisibility();
} }
@@ -5697,10 +5628,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
return mController; return mController;
} }
void setCurrentUserid(int userId) {
mCurrentUserId = userId;
}
void addSwipedOutView(View v) { void addSwipedOutView(View v) {
mSwipedOutViews.add(v); mSwipedOutViews.add(v);
} }
@@ -5774,6 +5701,14 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
return mCheckForLeavebehind; 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 * A listener that is notified when the empty space below the notifications is clicked on
*/ */
@@ -5852,7 +5787,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
mSwipeHelper.resetExposedMenuView(animate, force); mSwipeHelper.resetExposedMenuView(animate, force);
} }
private static boolean matchesSelection( static boolean matchesSelection(
ExpandableNotificationRow row, ExpandableNotificationRow row,
@SelectedRows int selection) { @SelectedRows int selection) {
switch (selection) { switch (selection) {
@@ -6127,7 +6062,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
// --------------------- NotificationEntryManager/NotifPipeline methods ------------------------ // --------------------- 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 // 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. // notification. Since it's not clearable we should snap it back.
if (entry.rowExists() && !entry.getSbn().isClearable()) { if (entry.rowExists() && !entry.getSbn().isClearable()) {
@@ -6135,71 +6070,15 @@ 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. * Called after the animations for a "clear all notifications" action has ended.
*/ */
private void onDismissAllAnimationsEnd( private void onDismissAllAnimationsEnd(
List<ExpandableNotificationRow> viewsToRemove, List<ExpandableNotificationRow> viewsToRemove,
@SelectedRows int selectedRows) { @SelectedRows int selectedRows) {
if (mFeatureFlags.isNewNotifPipelineRenderingEnabled()) { if (mDismissAllAnimationListener != null) {
if (selectedRows == ROWS_ALL) { mDismissAllAnimationListener.onAnimationEnd(viewsToRemove, selectedRows);
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) {
}
}
}
}
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) { public void setKeyguardMediaControllorVisible(boolean keyguardMediaControllorVisible) {
@@ -6218,7 +6097,8 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
/* Only ever called as a consequence of a lockscreen expansion gesture. */ /* Only ever called as a consequence of a lockscreen expansion gesture. */
@Override @Override
public boolean onDraggedDown(View startingChild, int dragLengthY) { public boolean onDraggedDown(View startingChild, int dragLengthY) {
boolean canDragDown = hasActiveNotifications() || mKeyguardMediaControllorVisible; boolean canDragDown =
mController.hasActiveNotifications() || mKeyguardMediaControllorVisible;
if (mStatusBarState == StatusBarState.KEYGUARD && canDragDown) { if (mStatusBarState == StatusBarState.KEYGUARD && canDragDown) {
mLockscreenGestureLogger.write( mLockscreenGestureLogger.write(
MetricsEvent.ACTION_LS_SHADE, MetricsEvent.ACTION_LS_SHADE,
@@ -6236,7 +6116,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
} }
return true; return true;
} else if (mDynamicPrivacyController.isInLockedDownShade()) { } else if (mController.isInLockedDownShade()) {
mStatusbarStateController.setLeaveOpenOnKeyguardHide(true); mStatusbarStateController.setLeaveOpenOnKeyguardHide(true);
mStatusBar.dismissKeyguardThenExecute(() -> false /* dismissAction */, mStatusBar.dismissKeyguardThenExecute(() -> false /* dismissAction */,
null /* cancelRunnable */, false /* afterKeyguardGone */); null /* cancelRunnable */, false /* afterKeyguardGone */);
@@ -6280,7 +6160,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
if (isDragDownAnywhereEnabled()) { if (isDragDownAnywhereEnabled()) {
return true; return true;
} }
if (mDynamicPrivacyController.isInLockedDownShade()) { if (mController.isInLockedDownShade()) {
if (view == null) { if (view == null) {
// Dragging down is allowed in general // Dragging down is allowed in general
return true; return true;
@@ -6424,7 +6304,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
/** Enum for selecting some or all notification rows (does not included non-notif views). */ /** Enum for selecting some or all notification rows (does not included non-notif views). */
@Retention(SOURCE) @Retention(SOURCE)
@IntDef({ROWS_ALL, ROWS_HIGH_PRIORITY, ROWS_GENTLE}) @IntDef({ROWS_ALL, ROWS_HIGH_PRIORITY, ROWS_GENTLE})
public @interface SelectedRows {} @interface SelectedRows {}
/** All rows representing notifs. */ /** All rows representing notifs. */
public static final int ROWS_ALL = 0; public static final int ROWS_ALL = 0;
/** Only rows where entry.isHighPriority() is true. */ /** Only rows where entry.isHighPriority() is true. */
@@ -6466,4 +6346,9 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
interface KeyguardBypassEnabledProvider { interface KeyguardBypassEnabledProvider {
boolean getBypassEnabled(); boolean getBypassEnabled();
} }
interface DismissAllAnimationListener {
void onAnimationEnd(
List<ExpandableNotificationRow> viewsToRemove, @SelectedRows int selectedRows);
}
} }

View File

@@ -16,17 +16,28 @@
package com.android.systemui.statusbar.notification.stack; 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.Dependency.ALLOW_NOTIFICATION_LONG_PRESS_NAME;
import static com.android.systemui.statusbar.StatusBarState.KEYGUARD; 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_GENTLE;
import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.ROWS_HIGH_PRIORITY; 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.content.res.Resources;
import android.graphics.Point; import android.graphics.Point;
import android.graphics.PointF; import android.graphics.PointF;
import android.provider.Settings; import android.provider.Settings;
import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification; import android.service.notification.StatusBarNotification;
import android.util.Log; import android.util.Log;
import android.util.Pair;
import android.view.Display; import android.view.Display;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.View; import android.view.View;
@@ -37,6 +48,8 @@ import android.widget.FrameLayout;
import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent; 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.ExpandHelper;
import com.android.systemui.Gefingerpoken; import com.android.systemui.Gefingerpoken;
import com.android.systemui.R; 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.NotificationMenuRowPlugin.OnMenuEventListener;
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper; import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
import com.android.systemui.plugins.statusbar.StatusBarStateController; 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;
import com.android.systemui.statusbar.NotificationLockscreenUserManager.UserChangedListener; import com.android.systemui.statusbar.NotificationLockscreenUserManager.UserChangedListener;
import com.android.systemui.statusbar.NotificationShelfController; import com.android.systemui.statusbar.NotificationShelfController;
@@ -58,10 +72,17 @@ import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.notification.ActivityLaunchAnimator; import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
import com.android.systemui.statusbar.notification.DynamicPrivacyController; import com.android.systemui.statusbar.notification.DynamicPrivacyController;
import com.android.systemui.statusbar.notification.NotificationActivityStarter; 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.ShadeViewRefactor;
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.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy; 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.NotificationGroup;
import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy.OnGroupChangeListener; 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.GroupExpansionManager;
import com.android.systemui.statusbar.notification.collection.render.SectionHeaderController; import com.android.systemui.statusbar.notification.collection.render.SectionHeaderController;
import com.android.systemui.statusbar.notification.dagger.SilentHeader; import com.android.systemui.statusbar.notification.dagger.SilentHeader;
@@ -86,6 +107,8 @@ import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
import com.android.systemui.statusbar.policy.ZenModeController; import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.tuner.TunerService; import com.android.systemui.tuner.TunerService;
import java.util.ArrayList;
import java.util.List;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
import javax.inject.Inject; import javax.inject.Inject;
@@ -114,6 +137,11 @@ public class NotificationStackScrollLayoutController {
private final Resources mResources; private final Resources mResources;
private final NotificationSwipeHelper.Builder mNotificationSwipeHelperBuilder; private final NotificationSwipeHelper.Builder mNotificationSwipeHelperBuilder;
private final ScrimController mScrimController; 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 KeyguardMediaController mKeyguardMediaController;
private final SysuiStatusBarStateController mStatusBarStateController; private final SysuiStatusBarStateController mStatusBarStateController;
private final KeyguardBypassController mKeyguardBypassController; private final KeyguardBypassController mKeyguardBypassController;
@@ -211,13 +239,13 @@ public class NotificationStackScrollLayoutController {
mView.updateSensitiveness(mStatusBarStateController.goingToFullShade(), mView.updateSensitiveness(mStatusBarStateController.goingToFullShade(),
mLockscreenUserManager.isAnyProfilePublicMode()); mLockscreenUserManager.isAnyProfilePublicMode());
mView.onStatePostChange(mStatusBarStateController.fromShadeLocked()); mView.onStatePostChange(mStatusBarStateController.fromShadeLocked());
mNotificationEntryManager.updateNotifications("StatusBar state changed");
} }
}; };
private final UserChangedListener mLockscreenUserChangeListener = new UserChangedListener() { private final UserChangedListener mLockscreenUserChangeListener = new UserChangedListener() {
@Override @Override
public void onUserChanged(int userId) { public void onUserChanged(int userId) {
mView.setCurrentUserid(userId);
mView.updateSensitiveness(false, mLockscreenUserManager.isAnyProfilePublicMode()); mView.updateSensitiveness(false, mLockscreenUserManager.isAnyProfilePublicMode());
} }
}; };
@@ -525,7 +553,12 @@ public class NotificationStackScrollLayoutController {
ScrimController scrimController, ScrimController scrimController,
NotificationGroupManagerLegacy legacyGroupManager, NotificationGroupManagerLegacy legacyGroupManager,
GroupExpansionManager groupManager, GroupExpansionManager groupManager,
@SilentHeader SectionHeaderController silentHeaderController) { @SilentHeader SectionHeaderController silentHeaderController,
FeatureFlags featureFlags,
NotifPipeline notifPipeline,
NotifCollection notifCollection,
NotificationEntryManager notificationEntryManager,
IStatusBarService iStatusBarService) {
mAllowLongPress = allowLongPress; mAllowLongPress = allowLongPress;
mNotificationGutsManager = notificationGutsManager; mNotificationGutsManager = notificationGutsManager;
mHeadsUpManager = headsUpManager; mHeadsUpManager = headsUpManager;
@@ -549,7 +582,6 @@ public class NotificationStackScrollLayoutController {
groupManager.registerGroupExpansionChangeListener((changedRow, expanded) -> { groupManager.registerGroupExpansionChangeListener((changedRow, expanded) -> {
mView.onGroupExpandChanged(changedRow, expanded); mView.onGroupExpandChanged(changedRow, expanded);
}); });
legacyGroupManager.registerGroupChangeListener(new OnGroupChangeListener() { legacyGroupManager.registerGroupChangeListener(new OnGroupChangeListener() {
@Override @Override
public void onGroupCreatedFromChildren(NotificationGroup group) { public void onGroupCreatedFromChildren(NotificationGroup group) {
@@ -562,6 +594,11 @@ public class NotificationStackScrollLayoutController {
} }
}); });
mSilentHeaderController = silentHeaderController; mSilentHeaderController = silentHeaderController;
mFeatureFlags = featureFlags;
mNotifPipeline = notifPipeline;
mNotifCollection = notifCollection;
mNotificationEntryManager = notificationEntryManager;
mIStatusBarService = iStatusBarService;
} }
public void attach(NotificationStackScrollLayout view) { public void attach(NotificationStackScrollLayout view) {
@@ -569,6 +606,7 @@ public class NotificationStackScrollLayoutController {
mView.setController(this); mView.setController(this);
mView.setTouchHandler(new TouchHandler()); mView.setTouchHandler(new TouchHandler());
mView.setStatusBar(mStatusBar); mView.setStatusBar(mStatusBar);
mView.setDismissAllAnimationListener(this::onAnimationEnd);
mSwipeHelper = mNotificationSwipeHelperBuilder mSwipeHelper = mNotificationSwipeHelperBuilder
.setSwipeDirection(SwipeHelper.X) .setSwipeDirection(SwipeHelper.X)
@@ -576,6 +614,22 @@ public class NotificationStackScrollLayoutController {
.setOnMenuEventListener(mMenuEventListener) .setOnMenuEventListener(mMenuEventListener)
.build(); .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, mView.initView(mView.getContext(), mKeyguardBypassController::getBypassEnabled,
mSwipeHelper); mSwipeHelper);
@@ -587,7 +641,6 @@ public class NotificationStackScrollLayoutController {
mScrimController.setScrimBehindChangeRunnable(mView::updateBackgroundDimming); mScrimController.setScrimBehindChangeRunnable(mView::updateBackgroundDimming);
mLockscreenUserManager.addUserChangedListener(mLockscreenUserChangeListener); mLockscreenUserManager.addUserChangedListener(mLockscreenUserChangeListener);
mView.setCurrentUserid(mLockscreenUserManager.getCurrentUserId());
mFadeNotificationsOnDismiss = // TODO: this should probably be injected directly mFadeNotificationsOnDismiss = // TODO: this should probably be injected directly
mResources.getBoolean(R.bool.config_fadeNotificationsOnDismiss); mResources.getBoolean(R.bool.config_fadeNotificationsOnDismiss);
@@ -597,12 +650,19 @@ public class NotificationStackScrollLayoutController {
mTunerService.addTunable( mTunerService.addTunable(
(key, newValue) -> { (key, newValue) -> {
if (key.equals(Settings.Secure.NOTIFICATION_DISMISS_RTL)) { switch (key) {
case Settings.Secure.NOTIFICATION_DISMISS_RTL:
mView.updateDismissRtlSetting("1".equals(newValue)); mView.updateDismissRtlSetting("1".equals(newValue));
} else if (key.equals(Settings.Secure.NOTIFICATION_HISTORY_ENABLED)) { break;
case Settings.Secure.NOTIFICATION_HISTORY_ENABLED:
updateFooter(); updateFooter();
break;
case HIGH_PRIORITY:
mView.setHighPriorityBeforeSpeedBump("1".equals(newValue));
break;
} }
}, },
HIGH_PRIORITY,
Settings.Secure.NOTIFICATION_DISMISS_RTL, Settings.Secure.NOTIFICATION_DISMISS_RTL,
Settings.Secure.NOTIFICATION_HISTORY_ENABLED); Settings.Secure.NOTIFICATION_HISTORY_ENABLED);
@@ -684,12 +744,12 @@ public class NotificationStackScrollLayoutController {
} }
public void setOverscrollTopChangedListener( public void setOverscrollTopChangedListener(
NotificationStackScrollLayout.OnOverscrollTopChangedListener listener) { OnOverscrollTopChangedListener listener) {
mView.setOverscrollTopChangedListener(listener); mView.setOverscrollTopChangedListener(listener);
} }
public void setOnEmptySpaceClickListener( public void setOnEmptySpaceClickListener(
NotificationStackScrollLayout.OnEmptySpaceClickListener listener) { OnEmptySpaceClickListener listener) {
mView.setOnEmptySpaceClickListener(listener); mView.setOnEmptySpaceClickListener(listener);
} }
@@ -1007,9 +1067,26 @@ public class NotificationStackScrollLayoutController {
mView.setPulsing(pulsing, animatePulse); mView.setPulsing(pulsing, animatePulse);
} }
public boolean hasActiveClearableNotifications( /**
@NotificationStackScrollLayout.SelectedRows int selection) { * Return whether there are any clearable notifications
return mView.hasActiveClearableNotifications(selection); */
public boolean hasActiveClearableNotifications(@SelectedRows int selection) {
if (mDynamicPrivacyController.isInLockedDownShade()) {
return false;
}
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
if (!(child instanceof ExpandableNotificationRow)) {
continue;
}
final ExpandableNotificationRow row = (ExpandableNotificationRow) child;
if (row.canViewBeDismissed() &&
NotificationStackScrollLayout.matchesSelection(row, selection)) {
return true;
}
}
return false;
} }
/** /**
@@ -1120,6 +1197,29 @@ public class NotificationStackScrollLayoutController {
mView.resetCheckSnoozeLeavebehind(); 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) { public void closeControlsIfOutsideTouch(MotionEvent ev) {
NotificationGuts guts = mNotificationGutsManager.getExposedGuts(); NotificationGuts guts = mNotificationGutsManager.getExposedGuts();
NotificationMenuRowPlugin menuRow = mSwipeHelper.getCurrentMenuRow(); NotificationMenuRowPlugin menuRow = mSwipeHelper.getCurrentMenuRow();
@@ -1148,6 +1248,51 @@ public class NotificationStackScrollLayoutController {
mView.clearNotifications(ROWS_GENTLE, closeShade); 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) {
}
}
}
}
public boolean isInLockedDownShade() {
return mDynamicPrivacyController.isInLockedDownShade();
}
private class NotificationListContainerImpl implements NotificationListContainer { private class NotificationListContainerImpl implements NotificationListContainer {
@Override @Override

View File

@@ -16,6 +16,8 @@ package com.android.systemui.statusbar.notification.stack;
import static android.provider.Settings.Secure.NOTIFICATION_HISTORY_ENABLED; import static android.provider.Settings.Secure.NOTIFICATION_HISTORY_ENABLED;
import static android.provider.Settings.Secure.NOTIFICATION_NEW_INTERRUPTION_MODEL; import static android.provider.Settings.Secure.NOTIFICATION_NEW_INTERRUPTION_MODEL;
import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.ROWS_ALL;
import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNotNull; import static junit.framework.Assert.assertNotNull;
@@ -43,44 +45,26 @@ import androidx.test.filters.SmallTest;
import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.testing.UiEventLoggerFake; import com.android.internal.logging.testing.UiEventLoggerFake;
import com.android.internal.statusbar.IStatusBarService;
import com.android.systemui.ExpandHelper; import com.android.systemui.ExpandHelper;
import com.android.systemui.R; import com.android.systemui.R;
import com.android.systemui.SysuiTestCase; import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.EmptyShadeView; 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.NotificationRemoteInputManager;
import com.android.systemui.statusbar.NotificationShelf; import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.NotificationShelfController; import com.android.systemui.statusbar.NotificationShelfController;
import com.android.systemui.statusbar.RemoteInputController; import com.android.systemui.statusbar.RemoteInputController;
import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.SysuiStatusBarStateController; 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.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.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.NotificationGroupManagerLegacy;
import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager; 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.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.FooterView; import com.android.systemui.statusbar.notification.row.FooterView;
import com.android.systemui.statusbar.notification.row.NotificationBlockingHelperManager; import com.android.systemui.statusbar.notification.row.NotificationBlockingHelperManager;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.KeyguardBypassEnabledProvider; 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.ShadeController;
import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.util.leak.LeakDetector;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
@@ -92,9 +76,6 @@ import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule; import org.mockito.junit.MockitoRule;
import java.util.ArrayList;
import java.util.List;
/** /**
* Tests for {@link NotificationStackScrollLayout}. * Tests for {@link NotificationStackScrollLayout}.
*/ */
@@ -109,7 +90,6 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase {
@Rule public MockitoRule mockito = MockitoJUnit.rule(); @Rule public MockitoRule mockito = MockitoJUnit.rule();
@Mock private StatusBar mBar; @Mock private StatusBar mBar;
@Mock private SysuiStatusBarStateController mBarState; @Mock private SysuiStatusBarStateController mBarState;
@Mock private HeadsUpManagerPhone mHeadsUpManager;
@Mock private NotificationBlockingHelperManager mBlockingHelperManager; @Mock private NotificationBlockingHelperManager mBlockingHelperManager;
@Mock private NotificationGroupManagerLegacy mGroupMembershipManger; @Mock private NotificationGroupManagerLegacy mGroupMembershipManger;
@Mock private NotificationGroupManagerLegacy mGroupExpansionManager; @Mock private NotificationGroupManagerLegacy mGroupExpansionManager;
@@ -122,11 +102,9 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase {
@Mock private KeyguardBypassEnabledProvider mKeyguardBypassEnabledProvider; @Mock private KeyguardBypassEnabledProvider mKeyguardBypassEnabledProvider;
@Mock private NotificationSectionsManager mNotificationSectionsManager; @Mock private NotificationSectionsManager mNotificationSectionsManager;
@Mock private NotificationSection mNotificationSection; @Mock private NotificationSection mNotificationSection;
@Mock private FeatureFlags mFeatureFlags;
@Mock private SysuiStatusBarStateController mStatusBarStateController; @Mock private SysuiStatusBarStateController mStatusBarStateController;
@Mock private NotificationSwipeHelper mNotificationSwipeHelper; @Mock private NotificationSwipeHelper mNotificationSwipeHelper;
@Mock NotificationStackScrollLayoutController mStackScrollLayoutController; @Mock private NotificationStackScrollLayoutController mStackScrollLayoutController;
private NotificationEntryManager mEntryManager;
private int mOriginalInterruptionModelSetting; private int mOriginalInterruptionModelSetting;
private UiEventLoggerFake mUiEventLoggerFake = new UiEventLoggerFake(); private UiEventLoggerFake mUiEventLoggerFake = new UiEventLoggerFake();
@@ -154,31 +132,6 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase {
mRemoteInputManager); mRemoteInputManager);
mDependency.injectMockDependency(ShadeController.class); mDependency.injectMockDependency(ShadeController.class);
when(mRemoteInputManager.getController()).thenReturn(mRemoteInputController); 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 = NotificationShelfController notificationShelfController =
mock(NotificationShelfController.class); mock(NotificationShelfController.class);
NotificationShelf notificationShelf = mock(NotificationShelf.class); NotificationShelf notificationShelf = mock(NotificationShelf.class);
@@ -196,18 +149,13 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase {
getContext(), getContext(),
null, null,
mNotificationRoundnessManager, mNotificationRoundnessManager,
mock(DynamicPrivacyController.class),
mStatusBarStateController, mStatusBarStateController,
mNotificationSectionsManager, mNotificationSectionsManager,
mock(ForegroundServiceSectionController.class), mock(ForegroundServiceSectionController.class),
mock(ForegroundServiceDismissalFeatureController.class), mock(ForegroundServiceDismissalFeatureController.class),
mFeatureFlags,
mock(NotifPipeline.class),
mEntryManager,
mock(NotifCollection.class),
mUiEventLoggerFake,
mGroupMembershipManger, mGroupMembershipManger,
mGroupExpansionManager mGroupExpansionManager,
mUiEventLoggerFake
); );
mStackScrollerInternal.initView(getContext(), mKeyguardBypassEnabledProvider, mStackScrollerInternal.initView(getContext(), mKeyguardBypassEnabledProvider,
mNotificationSwipeHelper); mNotificationSwipeHelper);
@@ -216,7 +164,7 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase {
mStackScroller.setStatusBar(mBar); mStackScroller.setStatusBar(mBar);
mStackScroller.setEmptyShadeView(mEmptyShadeView); mStackScroller.setEmptyShadeView(mEmptyShadeView);
when(mStackScrollLayoutController.getNoticationRoundessManager()) when(mStackScrollLayoutController.getNoticationRoundessManager())
.thenReturn(mock(NotificationRoundnessManager.class)); .thenReturn(mNotificationRoundnessManager);
mStackScroller.setController(mStackScrollLayoutController); mStackScroller.setController(mStackScrollLayoutController);
// Stub out functionality that isn't necessary to test. // Stub out functionality that isn't necessary to test.
@@ -323,8 +271,6 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase {
@Test @Test
public void testUpdateFooter_noNotifications() { public void testUpdateFooter_noNotifications() {
setBarStateForTest(StatusBarState.SHADE); setBarStateForTest(StatusBarState.SHADE);
assertEquals(0, mEntryManager.getActiveNotificationsCount());
FooterView view = mock(FooterView.class); FooterView view = mock(FooterView.class);
mStackScroller.setFooterView(view); mStackScroller.setFooterView(view);
mStackScroller.updateFooter(); mStackScroller.updateFooter();
@@ -334,15 +280,15 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase {
@Test @Test
public void testUpdateFooter_remoteInput() { public void testUpdateFooter_remoteInput() {
setBarStateForTest(StatusBarState.SHADE); setBarStateForTest(StatusBarState.SHADE);
ArrayList<NotificationEntry> entries = new ArrayList<>();
entries.add(new NotificationEntryBuilder().build());
addEntriesToEntryManager(entries);
ExpandableNotificationRow row = mock(ExpandableNotificationRow.class); ExpandableNotificationRow row = mock(ExpandableNotificationRow.class);
when(row.canViewBeDismissed()).thenReturn(true); when(row.canViewBeDismissed()).thenReturn(true);
when(mStackScroller.getChildCount()).thenReturn(1); when(mStackScroller.getChildCount()).thenReturn(1);
when(mStackScroller.getChildAt(anyInt())).thenReturn(row); when(mStackScroller.getChildAt(anyInt())).thenReturn(row);
when(mRemoteInputController.isRemoteInputActive()).thenReturn(true); when(mRemoteInputController.isRemoteInputActive()).thenReturn(true);
when(mStackScrollLayoutController.hasActiveClearableNotifications(ROWS_ALL))
.thenReturn(true);
when(mStackScrollLayoutController.hasActiveNotifications()).thenReturn(true);
FooterView view = mock(FooterView.class); FooterView view = mock(FooterView.class);
mStackScroller.setFooterView(view); mStackScroller.setFooterView(view);
@@ -354,14 +300,9 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase {
public void testUpdateFooter_oneClearableNotification() { public void testUpdateFooter_oneClearableNotification() {
setBarStateForTest(StatusBarState.SHADE); setBarStateForTest(StatusBarState.SHADE);
ArrayList<NotificationEntry> entries = new ArrayList<>(); when(mStackScrollLayoutController.hasActiveClearableNotifications(ROWS_ALL))
entries.add(new NotificationEntryBuilder().build()); .thenReturn(true);
addEntriesToEntryManager(entries); when(mStackScrollLayoutController.hasActiveNotifications()).thenReturn(true);
ExpandableNotificationRow row = mock(ExpandableNotificationRow.class);
when(row.canViewBeDismissed()).thenReturn(true);
when(mStackScroller.getChildCount()).thenReturn(1);
when(mStackScroller.getChildAt(anyInt())).thenReturn(row);
FooterView view = mock(FooterView.class); FooterView view = mock(FooterView.class);
mStackScroller.setFooterView(view); mStackScroller.setFooterView(view);
@@ -373,9 +314,13 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase {
public void testUpdateFooter_oneNonClearableNotification() { public void testUpdateFooter_oneNonClearableNotification() {
setBarStateForTest(StatusBarState.SHADE); setBarStateForTest(StatusBarState.SHADE);
ArrayList<NotificationEntry> entries = new ArrayList<>(); ExpandableNotificationRow row = mock(ExpandableNotificationRow.class);
entries.add(new NotificationEntryBuilder().build()); when(row.canViewBeDismissed()).thenReturn(false);
addEntriesToEntryManager(entries); when(mStackScroller.getChildCount()).thenReturn(1);
when(mStackScroller.getChildAt(anyInt())).thenReturn(row);
when(mStackScrollLayoutController.hasActiveNotifications()).thenReturn(true);
when(mStackScrollLayoutController.hasActiveClearableNotifications(ROWS_ALL))
.thenReturn(false);
FooterView view = mock(FooterView.class); FooterView view = mock(FooterView.class);
mStackScroller.setFooterView(view); mStackScroller.setFooterView(view);
@@ -435,7 +380,7 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase {
@Test @Test
public void testClearNotifications_All() { public void testClearNotifications_All() {
mStackScroller.clearNotifications(NotificationStackScrollLayout.ROWS_ALL, true); mStackScroller.clearNotifications(ROWS_ALL, true);
assertEquals(1, mUiEventLoggerFake.numLogs()); assertEquals(1, mUiEventLoggerFake.numLogs());
assertEquals(NotificationStackScrollLayout.NotificationPanelEvent assertEquals(NotificationStackScrollLayout.NotificationPanelEvent
.DISMISS_ALL_NOTIFICATIONS_PANEL.getId(), mUiEventLoggerFake.eventId(0)); .DISMISS_ALL_NOTIFICATIONS_PANEL.getId(), mUiEventLoggerFake.eventId(0));
@@ -508,10 +453,4 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase {
// rather than the mock because the spy just coppied the anonymous inner /shruggie. // rather than the mock because the spy just coppied the anonymous inner /shruggie.
mStackScroller.setStatusBarState(state); mStackScroller.setStatusBarState(state);
} }
private void addEntriesToEntryManager(List<NotificationEntry> entries) {
for (NotificationEntry e : entries) {
mEntryManager.addActiveNotificationForTest(e);
}
}
} }

View File

@@ -37,6 +37,7 @@ import androidx.test.filters.SmallTest;
import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto; import com.android.internal.logging.nano.MetricsProto;
import com.android.internal.statusbar.IStatusBarService;
import com.android.systemui.SysuiTestCase; import com.android.systemui.SysuiTestCase;
import com.android.systemui.colorextraction.SysuiColorExtractor; import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.media.KeyguardMediaController; 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;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.OnMenuEventListener; import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.OnMenuEventListener;
import com.android.systemui.plugins.statusbar.StatusBarStateController; 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;
import com.android.systemui.statusbar.NotificationLockscreenUserManager.UserChangedListener; import com.android.systemui.statusbar.NotificationLockscreenUserManager.UserChangedListener;
import com.android.systemui.statusbar.SysuiStatusBarStateController; import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.notification.DynamicPrivacyController; 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.legacy.NotificationGroupManagerLegacy;
import com.android.systemui.statusbar.notification.collection.render.SectionHeaderController; import com.android.systemui.statusbar.notification.collection.render.SectionHeaderController;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
@@ -101,9 +106,14 @@ public class NotificationStackScrollerControllerTest extends SysuiTestCase {
@Mock private ScrimController mScrimController; @Mock private ScrimController mScrimController;
@Mock private NotificationGroupManagerLegacy mLegacyGroupManager; @Mock private NotificationGroupManagerLegacy mLegacyGroupManager;
@Mock private SectionHeaderController mSilentHeaderController; @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 @Captor
ArgumentCaptor<StatusBarStateController.StateListener> mStateListenerArgumentCaptor; private ArgumentCaptor<StatusBarStateController.StateListener> mStateListenerArgumentCaptor;
private NotificationStackScrollLayoutController mController; private NotificationStackScrollLayoutController mController;
@@ -112,6 +122,7 @@ public class NotificationStackScrollerControllerTest extends SysuiTestCase {
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
when(mNotificationSwipeHelperBuilder.build()).thenReturn(mNotificationSwipeHelper); when(mNotificationSwipeHelperBuilder.build()).thenReturn(mNotificationSwipeHelper);
when(mFeatureFlags.isNewNotifPipelineRenderingEnabled()).thenReturn(false);
mController = new NotificationStackScrollLayoutController( mController = new NotificationStackScrollLayoutController(
true, true,
@@ -136,7 +147,12 @@ public class NotificationStackScrollerControllerTest extends SysuiTestCase {
mScrimController, mScrimController,
mLegacyGroupManager, mLegacyGroupManager,
mLegacyGroupManager, mLegacyGroupManager,
mSilentHeaderController mSilentHeaderController,
mFeatureFlags,
mNotifPipeline,
mNotifCollection,
mEntryManager,
mIStatusBarService
); );
when(mNotificationStackScrollLayout.isAttachedToWindow()).thenReturn(true); when(mNotificationStackScrollLayout.isAttachedToWindow()).thenReturn(true);
@@ -236,7 +252,6 @@ public class NotificationStackScrollerControllerTest extends SysuiTestCase {
UserChangedListener changedListener = userChangedCaptor.getValue(); UserChangedListener changedListener = userChangedCaptor.getValue();
changedListener.onUserChanged(0); changedListener.onUserChanged(0);
verify(mNotificationStackScrollLayout).setCurrentUserid(0);
verify(mNotificationStackScrollLayout).updateSensitiveness(false, true); verify(mNotificationStackScrollLayout).updateSensitiveness(false, true);
} }