Merge "Fix NotificationStack size calculation" into tm-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
11d05992e7
@@ -217,6 +217,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
|
|||||||
private HashSet<View> mFromMoreCardAdditions = new HashSet<>();
|
private HashSet<View> mFromMoreCardAdditions = new HashSet<>();
|
||||||
private ArrayList<AnimationEvent> mAnimationEvents = new ArrayList<>();
|
private ArrayList<AnimationEvent> mAnimationEvents = new ArrayList<>();
|
||||||
private ArrayList<View> mSwipedOutViews = new ArrayList<>();
|
private ArrayList<View> mSwipedOutViews = new ArrayList<>();
|
||||||
|
private NotificationStackSizeCalculator mNotificationStackSizeCalculator;
|
||||||
private final StackStateAnimator mStateAnimator = new StackStateAnimator(this);
|
private final StackStateAnimator mStateAnimator = new StackStateAnimator(this);
|
||||||
private boolean mAnimationsEnabled;
|
private boolean mAnimationsEnabled;
|
||||||
private boolean mChangePositionInProgress;
|
private boolean mChangePositionInProgress;
|
||||||
@@ -415,6 +416,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
|
|||||||
private NotificationShelf mShelf;
|
private NotificationShelf mShelf;
|
||||||
private int mMaxDisplayedNotifications = -1;
|
private int mMaxDisplayedNotifications = -1;
|
||||||
private float mKeyguardBottomPadding = -1;
|
private float mKeyguardBottomPadding = -1;
|
||||||
|
private float mKeyguardNotificationAvailableSpace = -1;
|
||||||
@VisibleForTesting int mStatusBarHeight;
|
@VisibleForTesting int mStatusBarHeight;
|
||||||
private int mMinInteractionHeight;
|
private int mMinInteractionHeight;
|
||||||
private final Rect mClipRect = new Rect();
|
private final Rect mClipRect = new Rect();
|
||||||
@@ -757,31 +759,34 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
|
|||||||
} else {
|
} else {
|
||||||
mDebugTextUsedYPositions.clear();
|
mDebugTextUsedYPositions.clear();
|
||||||
}
|
}
|
||||||
int y = mTopPadding;
|
int y = 0;
|
||||||
drawDebugInfo(canvas, y, Color.RED, /* label= */ "mTopPadding = "+y);
|
drawDebugInfo(canvas, y, Color.RED, /* label= */ "y = " + y);
|
||||||
|
|
||||||
|
y = mTopPadding;
|
||||||
|
drawDebugInfo(canvas, y, Color.RED, /* label= */ "mTopPadding = " + y);
|
||||||
|
|
||||||
y = getLayoutHeight();
|
y = getLayoutHeight();
|
||||||
drawDebugInfo(canvas, y, Color.YELLOW, /* label= */ "getLayoutHeight() = "+y);
|
drawDebugInfo(canvas, y, Color.YELLOW, /* label= */ "getLayoutHeight() = " + y);
|
||||||
|
|
||||||
y = (int) mMaxLayoutHeight;
|
y = (int) mMaxLayoutHeight;
|
||||||
drawDebugInfo(canvas, y, Color.MAGENTA, /* label= */ "mMaxLayoutHeight = "+y);
|
drawDebugInfo(canvas, y, Color.MAGENTA, /* label= */ "mMaxLayoutHeight = " + y);
|
||||||
|
|
||||||
if (mKeyguardBottomPadding >= 0) {
|
if (mKeyguardBottomPadding >= 0) {
|
||||||
y = getHeight() - (int) mKeyguardBottomPadding;
|
y = getHeight() - (int) mKeyguardBottomPadding;
|
||||||
drawDebugInfo(canvas, y, Color.GRAY,
|
drawDebugInfo(canvas, y, Color.GRAY,
|
||||||
/* label= */ "getHeight() - mKeyguardBottomPadding = "+y);
|
/* label= */ "getHeight() - mKeyguardBottomPadding = " + y);
|
||||||
}
|
}
|
||||||
|
|
||||||
y = getHeight() - getEmptyBottomMargin();
|
y = getHeight() - getEmptyBottomMargin();
|
||||||
drawDebugInfo(canvas, y, Color.GREEN,
|
drawDebugInfo(canvas, y, Color.GREEN,
|
||||||
/* label= */ "getHeight() - getEmptyBottomMargin() = "+y);
|
/* label= */ "getHeight() - getEmptyBottomMargin() = " + y);
|
||||||
|
|
||||||
y = (int) (mAmbientState.getStackY());
|
y = (int) (mAmbientState.getStackY());
|
||||||
drawDebugInfo(canvas, y, Color.CYAN, /* label= */ "mAmbientState.getStackY() = "+y);
|
drawDebugInfo(canvas, y, Color.CYAN, /* label= */ "mAmbientState.getStackY() = " + y);
|
||||||
|
|
||||||
y = (int) (mAmbientState.getStackY() + mAmbientState.getStackHeight());
|
y = (int) (mAmbientState.getStackY() + mAmbientState.getStackHeight());
|
||||||
drawDebugInfo(canvas, y, Color.BLUE,
|
drawDebugInfo(canvas, y, Color.BLUE,
|
||||||
/* label= */ "mAmbientState.getStackY() + mAmbientState.getStackHeight() = "+y);
|
/* label= */ "mAmbientState.getStackY() + mAmbientState.getStackHeight() = " + y);
|
||||||
|
|
||||||
y = (int) mAmbientState.getStackY() + mContentHeight;
|
y = (int) mAmbientState.getStackY() + mContentHeight;
|
||||||
drawDebugInfo(canvas, y, Color.MAGENTA,
|
drawDebugInfo(canvas, y, Color.MAGENTA,
|
||||||
@@ -790,6 +795,10 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
|
|||||||
y = (int) mAmbientState.getStackY() + mIntrinsicContentHeight;
|
y = (int) mAmbientState.getStackY() + mIntrinsicContentHeight;
|
||||||
drawDebugInfo(canvas, y, Color.YELLOW,
|
drawDebugInfo(canvas, y, Color.YELLOW,
|
||||||
/* label= */ "mAmbientState.getStackY() + mIntrinsicContentHeight = " + y);
|
/* label= */ "mAmbientState.getStackY() + mIntrinsicContentHeight = " + y);
|
||||||
|
|
||||||
|
y = (int) (mAmbientState.getStackY() + mKeyguardNotificationAvailableSpace);
|
||||||
|
drawDebugInfo(canvas, y, Color.RED, /* label= */
|
||||||
|
"mAmbientState.getStackY() + mKeyguardNotificationAvailableSpace = " + y);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void drawDebugInfo(Canvas canvas, int y, int color, String label) {
|
private void drawDebugInfo(Canvas canvas, int y, int color, String label) {
|
||||||
@@ -956,13 +965,15 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void reinitView() {
|
private void reinitView() {
|
||||||
initView(getContext(), mSwipeHelper);
|
initView(getContext(), mSwipeHelper, mNotificationStackSizeCalculator);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
|
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
|
||||||
void initView(Context context, NotificationSwipeHelper swipeHelper) {
|
void initView(Context context, NotificationSwipeHelper swipeHelper,
|
||||||
|
NotificationStackSizeCalculator notificationStackSizeCalculator) {
|
||||||
mScroller = new OverScroller(getContext());
|
mScroller = new OverScroller(getContext());
|
||||||
mSwipeHelper = swipeHelper;
|
mSwipeHelper = swipeHelper;
|
||||||
|
mNotificationStackSizeCalculator = notificationStackSizeCalculator;
|
||||||
|
|
||||||
setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);
|
setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);
|
||||||
setClipChildren(false);
|
setClipChildren(false);
|
||||||
@@ -2248,48 +2259,10 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
|
|||||||
@ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
|
@ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
|
||||||
private void updateContentHeight() {
|
private void updateContentHeight() {
|
||||||
final float scrimTopPadding = mAmbientState.isOnKeyguard() ? 0 : mMinimumPaddings;
|
final float scrimTopPadding = mAmbientState.isOnKeyguard() ? 0 : mMinimumPaddings;
|
||||||
int height = (int) scrimTopPadding;
|
final int height =
|
||||||
float previousPaddingRequest = mPaddingBetweenElements;
|
(int) scrimTopPadding + (int) mNotificationStackSizeCalculator.computeHeight(
|
||||||
int numShownItems = 0;
|
/* notificationStackScrollLayout= */ this, mMaxDisplayedNotifications,
|
||||||
int numShownNotifs = 0;
|
mShelf != null ? mShelf.getIntrinsicHeight() : 0);
|
||||||
boolean finish = false;
|
|
||||||
int maxDisplayedNotifications = mMaxDisplayedNotifications;
|
|
||||||
ExpandableView previousView = null;
|
|
||||||
|
|
||||||
for (int i = 0; i < getChildCount(); i++) {
|
|
||||||
ExpandableView expandableView = (ExpandableView) getChildAt(i);
|
|
||||||
boolean footerViewOnLockScreen = expandableView == mFooterView && onKeyguard();
|
|
||||||
|
|
||||||
if (expandableView.getVisibility() != View.GONE
|
|
||||||
&& !expandableView.hasNoContentHeight() && !footerViewOnLockScreen) {
|
|
||||||
|
|
||||||
boolean limitReached = maxDisplayedNotifications != -1
|
|
||||||
&& numShownNotifs >= maxDisplayedNotifications;
|
|
||||||
final float viewHeight;
|
|
||||||
if (limitReached) {
|
|
||||||
viewHeight = mShelf.getIntrinsicHeight();
|
|
||||||
finish = true;
|
|
||||||
} else {
|
|
||||||
viewHeight = expandableView.getIntrinsicHeight();
|
|
||||||
}
|
|
||||||
if (height != 0) {
|
|
||||||
height += mPaddingBetweenElements;
|
|
||||||
}
|
|
||||||
float gapHeight = calculateGapHeight(previousView, expandableView, numShownNotifs);
|
|
||||||
height += gapHeight;
|
|
||||||
height += viewHeight;
|
|
||||||
|
|
||||||
numShownItems++;
|
|
||||||
if (viewHeight > 0 || !(expandableView instanceof MediaContainerView)) {
|
|
||||||
// Only count the media as a notification if it has a positive height.
|
|
||||||
numShownNotifs++;
|
|
||||||
}
|
|
||||||
previousView = expandableView;
|
|
||||||
if (finish) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mIntrinsicContentHeight = height;
|
mIntrinsicContentHeight = height;
|
||||||
|
|
||||||
// The topPadding can be bigger than the regular padding when qs is expanded, in that
|
// The topPadding can be bigger than the regular padding when qs is expanded, in that
|
||||||
@@ -4932,6 +4905,15 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
|
|||||||
mKeyguardBottomPadding = keyguardBottomPadding;
|
mKeyguardBottomPadding = keyguardBottomPadding;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For debugging only. Enables to draw a line related to the available size for notifications in
|
||||||
|
* keyguard.
|
||||||
|
*/
|
||||||
|
public void setKeyguardAvailableSpaceForDebug(float keyguardNotificationAvailableSpace) {
|
||||||
|
mKeyguardNotificationAvailableSpace = keyguardNotificationAvailableSpace;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
|
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
|
||||||
public void setShouldShowShelfOnly(boolean shouldShowShelfOnly) {
|
public void setShouldShowShelfOnly(boolean shouldShowShelfOnly) {
|
||||||
mShouldShowShelfOnly = shouldShowShelfOnly;
|
mShouldShowShelfOnly = shouldShowShelfOnly;
|
||||||
|
|||||||
@@ -181,6 +181,7 @@ public class NotificationStackScrollLayoutController {
|
|||||||
private final SectionHeaderController mSilentHeaderController;
|
private final SectionHeaderController mSilentHeaderController;
|
||||||
private final LockscreenShadeTransitionController mLockscreenShadeTransitionController;
|
private final LockscreenShadeTransitionController mLockscreenShadeTransitionController;
|
||||||
private final InteractionJankMonitor mJankMonitor;
|
private final InteractionJankMonitor mJankMonitor;
|
||||||
|
private final NotificationStackSizeCalculator mNotificationStackSizeCalculator;
|
||||||
private final StackStateLogger mStackStateLogger;
|
private final StackStateLogger mStackStateLogger;
|
||||||
private final NotificationStackScrollLogger mLogger;
|
private final NotificationStackScrollLogger mLogger;
|
||||||
|
|
||||||
@@ -307,6 +308,7 @@ public class NotificationStackScrollLayoutController {
|
|||||||
R.dimen.lockscreen_shade_notification_movement);
|
R.dimen.lockscreen_shade_notification_movement);
|
||||||
mTotalDistanceForFullShadeTransition = mResources.getDimensionPixelSize(
|
mTotalDistanceForFullShadeTransition = mResources.getDimensionPixelSize(
|
||||||
R.dimen.lockscreen_shade_qs_transition_distance);
|
R.dimen.lockscreen_shade_qs_transition_distance);
|
||||||
|
mNotificationStackSizeCalculator.updateResources();
|
||||||
}
|
}
|
||||||
|
|
||||||
private final StatusBarStateController.StateListener mStateListener =
|
private final StatusBarStateController.StateListener mStateListener =
|
||||||
@@ -662,7 +664,8 @@ public class NotificationStackScrollLayoutController {
|
|||||||
ShadeController shadeController,
|
ShadeController shadeController,
|
||||||
InteractionJankMonitor jankMonitor,
|
InteractionJankMonitor jankMonitor,
|
||||||
StackStateLogger stackLogger,
|
StackStateLogger stackLogger,
|
||||||
NotificationStackScrollLogger logger) {
|
NotificationStackScrollLogger logger,
|
||||||
|
NotificationStackSizeCalculator notificationStackSizeCalculator) {
|
||||||
mStackStateLogger = stackLogger;
|
mStackStateLogger = stackLogger;
|
||||||
mLogger = logger;
|
mLogger = logger;
|
||||||
mAllowLongPress = allowLongPress;
|
mAllowLongPress = allowLongPress;
|
||||||
@@ -688,6 +691,7 @@ public class NotificationStackScrollLayoutController {
|
|||||||
mCentralSurfaces = centralSurfaces;
|
mCentralSurfaces = centralSurfaces;
|
||||||
mScrimController = scrimController;
|
mScrimController = scrimController;
|
||||||
mJankMonitor = jankMonitor;
|
mJankMonitor = jankMonitor;
|
||||||
|
mNotificationStackSizeCalculator = notificationStackSizeCalculator;
|
||||||
groupManager.registerGroupExpansionChangeListener(
|
groupManager.registerGroupExpansionChangeListener(
|
||||||
(changedRow, expanded) -> mView.onGroupExpandChanged(changedRow, expanded));
|
(changedRow, expanded) -> mView.onGroupExpandChanged(changedRow, expanded));
|
||||||
legacyGroupManager.registerGroupChangeListener(new OnGroupChangeListener() {
|
legacyGroupManager.registerGroupChangeListener(new OnGroupChangeListener() {
|
||||||
@@ -758,7 +762,7 @@ public class NotificationStackScrollLayoutController {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
mView.initView(mView.getContext(), mSwipeHelper);
|
mView.initView(mView.getContext(), mSwipeHelper, mNotificationStackSizeCalculator);
|
||||||
mView.setKeyguardBypassEnabled(mKeyguardBypassController.getBypassEnabled());
|
mView.setKeyguardBypassEnabled(mKeyguardBypassController.getBypassEnabled());
|
||||||
mKeyguardBypassController
|
mKeyguardBypassController
|
||||||
.registerOnBypassStateChangedListener(mView::setKeyguardBypassEnabled);
|
.registerOnBypassStateChangedListener(mView::setKeyguardBypassEnabled);
|
||||||
@@ -907,6 +911,13 @@ public class NotificationStackScrollLayoutController {
|
|||||||
return mView.getTop();
|
return mView.getTop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the bottom of the view.
|
||||||
|
*/
|
||||||
|
public int getBottom() {
|
||||||
|
return mView.getBottom();
|
||||||
|
}
|
||||||
|
|
||||||
public float getTranslationX() {
|
public float getTranslationX() {
|
||||||
return mView.getTranslationX();
|
return mView.getTranslationX();
|
||||||
}
|
}
|
||||||
@@ -1296,10 +1307,16 @@ public class NotificationStackScrollLayoutController {
|
|||||||
* appear on the keyguard.
|
* appear on the keyguard.
|
||||||
* Setting a negative number will disable rendering this line.
|
* Setting a negative number will disable rendering this line.
|
||||||
*/
|
*/
|
||||||
public void setKeyguardBottomPadding(float keyguardBottomPadding) {
|
public void setKeyguardBottomPaddingForDebug(float keyguardBottomPadding) {
|
||||||
mView.setKeyguardBottomPadding(keyguardBottomPadding);
|
mView.setKeyguardBottomPadding(keyguardBottomPadding);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** For debugging only. */
|
||||||
|
public void mKeyguardNotificationAvailableSpaceForDebug(
|
||||||
|
float keyguardNotificationAvailableSpace) {
|
||||||
|
mView.setKeyguardAvailableSpaceForDebug(keyguardNotificationAvailableSpace);
|
||||||
|
}
|
||||||
|
|
||||||
public RemoteInputController.Delegate createDelegate() {
|
public RemoteInputController.Delegate createDelegate() {
|
||||||
return new RemoteInputController.Delegate() {
|
return new RemoteInputController.Delegate() {
|
||||||
public void setRemoteInputActive(NotificationEntry entry,
|
public void setRemoteInputActive(NotificationEntry entry,
|
||||||
|
|||||||
@@ -0,0 +1,261 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.systemui.statusbar.notification.stack
|
||||||
|
|
||||||
|
import android.content.res.Resources
|
||||||
|
import android.util.Log
|
||||||
|
import android.view.View.GONE
|
||||||
|
import com.android.systemui.R
|
||||||
|
import com.android.systemui.dagger.SysUISingleton
|
||||||
|
import com.android.systemui.dagger.qualifiers.Main
|
||||||
|
import com.android.systemui.statusbar.NotificationLockscreenUserManager
|
||||||
|
import com.android.systemui.statusbar.StatusBarState.KEYGUARD
|
||||||
|
import com.android.systemui.statusbar.SysuiStatusBarStateController
|
||||||
|
import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy
|
||||||
|
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
|
||||||
|
import com.android.systemui.statusbar.notification.row.ExpandableView
|
||||||
|
import com.android.systemui.util.children
|
||||||
|
import javax.inject.Inject
|
||||||
|
import kotlin.math.max
|
||||||
|
import kotlin.properties.Delegates.notNull
|
||||||
|
|
||||||
|
private const val TAG = "NotificationStackSizeCalculator"
|
||||||
|
private const val DEBUG = false
|
||||||
|
|
||||||
|
/** Calculates number of notifications to display and the height of the notification stack. */
|
||||||
|
@SysUISingleton
|
||||||
|
class NotificationStackSizeCalculator
|
||||||
|
@Inject
|
||||||
|
constructor(
|
||||||
|
private val groupManager: NotificationGroupManagerLegacy,
|
||||||
|
private val lockscreenUserManager: NotificationLockscreenUserManager,
|
||||||
|
private val statusBarStateController: SysuiStatusBarStateController,
|
||||||
|
@Main private val resources: Resources
|
||||||
|
) {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum # notifications to show on Keyguard; extras will be collapsed in an overflow shelf.
|
||||||
|
* If there are exactly 1 + mMaxKeyguardNotifications, and they fit in the available space
|
||||||
|
* (considering the overflow shelf is not displayed in this case), then all notifications are
|
||||||
|
* shown.
|
||||||
|
*/
|
||||||
|
private var maxKeyguardNotifications by notNull<Int>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Minimum space between two notifications. There might be more space, see [calculateGapHeight].
|
||||||
|
*/
|
||||||
|
private var notificationPadding by notNull<Int>()
|
||||||
|
|
||||||
|
init {
|
||||||
|
updateResources()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given the [availableSpace] constraint, calculates how many notification to show.
|
||||||
|
*
|
||||||
|
* This number is only valid in keyguard.
|
||||||
|
*
|
||||||
|
* @param availableSpace space for notifications. This doesn't include the space for the shelf.
|
||||||
|
*/
|
||||||
|
fun computeMaxKeyguardNotifications(
|
||||||
|
stack: NotificationStackScrollLayout,
|
||||||
|
availableSpace: Float,
|
||||||
|
shelfHeight: Float
|
||||||
|
): Int {
|
||||||
|
log {
|
||||||
|
"computeMaxKeyguardNotifications(" +
|
||||||
|
"availableSpace=$availableSpace shelfHeight=$shelfHeight)"
|
||||||
|
}
|
||||||
|
|
||||||
|
val children: Sequence<ExpandableView> = stack.childrenSequence
|
||||||
|
var remainingSpace: Float = availableSpace
|
||||||
|
var count = 0
|
||||||
|
var previous: ExpandableView? = null
|
||||||
|
val onLockscreen = true
|
||||||
|
val showableRows = children.filter { it.isShowable(onLockscreen) }
|
||||||
|
val showableRowsCount = showableRows.count()
|
||||||
|
showableRows.forEachIndexed { i, current ->
|
||||||
|
val spaceNeeded = current.spaceNeeded(count, previous, stack, onLockscreen)
|
||||||
|
previous = current
|
||||||
|
log { "\ti=$i spaceNeeded=$spaceNeeded remainingSpace=$remainingSpace" }
|
||||||
|
|
||||||
|
if (remainingSpace - spaceNeeded >= 0 && count < maxKeyguardNotifications) {
|
||||||
|
count += 1
|
||||||
|
remainingSpace -= spaceNeeded
|
||||||
|
} else if (remainingSpace - spaceNeeded > -shelfHeight && i == showableRowsCount - 1) {
|
||||||
|
log { "Showing all notifications. Shelf is not be needed." }
|
||||||
|
// If this is the last one, and it fits using the space shelf would use, then we can
|
||||||
|
// display it, as the shelf will not be needed (as all notifications are shown).
|
||||||
|
return count + 1
|
||||||
|
} else {
|
||||||
|
log {
|
||||||
|
"No more fit. Returning $count. Space used: ${availableSpace - remainingSpace}"
|
||||||
|
}
|
||||||
|
return count
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log { "All fit. Returning $count" }
|
||||||
|
return count
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given the [maxNotifications] constraint, calculates the height of the
|
||||||
|
* [NotificationStackScrollLayout]. This might or might not be in keyguard.
|
||||||
|
*
|
||||||
|
* @param stack stack containing notifications as children.
|
||||||
|
* @param maxNotifications Maximum number of notifications. When reached, the others will go
|
||||||
|
* into the shelf.
|
||||||
|
* @param shelfHeight height of the shelf. It might be zero.
|
||||||
|
*
|
||||||
|
* @return height of the stack, including shelf height, if needed.
|
||||||
|
*/
|
||||||
|
fun computeHeight(
|
||||||
|
stack: NotificationStackScrollLayout,
|
||||||
|
maxNotifications: Int,
|
||||||
|
shelfHeight: Float
|
||||||
|
): Float {
|
||||||
|
val children: Sequence<ExpandableView> = stack.childrenSequence
|
||||||
|
val maxNotificationsArg = infiniteIfNegative(maxNotifications)
|
||||||
|
var height = 0f
|
||||||
|
var previous: ExpandableView? = null
|
||||||
|
var count = 0
|
||||||
|
val onLockscreen = onLockscreen()
|
||||||
|
|
||||||
|
log { "computeHeight(maxNotification=$maxNotifications, shelf=$shelfHeight" }
|
||||||
|
children.filter { it.isShowable(onLockscreen) }.forEach { current ->
|
||||||
|
if (count < maxNotificationsArg) {
|
||||||
|
val spaceNeeded = current.spaceNeeded(count, previous, stack, onLockscreen)
|
||||||
|
log { "\ti=$count spaceNeeded=$spaceNeeded" }
|
||||||
|
height += spaceNeeded
|
||||||
|
count += 1
|
||||||
|
} else {
|
||||||
|
height += shelfHeight
|
||||||
|
log { "returning height with shelf -> $height" }
|
||||||
|
return height
|
||||||
|
}
|
||||||
|
previous = current
|
||||||
|
}
|
||||||
|
log { "Returning height without shelf -> $height" }
|
||||||
|
return height
|
||||||
|
}
|
||||||
|
|
||||||
|
fun updateResources() {
|
||||||
|
maxKeyguardNotifications =
|
||||||
|
infiniteIfNegative(resources.getInteger(R.integer.keyguard_max_notification_count))
|
||||||
|
|
||||||
|
notificationPadding =
|
||||||
|
max(1, resources.getDimensionPixelSize(R.dimen.notification_divider_height))
|
||||||
|
}
|
||||||
|
|
||||||
|
private val NotificationStackScrollLayout.childrenSequence: Sequence<ExpandableView>
|
||||||
|
get() = children.map { it as ExpandableView }
|
||||||
|
|
||||||
|
private fun onLockscreen() = statusBarStateController.state == KEYGUARD
|
||||||
|
|
||||||
|
private fun ExpandableView.spaceNeeded(
|
||||||
|
visibleIndex: Int,
|
||||||
|
previousView: ExpandableView?,
|
||||||
|
stack: NotificationStackScrollLayout,
|
||||||
|
onLockscreen: Boolean
|
||||||
|
): Float {
|
||||||
|
assert(isShowable(onLockscreen))
|
||||||
|
var size =
|
||||||
|
if (onLockscreen) {
|
||||||
|
getMinHeight(/* ignoreTemporaryStates= */ true).toFloat()
|
||||||
|
} else {
|
||||||
|
intrinsicHeight.toFloat()
|
||||||
|
}
|
||||||
|
if (visibleIndex != 0) {
|
||||||
|
size += notificationPadding
|
||||||
|
}
|
||||||
|
size += calculateGapHeight(stack, previousView, visibleIndex)
|
||||||
|
return size
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun ExpandableView.isShowable(onLockscreen: Boolean): Boolean {
|
||||||
|
if (visibility == GONE || hasNoContentHeight()) return false
|
||||||
|
if (onLockscreen) {
|
||||||
|
when (this) {
|
||||||
|
is ExpandableNotificationRow -> {
|
||||||
|
if (isSummaryOfSuppressedGroup() || !canShowViewOnLockscreen() || isRemoved) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is MediaContainerView -> if (intrinsicHeight == 0) return false
|
||||||
|
else -> return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun ExpandableView.calculateGapHeight(
|
||||||
|
stack: NotificationStackScrollLayout,
|
||||||
|
previous: ExpandableView?,
|
||||||
|
visibleIndex: Int
|
||||||
|
) = stack.calculateGapHeight(previous, /* current= */ this, visibleIndex)
|
||||||
|
|
||||||
|
private fun ExpandableNotificationRow.isSummaryOfSuppressedGroup() =
|
||||||
|
groupManager.isSummaryOfSuppressedGroup(entry.sbn)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Can a view be shown on the lockscreen when calculating the number of allowed notifications to
|
||||||
|
* show?
|
||||||
|
*
|
||||||
|
* @return `true` if it can be shown.
|
||||||
|
*/
|
||||||
|
private fun ExpandableView.canShowViewOnLockscreen(): Boolean {
|
||||||
|
if (hasNoContentHeight()) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (this is ExpandableNotificationRow && !canShowRowOnLockscreen()) {
|
||||||
|
return false
|
||||||
|
} else if (visibility == GONE) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Can a row be shown on the lockscreen when calculating the number of allowed notifications to
|
||||||
|
* show?
|
||||||
|
*
|
||||||
|
* @return true if it can be shown
|
||||||
|
*/
|
||||||
|
private fun ExpandableNotificationRow.canShowRowOnLockscreen(): Boolean {
|
||||||
|
if (isSummaryOfSuppressedGroup()) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (!lockscreenUserManager.shouldShowOnKeyguard(entry)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return !isRemoved
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun log(s: () -> String) {
|
||||||
|
if (DEBUG) {
|
||||||
|
Log.d(TAG, s())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns infinite when [v] is negative. Useful in case a resource doesn't limit when -1. */
|
||||||
|
private fun infiniteIfNegative(v: Int): Int =
|
||||||
|
if (v < 0) {
|
||||||
|
Int.MAX_VALUE
|
||||||
|
} else {
|
||||||
|
v
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -17,7 +17,6 @@
|
|||||||
package com.android.systemui.statusbar.phone;
|
package com.android.systemui.statusbar.phone;
|
||||||
|
|
||||||
import static android.app.StatusBarManager.WINDOW_STATE_SHOWING;
|
import static android.app.StatusBarManager.WINDOW_STATE_SHOWING;
|
||||||
import static android.view.View.GONE;
|
|
||||||
|
|
||||||
import static androidx.constraintlayout.widget.ConstraintSet.END;
|
import static androidx.constraintlayout.widget.ConstraintSet.END;
|
||||||
import static androidx.constraintlayout.widget.ConstraintSet.PARENT_ID;
|
import static androidx.constraintlayout.widget.ConstraintSet.PARENT_ID;
|
||||||
@@ -144,7 +143,6 @@ import com.android.systemui.statusbar.GestureRecorder;
|
|||||||
import com.android.systemui.statusbar.KeyguardAffordanceView;
|
import com.android.systemui.statusbar.KeyguardAffordanceView;
|
||||||
import com.android.systemui.statusbar.KeyguardIndicationController;
|
import com.android.systemui.statusbar.KeyguardIndicationController;
|
||||||
import com.android.systemui.statusbar.LockscreenShadeTransitionController;
|
import com.android.systemui.statusbar.LockscreenShadeTransitionController;
|
||||||
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
|
|
||||||
import com.android.systemui.statusbar.NotificationRemoteInputManager;
|
import com.android.systemui.statusbar.NotificationRemoteInputManager;
|
||||||
import com.android.systemui.statusbar.NotificationShadeDepthController;
|
import com.android.systemui.statusbar.NotificationShadeDepthController;
|
||||||
import com.android.systemui.statusbar.NotificationShadeWindowController;
|
import com.android.systemui.statusbar.NotificationShadeWindowController;
|
||||||
@@ -165,17 +163,16 @@ import com.android.systemui.statusbar.notification.PropertyAnimator;
|
|||||||
import com.android.systemui.statusbar.notification.ViewGroupFadeHelper;
|
import com.android.systemui.statusbar.notification.ViewGroupFadeHelper;
|
||||||
import com.android.systemui.statusbar.notification.collection.ListEntry;
|
import com.android.systemui.statusbar.notification.collection.ListEntry;
|
||||||
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.render.ShadeViewManager;
|
import com.android.systemui.statusbar.notification.collection.render.ShadeViewManager;
|
||||||
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
|
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
|
||||||
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
|
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
|
||||||
import com.android.systemui.statusbar.notification.row.ExpandableView;
|
import com.android.systemui.statusbar.notification.row.ExpandableView;
|
||||||
import com.android.systemui.statusbar.notification.stack.AmbientState;
|
import com.android.systemui.statusbar.notification.stack.AmbientState;
|
||||||
import com.android.systemui.statusbar.notification.stack.AnimationProperties;
|
import com.android.systemui.statusbar.notification.stack.AnimationProperties;
|
||||||
import com.android.systemui.statusbar.notification.stack.MediaContainerView;
|
|
||||||
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
|
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
|
||||||
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
|
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
|
||||||
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
|
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
|
||||||
|
import com.android.systemui.statusbar.notification.stack.NotificationStackSizeCalculator;
|
||||||
import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
|
import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
|
||||||
import com.android.systemui.statusbar.phone.LockscreenGestureLogger.LockscreenUiEvent;
|
import com.android.systemui.statusbar.phone.LockscreenGestureLogger.LockscreenUiEvent;
|
||||||
import com.android.systemui.statusbar.phone.dagger.CentralSurfacesComponent;
|
import com.android.systemui.statusbar.phone.dagger.CentralSurfacesComponent;
|
||||||
@@ -312,9 +309,6 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
private final ControlsComponent mControlsComponent;
|
private final ControlsComponent mControlsComponent;
|
||||||
private final NotificationRemoteInputManager mRemoteInputManager;
|
private final NotificationRemoteInputManager mRemoteInputManager;
|
||||||
|
|
||||||
// Maximum # notifications to show on Keyguard; extras will be collapsed in an overflow card.
|
|
||||||
// If there are exactly 1 + mMaxKeyguardNotifications, then still shows all notifications
|
|
||||||
private final int mMaxKeyguardNotifications;
|
|
||||||
private final LockscreenShadeTransitionController mLockscreenShadeTransitionController;
|
private final LockscreenShadeTransitionController mLockscreenShadeTransitionController;
|
||||||
private final TapAgainViewController mTapAgainViewController;
|
private final TapAgainViewController mTapAgainViewController;
|
||||||
private final SplitShadeHeaderController mSplitShadeHeaderController;
|
private final SplitShadeHeaderController mSplitShadeHeaderController;
|
||||||
@@ -323,6 +317,8 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
private boolean mShouldUseSplitNotificationShade;
|
private boolean mShouldUseSplitNotificationShade;
|
||||||
// The bottom padding reserved for elements of the keyguard measuring notifications
|
// The bottom padding reserved for elements of the keyguard measuring notifications
|
||||||
private float mKeyguardNotificationBottomPadding;
|
private float mKeyguardNotificationBottomPadding;
|
||||||
|
// Space available for notifications.
|
||||||
|
private float mKeyguardNotificationAvailableSpace;
|
||||||
// Current max allowed keyguard notifications determined by measuring the panel
|
// Current max allowed keyguard notifications determined by measuring the panel
|
||||||
private int mMaxAllowedKeyguardNotifications;
|
private int mMaxAllowedKeyguardNotifications;
|
||||||
|
|
||||||
@@ -446,8 +442,6 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
setHeadsUpAnimatingAway(false);
|
setHeadsUpAnimatingAway(false);
|
||||||
updatePanelExpansionAndVisibility();
|
updatePanelExpansionAndVisibility();
|
||||||
};
|
};
|
||||||
// TODO (b/162832756): once migrated to the new pipeline, delete legacy group manager
|
|
||||||
private NotificationGroupManagerLegacy mGroupManager;
|
|
||||||
private boolean mShowIconsWhenExpanded;
|
private boolean mShowIconsWhenExpanded;
|
||||||
private int mIndicationBottomPadding;
|
private int mIndicationBottomPadding;
|
||||||
private int mAmbientIndicationBottomPadding;
|
private int mAmbientIndicationBottomPadding;
|
||||||
@@ -509,7 +503,6 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
private final NotificationEntryManager mEntryManager;
|
private final NotificationEntryManager mEntryManager;
|
||||||
|
|
||||||
private final CommandQueue mCommandQueue;
|
private final CommandQueue mCommandQueue;
|
||||||
private final NotificationLockscreenUserManager mLockscreenUserManager;
|
|
||||||
private final UserManager mUserManager;
|
private final UserManager mUserManager;
|
||||||
private final MediaDataManager mMediaDataManager;
|
private final MediaDataManager mMediaDataManager;
|
||||||
private final SysUiState mSysUiState;
|
private final SysUiState mSysUiState;
|
||||||
@@ -651,6 +644,7 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
mNotificationPanelUnfoldAnimationController;
|
mNotificationPanelUnfoldAnimationController;
|
||||||
|
|
||||||
private final NotificationListContainer mNotificationListContainer;
|
private final NotificationListContainer mNotificationListContainer;
|
||||||
|
private final NotificationStackSizeCalculator mNotificationStackSizeCalculator;
|
||||||
|
|
||||||
private View.AccessibilityDelegate mAccessibilityDelegate = new View.AccessibilityDelegate() {
|
private View.AccessibilityDelegate mAccessibilityDelegate = new View.AccessibilityDelegate() {
|
||||||
@Override
|
@Override
|
||||||
@@ -695,7 +689,6 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
DynamicPrivacyController dynamicPrivacyController,
|
DynamicPrivacyController dynamicPrivacyController,
|
||||||
KeyguardBypassController bypassController, FalsingManager falsingManager,
|
KeyguardBypassController bypassController, FalsingManager falsingManager,
|
||||||
FalsingCollector falsingCollector,
|
FalsingCollector falsingCollector,
|
||||||
NotificationLockscreenUserManager notificationLockscreenUserManager,
|
|
||||||
NotificationEntryManager notificationEntryManager,
|
NotificationEntryManager notificationEntryManager,
|
||||||
KeyguardStateController keyguardStateController,
|
KeyguardStateController keyguardStateController,
|
||||||
StatusBarStateController statusBarStateController,
|
StatusBarStateController statusBarStateController,
|
||||||
@@ -721,7 +714,6 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
KeyguardUserSwitcherComponent.Factory keyguardUserSwitcherComponentFactory,
|
KeyguardUserSwitcherComponent.Factory keyguardUserSwitcherComponentFactory,
|
||||||
KeyguardStatusBarViewComponent.Factory keyguardStatusBarViewComponentFactory,
|
KeyguardStatusBarViewComponent.Factory keyguardStatusBarViewComponentFactory,
|
||||||
LockscreenShadeTransitionController lockscreenShadeTransitionController,
|
LockscreenShadeTransitionController lockscreenShadeTransitionController,
|
||||||
NotificationGroupManagerLegacy groupManager,
|
|
||||||
NotificationIconAreaController notificationIconAreaController,
|
NotificationIconAreaController notificationIconAreaController,
|
||||||
AuthController authController,
|
AuthController authController,
|
||||||
ScrimController scrimController,
|
ScrimController scrimController,
|
||||||
@@ -753,7 +745,8 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
SysUiState sysUiState,
|
SysUiState sysUiState,
|
||||||
KeyguardUnlockAnimationController keyguardUnlockAnimationController,
|
KeyguardUnlockAnimationController keyguardUnlockAnimationController,
|
||||||
NotificationListContainer notificationListContainer,
|
NotificationListContainer notificationListContainer,
|
||||||
PanelEventsEmitter panelEventsEmitter) {
|
PanelEventsEmitter panelEventsEmitter,
|
||||||
|
NotificationStackSizeCalculator notificationStackSizeCalculator) {
|
||||||
super(view,
|
super(view,
|
||||||
falsingManager,
|
falsingManager,
|
||||||
dozeLog,
|
dozeLog,
|
||||||
@@ -785,9 +778,9 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
|
mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
|
||||||
mNotificationsQSContainerController = notificationsQSContainerController;
|
mNotificationsQSContainerController = notificationsQSContainerController;
|
||||||
mNotificationListContainer = notificationListContainer;
|
mNotificationListContainer = notificationListContainer;
|
||||||
|
mNotificationStackSizeCalculator = notificationStackSizeCalculator;
|
||||||
mNotificationsQSContainerController.init();
|
mNotificationsQSContainerController.init();
|
||||||
mNotificationStackScrollLayoutController = notificationStackScrollLayoutController;
|
mNotificationStackScrollLayoutController = notificationStackScrollLayoutController;
|
||||||
mGroupManager = groupManager;
|
|
||||||
mNotificationIconAreaController = notificationIconAreaController;
|
mNotificationIconAreaController = notificationIconAreaController;
|
||||||
mKeyguardStatusViewComponentFactory = keyguardStatusViewComponentFactory;
|
mKeyguardStatusViewComponentFactory = keyguardStatusViewComponentFactory;
|
||||||
mKeyguardStatusBarViewComponentFactory = keyguardStatusBarViewComponentFactory;
|
mKeyguardStatusBarViewComponentFactory = keyguardStatusBarViewComponentFactory;
|
||||||
@@ -849,7 +842,6 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
});
|
});
|
||||||
mBottomAreaShadeAlphaAnimator.setDuration(160);
|
mBottomAreaShadeAlphaAnimator.setDuration(160);
|
||||||
mBottomAreaShadeAlphaAnimator.setInterpolator(Interpolators.ALPHA_OUT);
|
mBottomAreaShadeAlphaAnimator.setInterpolator(Interpolators.ALPHA_OUT);
|
||||||
mLockscreenUserManager = notificationLockscreenUserManager;
|
|
||||||
mEntryManager = notificationEntryManager;
|
mEntryManager = notificationEntryManager;
|
||||||
mConversationNotificationManager = conversationNotificationManager;
|
mConversationNotificationManager = conversationNotificationManager;
|
||||||
mAuthController = authController;
|
mAuthController = authController;
|
||||||
@@ -874,7 +866,6 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
mView.getOverlay().add(new DebugDrawable());
|
mView.getOverlay().add(new DebugDrawable());
|
||||||
}
|
}
|
||||||
|
|
||||||
mMaxKeyguardNotifications = resources.getInteger(R.integer.keyguard_max_notification_count);
|
|
||||||
mKeyguardUnfoldTransition = unfoldComponent.map(c -> c.getKeyguardUnfoldTransition());
|
mKeyguardUnfoldTransition = unfoldComponent.map(c -> c.getKeyguardUnfoldTransition());
|
||||||
mNotificationPanelUnfoldAnimationController = unfoldComponent.map(
|
mNotificationPanelUnfoldAnimationController = unfoldComponent.map(
|
||||||
SysUIUnfoldComponent::getNotificationPanelUnfoldAnimationController);
|
SysUIUnfoldComponent::getNotificationPanelUnfoldAnimationController);
|
||||||
@@ -1238,12 +1229,14 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
if (mKeyguardShowing && !mKeyguardBypassController.getBypassEnabled()) {
|
if (mKeyguardShowing && !mKeyguardBypassController.getBypassEnabled()) {
|
||||||
mNotificationStackScrollLayoutController.setMaxDisplayedNotifications(
|
mNotificationStackScrollLayoutController.setMaxDisplayedNotifications(
|
||||||
mMaxAllowedKeyguardNotifications);
|
mMaxAllowedKeyguardNotifications);
|
||||||
mNotificationStackScrollLayoutController.setKeyguardBottomPadding(
|
mNotificationStackScrollLayoutController.setKeyguardBottomPaddingForDebug(
|
||||||
mKeyguardNotificationBottomPadding);
|
mKeyguardNotificationBottomPadding);
|
||||||
|
mNotificationStackScrollLayoutController.mKeyguardNotificationAvailableSpaceForDebug(
|
||||||
|
mKeyguardNotificationAvailableSpace);
|
||||||
} else {
|
} else {
|
||||||
// no max when not on the keyguard
|
// no max when not on the keyguard
|
||||||
mNotificationStackScrollLayoutController.setMaxDisplayedNotifications(-1);
|
mNotificationStackScrollLayoutController.setMaxDisplayedNotifications(-1);
|
||||||
mNotificationStackScrollLayoutController.setKeyguardBottomPadding(-1f);
|
mNotificationStackScrollLayoutController.setKeyguardBottomPaddingForDebug(-1f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1454,127 +1447,38 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
* @return the maximum keyguard notifications that can fit on the screen
|
* @return the maximum keyguard notifications that can fit on the screen
|
||||||
*/
|
*/
|
||||||
private int computeMaxKeyguardNotifications() {
|
private int computeMaxKeyguardNotifications() {
|
||||||
float minPadding = mClockPositionAlgorithm.getMinStackScrollerPadding();
|
|
||||||
int notificationPadding = Math.max(
|
int notificationPadding = Math.max(
|
||||||
1, mResources.getDimensionPixelSize(R.dimen.notification_divider_height));
|
1, mResources.getDimensionPixelSize(R.dimen.notification_divider_height));
|
||||||
float shelfSize =
|
float topPadding = mNotificationStackScrollLayoutController.getTopPadding();
|
||||||
|
float shelfHeight =
|
||||||
mNotificationShelfController.getVisibility() == View.GONE
|
mNotificationShelfController.getVisibility() == View.GONE
|
||||||
? 0
|
? 0
|
||||||
: mNotificationShelfController.getIntrinsicHeight() + notificationPadding;
|
: mNotificationShelfController.getIntrinsicHeight() + notificationPadding;
|
||||||
|
|
||||||
|
// Padding to add to the bottom of the stack to keep a minimum distance from the top of
|
||||||
|
// the lock icon.
|
||||||
float lockIconPadding = 0;
|
float lockIconPadding = 0;
|
||||||
if (mLockIconViewController.getTop() != 0) {
|
if (mLockIconViewController.getTop() != 0) {
|
||||||
lockIconPadding = mCentralSurfaces.getDisplayHeight() - mLockIconViewController.getTop()
|
final float lockIconTopWithPadding = mLockIconViewController.getTop()
|
||||||
+ mResources.getDimensionPixelSize(R.dimen.min_lock_icon_padding);
|
- mResources.getDimensionPixelSize(R.dimen.min_lock_icon_padding);
|
||||||
|
lockIconPadding = mNotificationStackScrollLayoutController.getBottom()
|
||||||
|
- lockIconTopWithPadding;
|
||||||
}
|
}
|
||||||
|
|
||||||
float bottomPadding = Math.max(mIndicationBottomPadding, mAmbientIndicationBottomPadding);
|
float bottomPadding = Math.max(lockIconPadding,
|
||||||
bottomPadding = Math.max(lockIconPadding, bottomPadding);
|
Math.max(mIndicationBottomPadding, mAmbientIndicationBottomPadding));
|
||||||
mKeyguardNotificationBottomPadding = bottomPadding;
|
mKeyguardNotificationBottomPadding = bottomPadding;
|
||||||
|
|
||||||
float availableSpace =
|
float availableSpace =
|
||||||
mNotificationStackScrollLayoutController.getHeight()
|
mNotificationStackScrollLayoutController.getHeight()
|
||||||
- minPadding
|
- topPadding
|
||||||
- shelfSize
|
- shelfHeight
|
||||||
- bottomPadding;
|
- bottomPadding;
|
||||||
|
mKeyguardNotificationAvailableSpace = availableSpace;
|
||||||
|
|
||||||
int count = 0;
|
return mNotificationStackSizeCalculator.computeMaxKeyguardNotifications(
|
||||||
ExpandableView previousView = null;
|
mNotificationStackScrollLayoutController.getView(), availableSpace,
|
||||||
for (int i = 0; i < mNotificationStackScrollLayoutController.getChildCount(); i++) {
|
shelfHeight);
|
||||||
ExpandableView child = mNotificationStackScrollLayoutController.getChildAt(i);
|
|
||||||
if (child instanceof ExpandableNotificationRow) {
|
|
||||||
ExpandableNotificationRow row = (ExpandableNotificationRow) child;
|
|
||||||
boolean suppressedSummary = mGroupManager != null
|
|
||||||
&& mGroupManager.isSummaryOfSuppressedGroup(row.getEntry().getSbn());
|
|
||||||
if (suppressedSummary) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!canShowViewOnLockscreen(child)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (row.isRemoved()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
} else if (child instanceof MediaContainerView) {
|
|
||||||
if (child.getVisibility() == GONE) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (child.getIntrinsicHeight() == 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
availableSpace -= child.getMinHeight(true /* ignoreTemporaryStates */);
|
|
||||||
availableSpace -= count == 0 ? 0 : notificationPadding;
|
|
||||||
availableSpace -= mNotificationStackScrollLayoutController
|
|
||||||
.calculateGapHeight(previousView, child, count);
|
|
||||||
previousView = child;
|
|
||||||
if (availableSpace >= 0
|
|
||||||
&& (mMaxKeyguardNotifications == -1 || count < mMaxKeyguardNotifications)) {
|
|
||||||
count++;
|
|
||||||
} else if (availableSpace > -shelfSize) {
|
|
||||||
// if we are exactly the last view, then we can show us still!
|
|
||||||
int childCount = mNotificationStackScrollLayoutController.getChildCount();
|
|
||||||
for (int j = i + 1; j < childCount; j++) {
|
|
||||||
ExpandableView view = mNotificationStackScrollLayoutController.getChildAt(j);
|
|
||||||
if (view instanceof ExpandableNotificationRow
|
|
||||||
&& canShowViewOnLockscreen(view)) {
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
count++;
|
|
||||||
return count;
|
|
||||||
} else {
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Can a view be shown on the lockscreen when calculating the number of allowed notifications
|
|
||||||
* to show?
|
|
||||||
*
|
|
||||||
* @param child the view in question
|
|
||||||
* @return true if it can be shown
|
|
||||||
*/
|
|
||||||
private boolean canShowViewOnLockscreen(ExpandableView child) {
|
|
||||||
if (child.hasNoContentHeight()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (child instanceof ExpandableNotificationRow &&
|
|
||||||
!canShowRowOnLockscreen((ExpandableNotificationRow) child)) {
|
|
||||||
return false;
|
|
||||||
} else if (child.getVisibility() == GONE) {
|
|
||||||
// ENRs can be gone and count because their visibility is only set after
|
|
||||||
// this calculation, but all other views should be up to date
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Can a row be shown on the lockscreen when calculating the number of allowed notifications
|
|
||||||
* to show?
|
|
||||||
*
|
|
||||||
* @param row the row in question
|
|
||||||
* @return true if it can be shown
|
|
||||||
*/
|
|
||||||
private boolean canShowRowOnLockscreen(ExpandableNotificationRow row) {
|
|
||||||
boolean suppressedSummary =
|
|
||||||
mGroupManager != null && mGroupManager.isSummaryOfSuppressedGroup(
|
|
||||||
row.getEntry().getSbn());
|
|
||||||
if (suppressedSummary) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!mLockscreenUserManager.shouldShowOnKeyguard(row.getEntry())) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (row.isRemoved()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateClock() {
|
private void updateClock() {
|
||||||
@@ -4883,6 +4787,8 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
"calculateNotificationsTopPadding()");
|
"calculateNotificationsTopPadding()");
|
||||||
drawDebugInfo(canvas, mClockPositionResult.clockY, Color.GRAY,
|
drawDebugInfo(canvas, mClockPositionResult.clockY, Color.GRAY,
|
||||||
"mClockPositionResult.clockY");
|
"mClockPositionResult.clockY");
|
||||||
|
drawDebugInfo(canvas, (int) mLockIconViewController.getTop(), Color.GRAY,
|
||||||
|
"mLockIconViewController.getTop()");
|
||||||
|
|
||||||
mDebugPaint.setColor(Color.CYAN);
|
mDebugPaint.setColor(Color.CYAN);
|
||||||
canvas.drawLine(0, mClockPositionResult.stackScrollerPadding, mView.getWidth(),
|
canvas.drawLine(0, mClockPositionResult.stackScrollerPadding, mView.getWidth(),
|
||||||
|
|||||||
@@ -134,6 +134,7 @@ public class NotificationStackScrollLayoutControllerTest extends SysuiTestCase {
|
|||||||
@Mock private InteractionJankMonitor mJankMonitor;
|
@Mock private InteractionJankMonitor mJankMonitor;
|
||||||
@Mock private StackStateLogger mStackLogger;
|
@Mock private StackStateLogger mStackLogger;
|
||||||
@Mock private NotificationStackScrollLogger mLogger;
|
@Mock private NotificationStackScrollLogger mLogger;
|
||||||
|
@Mock private NotificationStackSizeCalculator mNotificationStackSizeCalculator;
|
||||||
|
|
||||||
@Captor
|
@Captor
|
||||||
private ArgumentCaptor<StatusBarStateController.StateListener> mStateListenerArgumentCaptor;
|
private ArgumentCaptor<StatusBarStateController.StateListener> mStateListenerArgumentCaptor;
|
||||||
@@ -186,7 +187,8 @@ public class NotificationStackScrollLayoutControllerTest extends SysuiTestCase {
|
|||||||
mShadeController,
|
mShadeController,
|
||||||
mJankMonitor,
|
mJankMonitor,
|
||||||
mStackLogger,
|
mStackLogger,
|
||||||
mLogger
|
mLogger,
|
||||||
|
mNotificationStackSizeCalculator
|
||||||
);
|
);
|
||||||
|
|
||||||
when(mNotificationStackScrollLayout.isAttachedToWindow()).thenReturn(true);
|
when(mNotificationStackScrollLayout.isAttachedToWindow()).thenReturn(true);
|
||||||
|
|||||||
@@ -103,6 +103,7 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase {
|
|||||||
@Mock private NotificationStackScrollLayoutController mStackScrollLayoutController;
|
@Mock private NotificationStackScrollLayoutController mStackScrollLayoutController;
|
||||||
@Mock private UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController;
|
@Mock private UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController;
|
||||||
@Mock private NotificationShelf mNotificationShelf;
|
@Mock private NotificationShelf mNotificationShelf;
|
||||||
|
@Mock private NotificationStackSizeCalculator mNotificationStackSizeCalculator;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
@UiThreadTest
|
@UiThreadTest
|
||||||
@@ -138,7 +139,8 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase {
|
|||||||
// holds a copy of the CUT's instances of these KeyguardBypassController, so they still
|
// holds a copy of the CUT's instances of these KeyguardBypassController, so they still
|
||||||
// refer to the CUT's member variables, not the spy's member variables.
|
// refer to the CUT's member variables, not the spy's member variables.
|
||||||
mStackScrollerInternal = new NotificationStackScrollLayout(getContext(), null);
|
mStackScrollerInternal = new NotificationStackScrollLayout(getContext(), null);
|
||||||
mStackScrollerInternal.initView(getContext(), mNotificationSwipeHelper);
|
mStackScrollerInternal.initView(getContext(), mNotificationSwipeHelper,
|
||||||
|
mNotificationStackSizeCalculator);
|
||||||
mStackScroller = spy(mStackScrollerInternal);
|
mStackScroller = spy(mStackScrollerInternal);
|
||||||
mStackScroller.setShelfController(notificationShelfController);
|
mStackScroller.setShelfController(notificationShelfController);
|
||||||
mStackScroller.setCentralSurfaces(mCentralSurfaces);
|
mStackScroller.setCentralSurfaces(mCentralSurfaces);
|
||||||
|
|||||||
@@ -0,0 +1,266 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.systemui.statusbar.notification.stack
|
||||||
|
|
||||||
|
import android.service.notification.StatusBarNotification
|
||||||
|
import android.testing.AndroidTestingRunner
|
||||||
|
import android.view.View.VISIBLE
|
||||||
|
import androidx.test.filters.SmallTest
|
||||||
|
import com.android.systemui.R
|
||||||
|
import com.android.systemui.SysuiTestCase
|
||||||
|
import com.android.systemui.statusbar.NotificationLockscreenUserManager
|
||||||
|
import com.android.systemui.statusbar.StatusBarState.KEYGUARD
|
||||||
|
import com.android.systemui.statusbar.StatusBarState.SHADE
|
||||||
|
import com.android.systemui.statusbar.SysuiStatusBarStateController
|
||||||
|
import com.android.systemui.statusbar.notification.collection.NotificationEntry
|
||||||
|
import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy
|
||||||
|
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
|
||||||
|
import com.android.systemui.statusbar.notification.row.ExpandableView
|
||||||
|
import com.android.systemui.util.mockito.any
|
||||||
|
import com.android.systemui.util.mockito.nullable
|
||||||
|
import com.google.common.truth.Truth.assertThat
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import org.mockito.Mock
|
||||||
|
import org.mockito.Mockito.mock
|
||||||
|
import org.mockito.Mockito.`when` as whenever
|
||||||
|
import org.mockito.MockitoAnnotations
|
||||||
|
|
||||||
|
@SmallTest
|
||||||
|
@RunWith(AndroidTestingRunner::class)
|
||||||
|
class NotificationStackSizeCalculatorTest : SysuiTestCase() {
|
||||||
|
|
||||||
|
@Mock private lateinit var groupManager: NotificationGroupManagerLegacy
|
||||||
|
|
||||||
|
@Mock private lateinit var notificationLockscreenUserManager: NotificationLockscreenUserManager
|
||||||
|
|
||||||
|
@Mock private lateinit var sysuiStatusBarStateController: SysuiStatusBarStateController
|
||||||
|
|
||||||
|
@Mock private lateinit var stackLayout: NotificationStackScrollLayout
|
||||||
|
|
||||||
|
private val testableResources = mContext.getOrCreateTestableResources()
|
||||||
|
|
||||||
|
private lateinit var sizeCalculator: NotificationStackSizeCalculator
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun setUp() {
|
||||||
|
MockitoAnnotations.initMocks(this)
|
||||||
|
|
||||||
|
whenever(stackLayout.calculateGapHeight(nullable(), nullable(), any()))
|
||||||
|
.thenReturn(GAP_HEIGHT)
|
||||||
|
whenever(groupManager.isSummaryOfSuppressedGroup(any())).thenReturn(false)
|
||||||
|
with(testableResources) {
|
||||||
|
addOverride(R.integer.keyguard_max_notification_count, -1)
|
||||||
|
addOverride(R.dimen.notification_divider_height, NOTIFICATION_PADDING.toInt())
|
||||||
|
}
|
||||||
|
|
||||||
|
sizeCalculator =
|
||||||
|
NotificationStackSizeCalculator(
|
||||||
|
groupManager = groupManager,
|
||||||
|
lockscreenUserManager = notificationLockscreenUserManager,
|
||||||
|
statusBarStateController = sysuiStatusBarStateController,
|
||||||
|
testableResources.resources)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun computeMaxKeyguardNotifications_zeroSpace_returnZero() {
|
||||||
|
val rows = listOf(createMockRow(height = ROW_HEIGHT, visibleOnLockscreen = true))
|
||||||
|
|
||||||
|
val maxNotifications =
|
||||||
|
computeMaxKeyguardNotifications(rows, availableSpace = 0f, shelfHeight = 0f)
|
||||||
|
|
||||||
|
assertThat(maxNotifications).isEqualTo(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun computeMaxKeyguardNotifications_infiniteSpace_returnsAll() {
|
||||||
|
val numberOfRows = 30
|
||||||
|
val rows = createLockscreenRows(numberOfRows)
|
||||||
|
|
||||||
|
val maxNotifications = computeMaxKeyguardNotifications(rows, Float.MAX_VALUE)
|
||||||
|
|
||||||
|
assertThat(maxNotifications).isEqualTo(numberOfRows)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun computeMaxKeyguardNotifications_spaceForOne_returnsOne() {
|
||||||
|
val rowHeight = ROW_HEIGHT
|
||||||
|
val totalSpaceForEachRow = GAP_HEIGHT + rowHeight
|
||||||
|
val shelfHeight =
|
||||||
|
totalSpaceForEachRow / 2 // In this way shelf absence will not leave room for another.
|
||||||
|
val spaceForOne = totalSpaceForEachRow
|
||||||
|
val rows =
|
||||||
|
listOf(
|
||||||
|
createMockRow(rowHeight, visibleOnLockscreen = true),
|
||||||
|
createMockRow(rowHeight, visibleOnLockscreen = true))
|
||||||
|
|
||||||
|
val maxNotifications =
|
||||||
|
computeMaxKeyguardNotifications(
|
||||||
|
rows, availableSpace = spaceForOne, shelfHeight = shelfHeight)
|
||||||
|
|
||||||
|
assertThat(maxNotifications).isEqualTo(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun computeMaxKeyguardNotifications_spaceForOne_shelfUsableForLastNotification_returnsTwo() {
|
||||||
|
val rowHeight = ROW_HEIGHT
|
||||||
|
val totalSpaceForEachRow = GAP_HEIGHT + rowHeight
|
||||||
|
val shelfHeight = totalSpaceForEachRow + NOTIFICATION_PADDING
|
||||||
|
val spaceForOne = totalSpaceForEachRow
|
||||||
|
val rows =
|
||||||
|
listOf(
|
||||||
|
createMockRow(rowHeight, visibleOnLockscreen = true),
|
||||||
|
createMockRow(rowHeight, visibleOnLockscreen = true))
|
||||||
|
|
||||||
|
val maxNotifications =
|
||||||
|
computeMaxKeyguardNotifications(
|
||||||
|
rows, availableSpace = spaceForOne, shelfHeight = shelfHeight)
|
||||||
|
|
||||||
|
assertThat(maxNotifications).isEqualTo(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun computeMaxKeyguardNotifications_invisibleOnLockscreen_returnsZero() {
|
||||||
|
val rows = listOf(createMockRow(visibleOnLockscreen = false))
|
||||||
|
|
||||||
|
val maxNotifications = computeMaxKeyguardNotifications(rows, Float.MAX_VALUE)
|
||||||
|
|
||||||
|
assertThat(maxNotifications).isEqualTo(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun computeMaxKeyguardNotifications_spaceForTwo_returnsTwo() {
|
||||||
|
val rowHeight = ROW_HEIGHT
|
||||||
|
val totalSpaceForEachRow = GAP_HEIGHT + rowHeight
|
||||||
|
val spaceForTwo = totalSpaceForEachRow * 2 + NOTIFICATION_PADDING
|
||||||
|
val rows =
|
||||||
|
listOf(
|
||||||
|
createMockRow(rowHeight, visibleOnLockscreen = true),
|
||||||
|
createMockRow(rowHeight, visibleOnLockscreen = true),
|
||||||
|
createMockRow(rowHeight, visibleOnLockscreen = true))
|
||||||
|
|
||||||
|
val maxNotifications = computeMaxKeyguardNotifications(rows, spaceForTwo, shelfHeight = 0f)
|
||||||
|
|
||||||
|
assertThat(maxNotifications).isEqualTo(2)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun computeHeight_returnsLessThanAvailableSpaceUsedToCalculateMaxNotifications() {
|
||||||
|
val rowHeight = ROW_HEIGHT
|
||||||
|
val shelfHeight = SHELF_HEIGHT
|
||||||
|
val totalSpaceForEachRow = GAP_HEIGHT + rowHeight + NOTIFICATION_PADDING
|
||||||
|
val availableSpace = totalSpaceForEachRow * 2
|
||||||
|
val rows =
|
||||||
|
listOf(
|
||||||
|
createMockRow(rowHeight, visibleOnLockscreen = true),
|
||||||
|
createMockRow(rowHeight, visibleOnLockscreen = true),
|
||||||
|
createMockRow(rowHeight, visibleOnLockscreen = true))
|
||||||
|
|
||||||
|
val maxNotifications = computeMaxKeyguardNotifications(rows, availableSpace, shelfHeight)
|
||||||
|
assertThat(maxNotifications).isEqualTo(2)
|
||||||
|
|
||||||
|
val height = sizeCalculator.computeHeight(stackLayout, maxNotifications, SHELF_HEIGHT)
|
||||||
|
assertThat(height).isAtMost(availableSpace + SHELF_HEIGHT)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun computeHeight_allInvisibleToLockscreen_NotInLockscreen_returnsHigherThanZero() {
|
||||||
|
setOnLockscreen(false)
|
||||||
|
val rowHeight = 10f
|
||||||
|
setupChildren(listOf(createMockRow(rowHeight, visibleOnLockscreen = false)))
|
||||||
|
|
||||||
|
val height =
|
||||||
|
sizeCalculator.computeHeight(
|
||||||
|
stackLayout, maxNotifications = Int.MAX_VALUE, SHELF_HEIGHT)
|
||||||
|
|
||||||
|
assertThat(height).isGreaterThan(rowHeight)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun computeHeight_allInvisibleToLockscreen_onLockscreen_returnsZero() {
|
||||||
|
setOnLockscreen(true)
|
||||||
|
setupChildren(listOf(createMockRow(visibleOnLockscreen = false)))
|
||||||
|
|
||||||
|
val height =
|
||||||
|
sizeCalculator.computeHeight(
|
||||||
|
stackLayout, maxNotifications = Int.MAX_VALUE, SHELF_HEIGHT)
|
||||||
|
|
||||||
|
assertThat(height).isEqualTo(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun computeMaxKeyguardNotifications(
|
||||||
|
rows: List<ExpandableView>,
|
||||||
|
availableSpace: Float,
|
||||||
|
shelfHeight: Float = SHELF_HEIGHT
|
||||||
|
): Int {
|
||||||
|
setupChildren(rows)
|
||||||
|
return sizeCalculator.computeMaxKeyguardNotifications(
|
||||||
|
stackLayout, availableSpace, shelfHeight)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setupChildren(children: List<ExpandableView>) {
|
||||||
|
whenever(stackLayout.getChildAt(any())).thenAnswer { invocation ->
|
||||||
|
val inx = invocation.getArgument<Int>(0)
|
||||||
|
return@thenAnswer children[inx]
|
||||||
|
}
|
||||||
|
whenever(stackLayout.childCount).thenReturn(children.size)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createLockscreenRows(number: Int): List<ExpandableNotificationRow> =
|
||||||
|
(1..number).map { createMockRow(visibleOnLockscreen = true) }.toList()
|
||||||
|
|
||||||
|
private fun createMockRow(
|
||||||
|
height: Float = ROW_HEIGHT,
|
||||||
|
visibleOnLockscreen: Boolean = true,
|
||||||
|
isRemoved: Boolean = false,
|
||||||
|
visibility: Int = VISIBLE,
|
||||||
|
summaryOfSuppressed: Boolean = false
|
||||||
|
): ExpandableNotificationRow {
|
||||||
|
val row = mock(ExpandableNotificationRow::class.java)
|
||||||
|
val entry = mock(NotificationEntry::class.java)
|
||||||
|
val sbn = mock(StatusBarNotification::class.java)
|
||||||
|
whenever(entry.sbn).thenReturn(sbn)
|
||||||
|
whenever(row.entry).thenReturn(entry)
|
||||||
|
whenever(row.isRemoved).thenReturn(isRemoved)
|
||||||
|
whenever(row.visibility).thenReturn(visibility)
|
||||||
|
whenever(notificationLockscreenUserManager.shouldShowOnKeyguard(entry))
|
||||||
|
.thenReturn(visibleOnLockscreen)
|
||||||
|
whenever(groupManager.isSummaryOfSuppressedGroup(sbn)).thenReturn(summaryOfSuppressed)
|
||||||
|
whenever(row.getMinHeight(any())).thenReturn(height.toInt())
|
||||||
|
whenever(row.intrinsicHeight).thenReturn(height.toInt())
|
||||||
|
return row
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setOnLockscreen(onLockscreen: Boolean) {
|
||||||
|
whenever(sysuiStatusBarStateController.state)
|
||||||
|
.thenReturn(
|
||||||
|
if (onLockscreen) {
|
||||||
|
KEYGUARD
|
||||||
|
} else {
|
||||||
|
SHADE
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Default dimensions for tests that don't overwrite them. */
|
||||||
|
companion object {
|
||||||
|
const val GAP_HEIGHT = 12f
|
||||||
|
const val NOTIFICATION_PADDING = 3f
|
||||||
|
const val SHELF_HEIGHT = 14f
|
||||||
|
const val ROW_HEIGHT = SHELF_HEIGHT * 3
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -104,7 +104,6 @@ import com.android.systemui.statusbar.CommandQueue;
|
|||||||
import com.android.systemui.statusbar.KeyguardAffordanceView;
|
import com.android.systemui.statusbar.KeyguardAffordanceView;
|
||||||
import com.android.systemui.statusbar.KeyguardIndicationController;
|
import com.android.systemui.statusbar.KeyguardIndicationController;
|
||||||
import com.android.systemui.statusbar.LockscreenShadeTransitionController;
|
import com.android.systemui.statusbar.LockscreenShadeTransitionController;
|
||||||
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
|
|
||||||
import com.android.systemui.statusbar.NotificationRemoteInputManager;
|
import com.android.systemui.statusbar.NotificationRemoteInputManager;
|
||||||
import com.android.systemui.statusbar.NotificationShadeDepthController;
|
import com.android.systemui.statusbar.NotificationShadeDepthController;
|
||||||
import com.android.systemui.statusbar.NotificationShadeWindowController;
|
import com.android.systemui.statusbar.NotificationShadeWindowController;
|
||||||
@@ -119,12 +118,12 @@ import com.android.systemui.statusbar.notification.ConversationNotificationManag
|
|||||||
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.NotificationEntryManager;
|
||||||
import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
|
import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
|
||||||
import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
|
|
||||||
import com.android.systemui.statusbar.notification.stack.AmbientState;
|
import com.android.systemui.statusbar.notification.stack.AmbientState;
|
||||||
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
|
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
|
||||||
import com.android.systemui.statusbar.notification.stack.NotificationRoundnessManager;
|
import com.android.systemui.statusbar.notification.stack.NotificationRoundnessManager;
|
||||||
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
|
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
|
||||||
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
|
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
|
||||||
|
import com.android.systemui.statusbar.notification.stack.NotificationStackSizeCalculator;
|
||||||
import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager;
|
import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager;
|
||||||
import com.android.systemui.statusbar.policy.ConfigurationController;
|
import com.android.systemui.statusbar.policy.ConfigurationController;
|
||||||
import com.android.systemui.statusbar.policy.KeyguardQsUserSwitchController;
|
import com.android.systemui.statusbar.policy.KeyguardQsUserSwitchController;
|
||||||
@@ -174,8 +173,6 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase {
|
|||||||
@Mock
|
@Mock
|
||||||
private NotificationShelfController mNotificationShelfController;
|
private NotificationShelfController mNotificationShelfController;
|
||||||
@Mock
|
@Mock
|
||||||
private NotificationGroupManagerLegacy mGroupManager;
|
|
||||||
@Mock
|
|
||||||
private KeyguardStatusBarView mKeyguardStatusBar;
|
private KeyguardStatusBarView mKeyguardStatusBar;
|
||||||
@Mock
|
@Mock
|
||||||
private KeyguardUserSwitcherView mUserSwitcherView;
|
private KeyguardUserSwitcherView mUserSwitcherView;
|
||||||
@@ -200,10 +197,6 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase {
|
|||||||
@Mock
|
@Mock
|
||||||
private DynamicPrivacyController mDynamicPrivacyController;
|
private DynamicPrivacyController mDynamicPrivacyController;
|
||||||
@Mock
|
@Mock
|
||||||
private ShadeController mShadeController;
|
|
||||||
@Mock
|
|
||||||
private NotificationLockscreenUserManager mNotificationLockscreenUserManager;
|
|
||||||
@Mock
|
|
||||||
private NotificationEntryManager mNotificationEntryManager;
|
private NotificationEntryManager mNotificationEntryManager;
|
||||||
@Mock
|
@Mock
|
||||||
private StatusBarTouchableRegionManager mStatusBarTouchableRegionManager;
|
private StatusBarTouchableRegionManager mStatusBarTouchableRegionManager;
|
||||||
@@ -336,6 +329,8 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase {
|
|||||||
private SysUiState mSysUiState;
|
private SysUiState mSysUiState;
|
||||||
@Mock
|
@Mock
|
||||||
private NotificationListContainer mNotificationListContainer;
|
private NotificationListContainer mNotificationListContainer;
|
||||||
|
@Mock
|
||||||
|
private NotificationStackSizeCalculator mNotificationStackSizeCalculator;
|
||||||
private NotificationPanelViewController.PanelEventsEmitter mPanelEventsEmitter;
|
private NotificationPanelViewController.PanelEventsEmitter mPanelEventsEmitter;
|
||||||
private Optional<SysUIUnfoldComponent> mSysUIUnfoldComponent = Optional.empty();
|
private Optional<SysUIUnfoldComponent> mSysUIUnfoldComponent = Optional.empty();
|
||||||
private SysuiStatusBarStateController mStatusBarStateController;
|
private SysuiStatusBarStateController mStatusBarStateController;
|
||||||
@@ -466,7 +461,7 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase {
|
|||||||
mFeatureFlags,
|
mFeatureFlags,
|
||||||
coordinator, expansionHandler, mDynamicPrivacyController, mKeyguardBypassController,
|
coordinator, expansionHandler, mDynamicPrivacyController, mKeyguardBypassController,
|
||||||
mFalsingManager, new FalsingCollectorFake(),
|
mFalsingManager, new FalsingCollectorFake(),
|
||||||
mNotificationLockscreenUserManager, mNotificationEntryManager,
|
mNotificationEntryManager,
|
||||||
mKeyguardStateController,
|
mKeyguardStateController,
|
||||||
mStatusBarStateController,
|
mStatusBarStateController,
|
||||||
mStatusBarWindowStateController,
|
mStatusBarWindowStateController,
|
||||||
@@ -484,7 +479,6 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase {
|
|||||||
mKeyguardUserSwitcherComponentFactory,
|
mKeyguardUserSwitcherComponentFactory,
|
||||||
mKeyguardStatusBarViewComponentFactory,
|
mKeyguardStatusBarViewComponentFactory,
|
||||||
mLockscreenShadeTransitionController,
|
mLockscreenShadeTransitionController,
|
||||||
mGroupManager,
|
|
||||||
mNotificationAreaController,
|
mNotificationAreaController,
|
||||||
mAuthController,
|
mAuthController,
|
||||||
mScrimController,
|
mScrimController,
|
||||||
@@ -516,7 +510,8 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase {
|
|||||||
mSysUiState,
|
mSysUiState,
|
||||||
mKeyguardUnlockAnimationController,
|
mKeyguardUnlockAnimationController,
|
||||||
mNotificationListContainer,
|
mNotificationListContainer,
|
||||||
mPanelEventsEmitter);
|
mPanelEventsEmitter,
|
||||||
|
mNotificationStackSizeCalculator);
|
||||||
mNotificationPanelViewController.initDependencies(
|
mNotificationPanelViewController.initDependencies(
|
||||||
mCentralSurfaces,
|
mCentralSurfaces,
|
||||||
() -> {},
|
() -> {},
|
||||||
|
|||||||
Reference in New Issue
Block a user