Snap for 12190349 from 9164534fb9 to 24Q4-release

Change-Id: I04f4e09f968b4c9af7c8ea4822f0ad0c67fd6441
This commit is contained in:
Android Build Coastguard Worker
2024-08-06 23:21:31 +00:00
20 changed files with 416 additions and 466 deletions
@@ -138,6 +138,8 @@ public class BubbleBarController extends IBubblesListener.Stub {
List<RemovedBubble> removedBubbles;
List<String> bubbleKeysInOrder;
Point expandedViewDropTargetSize;
boolean showOverflow;
boolean showOverflowChanged;
// These need to be loaded in the background
BubbleBarBubble addedBubble;
@@ -156,6 +158,8 @@ public class BubbleBarController extends IBubblesListener.Stub {
removedBubbles = update.removedBubbles;
bubbleKeysInOrder = update.bubbleKeysInOrder;
expandedViewDropTargetSize = update.expandedViewDropTargetSize;
showOverflow = update.showOverflow;
showOverflowChanged = update.showOverflowChanged;
}
}
@@ -271,7 +275,13 @@ public class BubbleBarController extends IBubblesListener.Stub {
BubbleBarBubble bubbleToSelect = null;
if (update.addedBubble != null && update.removedBubbles.size() == 1) {
if (Flags.enableOptionalBubbleOverflow()
&& update.showOverflowChanged && !update.showOverflow && update.addedBubble != null
&& update.removedBubbles.isEmpty()) {
// A bubble was added from the overflow (& now it's empty / not showing)
mBubbles.put(update.addedBubble.getKey(), update.addedBubble);
mBubbleBarViewController.removeOverflowAndAddBubble(update.addedBubble);
} else if (update.addedBubble != null && update.removedBubbles.size() == 1) {
// we're adding and removing a bubble at the same time. handle this as a single update.
RemovedBubble removedBubble = update.removedBubbles.get(0);
BubbleBarBubble bubbleToRemove = mBubbles.remove(removedBubble.getKey());
@@ -285,11 +295,17 @@ public class BubbleBarController extends IBubblesListener.Stub {
Log.w(TAG, "trying to remove bubble that doesn't exist: " + removedBubble.getKey());
}
} else {
boolean overflowNeedsToBeAdded = Flags.enableOptionalBubbleOverflow()
&& update.showOverflowChanged && update.showOverflow;
if (!update.removedBubbles.isEmpty()) {
for (int i = 0; i < update.removedBubbles.size(); i++) {
RemovedBubble removedBubble = update.removedBubbles.get(i);
BubbleBarBubble bubble = mBubbles.remove(removedBubble.getKey());
if (bubble != null) {
if (bubble != null && overflowNeedsToBeAdded) {
// First removal, show the overflow
overflowNeedsToBeAdded = false;
mBubbleBarViewController.addOverflowAndRemoveBubble(bubble);
} else if (bubble != null) {
mBubbleBarViewController.removeBubble(bubble);
} else {
Log.w(TAG, "trying to remove bubble that doesn't exist: "
@@ -302,6 +318,11 @@ public class BubbleBarController extends IBubblesListener.Stub {
mBubbleBarViewController.addBubble(update.addedBubble, isExpanding,
suppressAnimation);
}
if (Flags.enableOptionalBubbleOverflow()
&& update.showOverflowChanged
&& update.showOverflow != mBubbleBarViewController.isOverflowAdded()) {
mBubbleBarViewController.showOverflow(update.showOverflow);
}
}
// if a bubble was updated upstream, but removed before the update was received, add it back
@@ -333,6 +354,9 @@ public class BubbleBarController extends IBubblesListener.Stub {
}
}
}
if (Flags.enableOptionalBubbleOverflow() && update.initialState && update.showOverflow) {
mBubbleBarViewController.showOverflow(true);
}
// Adds and removals have happened, update visibility before any other visual changes.
mBubbleBarViewController.setHiddenForBubbles(mBubbles.isEmpty());
@@ -715,11 +715,13 @@ public class BubbleBarView extends FrameLayout {
public void addBubble(BubbleView bubble) {
FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams((int) mIconSize, (int) mIconSize,
Gravity.LEFT);
final int index = bubble.isOverflow() ? getChildCount() : 0;
if (isExpanded()) {
// if we're expanded scale the new bubble in
bubble.setScaleX(0f);
bubble.setScaleY(0f);
addView(bubble, 0, lp);
addView(bubble, index, lp);
bubble.showDotIfNeeded(/* animate= */ false);
mBubbleAnimator = new BubbleAnimator(mIconSize, mExpandedBarIconsSpacing,
@@ -748,23 +750,33 @@ public class BubbleBarView extends FrameLayout {
};
mBubbleAnimator.animateNewBubble(indexOfChild(mSelectedBubbleView), listener);
} else {
addView(bubble, 0, lp);
addView(bubble, index, lp);
}
}
/** Add a new bubble and remove an old bubble from the bubble bar. */
public void addBubbleAndRemoveBubble(View addedBubble, View removedBubble) {
public void addBubbleAndRemoveBubble(BubbleView addedBubble, BubbleView removedBubble) {
FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams((int) mIconSize, (int) mIconSize,
Gravity.LEFT);
boolean isOverflowSelected = mSelectedBubbleView.isOverflow();
boolean removingOverflow = removedBubble.isOverflow();
boolean addingOverflow = addedBubble.isOverflow();
if (!isExpanded()) {
removeView(removedBubble);
addView(addedBubble, 0, lp);
int index = addingOverflow ? getChildCount() : 0;
addView(addedBubble, index, lp);
return;
}
int index = addingOverflow ? getChildCount() : 0;
addedBubble.setScaleX(0f);
addedBubble.setScaleY(0f);
addView(addedBubble, 0, lp);
addView(addedBubble, index, lp);
if (isOverflowSelected && removingOverflow) {
// The added bubble will be selected
mSelectedBubbleView = addedBubble;
}
int indexOfSelectedBubble = indexOfChild(mSelectedBubbleView);
int indexOfBubbleToRemove = indexOfChild(removedBubble);
@@ -924,7 +936,7 @@ public class BubbleBarView extends FrameLayout {
final float currentWidth = getWidth();
final float expandedWidth = expandedWidth();
final float collapsedWidth = collapsedWidth();
int bubbleCount = getChildCount();
int childCount = getChildCount();
float viewBottom = mBubbleBarBounds.height() + (isExpanded() ? mPointerSize : 0);
float bubbleBarAnimatedTop = viewBottom - getBubbleBarHeight();
// When translating X & Y the scale is ignored, so need to deduct it from the translations
@@ -932,7 +944,7 @@ public class BubbleBarView extends FrameLayout {
final boolean onLeft = bubbleBarLocation.isOnLeft(isLayoutRtl());
// elevation state is opposite to widthState - when expanded all icons are flat
float elevationState = (1 - widthState);
for (int i = 0; i < bubbleCount; i++) {
for (int i = 0; i < childCount; i++) {
BubbleView bv = (BubbleView) getChildAt(i);
if (bv == mDraggedBubbleView || bv == mDismissedByDragBubbleView) {
// Skip the dragged bubble. Its translation is managed by the drag controller.
@@ -951,9 +963,9 @@ public class BubbleBarView extends FrameLayout {
bv.setTranslationY(ty);
// the position of the bubble when the bar is fully expanded
final float expandedX = getExpandedBubbleTranslationX(i, bubbleCount, onLeft);
final float expandedX = getExpandedBubbleTranslationX(i, childCount, onLeft);
// the position of the bubble when the bar is fully collapsed
final float collapsedX = getCollapsedBubbleTranslationX(i, bubbleCount, onLeft);
final float collapsedX = getCollapsedBubbleTranslationX(i, childCount, onLeft);
// slowly animate elevation while keeping correct Z ordering
float fullElevationForChild = (MAX_BUBBLES * mBubbleElevation) - i;
@@ -981,13 +993,10 @@ public class BubbleBarView extends FrameLayout {
final float collapsedBarShift = onLeft ? 0 : currentWidth - collapsedWidth;
final float targetX = collapsedX + collapsedBarShift;
bv.setTranslationX(widthState * (expandedX - targetX) + targetX);
// If we're fully collapsed, hide all bubbles except for the first 2. If there are
// only 2 bubbles, hide the second bubble as well because it's the overflow.
// If we're fully collapsed, hide all bubbles except for the first 2, excluding
// the overflow.
if (widthState == 0) {
if (i > MAX_VISIBLE_BUBBLES_COLLAPSED - 1) {
bv.setAlpha(0);
} else if (i == MAX_VISIBLE_BUBBLES_COLLAPSED - 1
&& bubbleCount == MAX_VISIBLE_BUBBLES_COLLAPSED) {
if (bv.isOverflow() || i > MAX_VISIBLE_BUBBLES_COLLAPSED - 1) {
bv.setAlpha(0);
} else {
bv.setAlpha(1);
@@ -1043,22 +1052,26 @@ public class BubbleBarView extends FrameLayout {
return translationX - getScaleIconShift();
}
private float getCollapsedBubbleTranslationX(int bubbleIndex, int bubbleCount, boolean onLeft) {
if (bubbleIndex < 0 || bubbleIndex >= bubbleCount) {
private float getCollapsedBubbleTranslationX(int bubbleIndex, int childCount, boolean onLeft) {
if (bubbleIndex < 0 || bubbleIndex >= childCount) {
return 0;
}
float translationX;
if (onLeft) {
// Shift the first bubble only if there are more bubbles in addition to overflow
translationX = mBubbleBarPadding + (
bubbleIndex == 0 && bubbleCount > MAX_VISIBLE_BUBBLES_COLLAPSED
? mIconOverlapAmount : 0);
// Shift the first bubble only if there are more bubbles
if (bubbleIndex == 0 && getBubbleChildCount() >= MAX_VISIBLE_BUBBLES_COLLAPSED) {
translationX = mIconOverlapAmount;
} else {
translationX = 0f;
}
} else {
translationX = mBubbleBarPadding + (
bubbleIndex == 0 || bubbleCount <= MAX_VISIBLE_BUBBLES_COLLAPSED
? 0 : mIconOverlapAmount);
if (bubbleIndex == 1 && getBubbleChildCount() >= MAX_VISIBLE_BUBBLES_COLLAPSED) {
translationX = mIconOverlapAmount;
} else {
translationX = 0f;
}
}
return translationX - getScaleIconShift();
return mBubbleBarPadding + translationX - getScaleIconShift();
}
/**
@@ -1256,15 +1269,20 @@ public class BubbleBarView extends FrameLayout {
}
private float collapsedWidth() {
final int childCount = getChildCount();
final int bubbleChildCount = getBubbleChildCount();
final float horizontalPadding = 2 * mBubbleBarPadding;
// If there are more than 2 bubbles, the first 2 should be visible when collapsed.
// Otherwise just the first bubble should be visible because we don't show the overflow.
return childCount > MAX_VISIBLE_BUBBLES_COLLAPSED
// If there are more than 2 bubbles, the first 2 should be visible when collapsed,
// excluding the overflow.
return bubbleChildCount >= MAX_VISIBLE_BUBBLES_COLLAPSED
? getScaledIconSize() + mIconOverlapAmount + horizontalPadding
: getScaledIconSize() + horizontalPadding;
}
/** Returns the child count excluding the overflow if it's present. */
private int getBubbleChildCount() {
return hasOverflow() ? getChildCount() - 1 : getChildCount();
}
private float getBubbleBarExpandedHeight() {
return getBubbleBarCollapsedHeight() + mPointerSize;
}
@@ -1303,8 +1321,8 @@ public class BubbleBarView extends FrameLayout {
return mIsAnimatingNewBubble;
}
private boolean hasOverview() {
// Overview is always the last bubble
private boolean hasOverflow() {
// Overflow is always the last bubble
View lastChild = getChildAt(getChildCount() - 1);
if (lastChild instanceof BubbleView bubbleView) {
return bubbleView.getBubble() instanceof BubbleBarOverflow;
@@ -1336,7 +1354,7 @@ public class BubbleBarView extends FrameLayout {
CharSequence contentDesc = firstChild != null ? firstChild.getContentDescription() : "";
// Don't count overflow if it exists
int bubbleCount = getChildCount() - (hasOverview() ? 1 : 0);
int bubbleCount = getChildCount() - (hasOverflow() ? 1 : 0);
if (bubbleCount > 1) {
contentDesc = getResources().getString(R.string.bubble_bar_description_multiple_bubbles,
contentDesc, bubbleCount - 1);
@@ -92,6 +92,8 @@ public class BubbleBarViewController {
private boolean mHiddenForNoBubbles = true;
private boolean mShouldShowEducation;
public boolean mOverflowAdded;
private BubbleBarViewAnimator mBubbleBarViewAnimator;
private final TimeSource mTimeSource = System::currentTimeMillis;
@@ -123,7 +125,6 @@ public class BubbleBarViewController {
mBubbleBarClickListener = v -> expandBubbleBar();
mBubbleDragController.setupBubbleBarView(mBarView);
mOverflowBubble = bubbleControllers.bubbleCreator.createOverflow(mBarView);
addOverflow();
mBarView.setOnClickListener(mBubbleBarClickListener);
mBarView.addOnLayoutChangeListener(
(v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
@@ -494,13 +495,44 @@ public class BubbleBarViewController {
}
}
/**
* Adds the overflow view to the bubble bar.
*/
public void addOverflow() {
mBarView.addBubble(mOverflowBubble.getView());
/** Whether the overflow view is added to the bubble bar. */
public boolean isOverflowAdded() {
return mOverflowAdded;
}
/** Shows or hides the overflow view. */
public void showOverflow(boolean showOverflow) {
if (mOverflowAdded == showOverflow) return;
mOverflowAdded = showOverflow;
if (mOverflowAdded) {
mBarView.addBubble(mOverflowBubble.getView());
mOverflowBubble.getView().setOnClickListener(mBubbleClickListener);
mOverflowBubble.getView().setController(mBubbleViewController);
} else {
mBarView.removeBubble(mOverflowBubble.getView());
mOverflowBubble.getView().setOnClickListener(null);
mOverflowBubble.getView().setController(null);
}
}
/** Adds the overflow view to the bubble bar while animating a view away. */
public void addOverflowAndRemoveBubble(BubbleBarBubble removedBubble) {
if (mOverflowAdded) return;
mOverflowAdded = true;
mBarView.addBubbleAndRemoveBubble(mOverflowBubble.getView(), removedBubble.getView());
mOverflowBubble.getView().setOnClickListener(mBubbleClickListener);
mOverflowBubble.getView().setController(mBubbleViewController);
removedBubble.getView().setController(null);
}
/** Removes the overflow view to the bubble bar while animating a view in. */
public void removeOverflowAndAddBubble(BubbleBarBubble addedBubble) {
if (!mOverflowAdded) return;
mOverflowAdded = false;
mBarView.addBubbleAndRemoveBubble(addedBubble.getView(), mOverflowBubble.getView());
addedBubble.getView().setOnClickListener(mBubbleClickListener);
addedBubble.getView().setController(mBubbleViewController);
mOverflowBubble.getView().setController(null);
}
/**
@@ -74,6 +74,7 @@ public class BubbleView extends ConstraintLayout {
private boolean mOnLeft = false;
private BubbleBarItem mBubble;
private boolean mIsOverflow;
private Bitmap mIcon;
@@ -271,12 +272,18 @@ public class BubbleView extends ConstraintLayout {
*/
public void setOverflow(BubbleBarOverflow overflow, Bitmap bitmap) {
mBubble = overflow;
mIsOverflow = true;
mIcon = bitmap;
updateBubbleIcon();
mAppIcon.setVisibility(GONE); // Overflow doesn't show the app badge
setContentDescription(getResources().getString(R.string.bubble_bar_overflow_description));
}
/** Whether this view represents the overflow button. */
public boolean isOverflow() {
return mIsOverflow;
}
/** Returns the bubble being rendered in this view. */
@Nullable
public BubbleBarItem getBubble() {
@@ -989,7 +989,6 @@ public abstract class AbsSwipeUpHandler<T extends RecentsViewContainer,
dp = dp.copy(mContext);
}
dp.updateInsets(targets.homeContentInsets);
dp.updateIsSeascape(mContext);
initTransitionEndpoints(dp);
orientationState.setMultiWindowMode(dp.isMultiWindowMode);
}
@@ -782,7 +782,6 @@ abstract class TutorialController implements BackGestureAttemptCallback,
(RelativeLayout.LayoutParams) mFakeHotseatView.getLayoutParams();
if (!mTutorialFragment.isLargeScreen()) {
DeviceProfile dp = mTutorialFragment.getDeviceProfile();
dp.updateIsSeascape(mContext);
hotseatLayoutParams.addRule(dp.isLandscape
? (dp.isSeascape()
@@ -140,15 +140,11 @@ public abstract class BaseDraggingActivity extends BaseActivity
}
protected void onDeviceProfileInitiated() {
if (mDeviceProfile.isVerticalBarLayout()) {
mDeviceProfile.updateIsSeascape(this);
}
}
@Override
public void onDisplayInfoChanged(Context context, Info info, int flags) {
if ((flags & CHANGE_ROTATION) != 0 && mDeviceProfile.isVerticalBarLayout()) {
mDeviceProfile.updateIsSeascape(this);
reapplyUi();
}
}
+1 -22
View File
@@ -65,7 +65,6 @@ import com.android.launcher3.responsive.ResponsiveSpec.Companion.ResponsiveSpecT
import com.android.launcher3.responsive.ResponsiveSpec.DimensionType;
import com.android.launcher3.responsive.ResponsiveSpecsProvider;
import com.android.launcher3.util.CellContentDimensions;
import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.DisplayController.Info;
import com.android.launcher3.util.IconSizeSteps;
import com.android.launcher3.util.ResourceHelper;
@@ -298,9 +297,6 @@ public class DeviceProfile {
// the widgetView, such that the actual view size is same as the widget size.
public final Rect widgetPadding = new Rect();
// When true, nav bar is on the left side of the screen.
private boolean mIsSeascape;
// Notification dots
public final DotRenderer mDotRendererWorkSpace;
public final DotRenderer mDotRendererAllApps;
@@ -2007,25 +2003,8 @@ public class DeviceProfile {
return isLandscape && transposeLayoutWithOrientation;
}
/**
* Updates orientation information and returns true if it has changed from the previous value.
*/
public boolean updateIsSeascape(Context context) {
if (isVerticalBarLayout()) {
boolean isSeascape = DisplayController.INSTANCE.get(context)
.getInfo().rotation == Surface.ROTATION_270;
if (mIsSeascape != isSeascape) {
mIsSeascape = isSeascape;
// Hotseat changing sides requires updating workspace left/right paddings
updateWorkspacePadding();
return true;
}
}
return false;
}
public boolean isSeascape() {
return isVerticalBarLayout() && mIsSeascape;
return rotationHint == Surface.ROTATION_270 && isVerticalBarLayout();
}
public boolean shouldFadeAdjacentWorkspaceScreens() {
@@ -62,6 +62,10 @@ class AllAppsRecyclerViewPool<T> : RecycledViewPool() where T : Context, T : Act
fun preInflateAllAppsViewHolders(context: T) {
val appsView = context.appsView ?: return
val activeRv: RecyclerView = appsView.activeRecyclerView ?: return
val preInflateCount = getPreinflateCount(context)
if (preInflateCount <= 0) {
return
}
if (activeRv.layoutManager == null) {
if (BuildConfig.IS_STUDIO_BUILD) {
@@ -99,7 +103,12 @@ class AllAppsRecyclerViewPool<T> : RecycledViewPool() where T : Context, T : Act
override fun getLayoutManager(): RecyclerView.LayoutManager? = null
}
preInflateAllAppsViewHolders(adapter, BaseAllAppsAdapter.VIEW_TYPE_ICON, activeRv) {
preInflateAllAppsViewHolders(
adapter,
BaseAllAppsAdapter.VIEW_TYPE_ICON,
activeRv,
preInflateCount
) {
getPreinflateCount(context)
}
}
@@ -109,10 +118,10 @@ class AllAppsRecyclerViewPool<T> : RecycledViewPool() where T : Context, T : Act
adapter: RecyclerView.Adapter<*>,
viewType: Int,
parent: ViewGroup,
preInflationCount: Int,
preInflationCountProvider: () -> Int
) {
val preinflationCount = preInflationCountProvider.invoke()
if (preinflationCount <= 0) {
if (preInflationCount <= 0) {
return
}
mCancellableTask?.cancel()
@@ -121,7 +130,7 @@ class AllAppsRecyclerViewPool<T> : RecycledViewPool() where T : Context, T : Act
CancellableTask(
{
val list: ArrayList<ViewHolder> = ArrayList()
for (i in 0 until preinflationCount) {
for (i in 0 until preInflationCount) {
if (task?.canceled == true) {
break
}
@@ -132,8 +141,8 @@ class AllAppsRecyclerViewPool<T> : RecycledViewPool() where T : Context, T : Act
MAIN_EXECUTOR,
{ viewHolders ->
// Run preInflationCountProvider again as the needed VH might have changed
val newPreinflationCount = preInflationCountProvider.invoke()
for (i in 0 until minOf(viewHolders.size, newPreinflationCount)) {
val newPreInflationCount = preInflationCountProvider.invoke()
for (i in 0 until minOf(viewHolders.size, newPreInflationCount)) {
putRecycledView(viewHolders[i])
}
}
@@ -104,7 +104,7 @@ class HotseatReorderUnitTest {
val cl = cellLayoutBuilder.createCellLayout(board.width, board.height, false)
// The views have to be sorted or the result can vary
board.icons
.map(IconPoint::getCoord)
.map(IconPoint::coord)
.sortedWith(
Comparator.comparing { p: Any -> (p as Point).x }
.thenComparing { p: Any -> (p as Point).y }
@@ -120,9 +120,7 @@ class HotseatReorderUnitTest {
)
}
board.widgets
.sortedWith(
Comparator.comparing(WidgetRect::getCellX).thenComparing(WidgetRect::getCellY)
)
.sortedWith(Comparator.comparing(WidgetRect::cellX).thenComparing(WidgetRect::cellY))
.forEach { widget ->
addViewInCellLayout(
cl,
@@ -0,0 +1,63 @@
/*
* Copyright (C) 2023 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.launcher3.celllayout.board
import android.graphics.Point
import android.graphics.Rect
/** Represents a widget in a CellLayoutBoard */
data class WidgetRect(
val type: Char,
val bounds: Rect,
) {
val spanX: Int = bounds.right - bounds.left + 1
val spanY: Int = bounds.top - bounds.bottom + 1
val cellY: Int = bounds.bottom
val cellX: Int = bounds.left
fun shouldIgnore() = type == CellType.IGNORE
fun contains(x: Int, y: Int) = bounds.contains(x, y)
}
/**
* [A-Z]: Represents a folder and number of icons in the folder is represented by the order of
* letter in the alphabet, A=2, B=3, C=4 ... etc.
*/
data class FolderPoint(val coord: Point, val type: Char) {
val numberIconsInside: Int = type.code - 'A'.code + 2
}
/** Represents an icon in a CellLayoutBoard */
data class IconPoint(val coord: Point, val type: Char = CellType.ICON)
object CellType {
// The cells marked by this will be filled by 1x1 widgets and will be ignored when
// validating
const val IGNORE = 'x'
// The cells marked by this will be filled by app icons
const val ICON = 'i'
// The cells marked by FOLDER will be filled by folders with 27 app icons inside
const val FOLDER = 'Z'
// Empty space
const val EMPTY = '-'
// Widget that will be saved as "main widget" for easier retrieval
const val MAIN_WIDGET = 'm' // Everything else will be consider a widget
}
@@ -88,7 +88,7 @@ public class CellLayoutBoard implements Comparable<CellLayoutBoard> {
public WidgetRect getWidgetOfType(char type) {
return mWidgetsRects.stream()
.filter(widgetRect -> widgetRect.mType == type).findFirst().orElse(null);
.filter(widgetRect -> widgetRect.getType() == type).findFirst().orElse(null);
}
public WidgetRect getWidgetAt(int x, int y) {
@@ -117,8 +117,8 @@ public class CellLayoutBoard implements Comparable<CellLayoutBoard> {
}
private void removeWidgetFromBoard(WidgetRect widget) {
for (int xi = widget.mBounds.left; xi <= widget.mBounds.right; xi++) {
for (int yi = widget.mBounds.bottom; yi <= widget.mBounds.top; yi++) {
for (int xi = widget.getBounds().left; xi <= widget.getBounds().right; xi++) {
for (int yi = widget.getBounds().bottom; yi <= widget.getBounds().top; yi++) {
mWidget[xi][yi] = '-';
}
}
@@ -127,7 +127,7 @@ public class CellLayoutBoard implements Comparable<CellLayoutBoard> {
private void removeOverlappingItems(Rect rect) {
// Remove overlapping widgets and remove them from the board
mWidgetsRects = mWidgetsRects.stream().filter(widget -> {
if (rect.intersect(widget.mBounds)) {
if (rect.intersect(widget.getBounds())) {
removeWidgetFromBoard(widget);
return false;
}
@@ -135,8 +135,8 @@ public class CellLayoutBoard implements Comparable<CellLayoutBoard> {
}).collect(Collectors.toList());
// Remove overlapping icons and remove them from the board
mIconPoints = mIconPoints.stream().filter(iconPoint -> {
int x = iconPoint.coord.x;
int y = iconPoint.coord.y;
int x = iconPoint.getCoord().x;
int y = iconPoint.getCoord().y;
if (rect.contains(x, y)) {
mWidget[x][y] = '-';
return false;
@@ -146,8 +146,8 @@ public class CellLayoutBoard implements Comparable<CellLayoutBoard> {
// Remove overlapping folders and remove them from the board
mFolderPoints = mFolderPoints.stream().filter(folderPoint -> {
int x = folderPoint.coord.x;
int y = folderPoint.coord.y;
int x = folderPoint.getCoord().x;
int y = folderPoint.getCoord().y;
if (rect.contains(x, y)) {
mWidget[x][y] = '-';
return false;
@@ -159,7 +159,7 @@ public class CellLayoutBoard implements Comparable<CellLayoutBoard> {
private void removeOverlappingItems(Point p) {
// Remove overlapping widgets and remove them from the board
mWidgetsRects = mWidgetsRects.stream().filter(widget -> {
if (IdenticalBoardComparator.Companion.touchesPoint(widget.mBounds, p)) {
if (IdenticalBoardComparator.Companion.touchesPoint(widget.getBounds(), p)) {
removeWidgetFromBoard(widget);
return false;
}
@@ -167,8 +167,8 @@ public class CellLayoutBoard implements Comparable<CellLayoutBoard> {
}).collect(Collectors.toList());
// Remove overlapping icons and remove them from the board
mIconPoints = mIconPoints.stream().filter(iconPoint -> {
int x = iconPoint.coord.x;
int y = iconPoint.coord.y;
int x = iconPoint.getCoord().x;
int y = iconPoint.getCoord().y;
if (p.x == x && p.y == y) {
mWidget[x][y] = '-';
return false;
@@ -178,8 +178,8 @@ public class CellLayoutBoard implements Comparable<CellLayoutBoard> {
// Remove overlapping folders and remove them from the board
mFolderPoints = mFolderPoints.stream().filter(folderPoint -> {
int x = folderPoint.coord.x;
int y = folderPoint.coord.y;
int x = folderPoint.getCoord().x;
int y = folderPoint.getCoord().y;
if (p.x == x && p.y == y) {
mWidget[x][y] = '-';
return false;
@@ -226,7 +226,7 @@ public class CellLayoutBoard implements Comparable<CellLayoutBoard> {
public void removeItem(char type) {
mWidgetsRects.stream()
.filter(widgetRect -> widgetRect.mType == type)
.filter(widgetRect -> widgetRect.getType() == type)
.forEach(widgetRect -> removeOverlappingItems(
new Point(widgetRect.getCellX(), widgetRect.getCellY())));
}
@@ -365,10 +365,10 @@ public class CellLayoutBoard implements Comparable<CellLayoutBoard> {
board.mWidth = lines[0].length();
board.mWidgetsRects = getRects(board.mWidget);
board.mWidgetsRects.forEach(widgetRect -> {
if (widgetRect.mType == CellType.MAIN_WIDGET) {
if (widgetRect.getType() == CellType.MAIN_WIDGET) {
board.mMain = widgetRect;
}
board.mWidgetsMap.put(widgetRect.mType, widgetRect);
board.mWidgetsMap.put(widgetRect.getType(), widgetRect);
});
board.mIconPoints = getIconPoints(board.mWidget);
board.mFolderPoints = getFolderPoints(board.mWidget);
@@ -1,32 +0,0 @@
/*
* Copyright (C) 2023 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.launcher3.celllayout.board;
public class CellType {
// The cells marked by this will be filled by 1x1 widgets and will be ignored when
// validating
public static final char IGNORE = 'x';
// The cells marked by this will be filled by app icons
public static final char ICON = 'i';
// The cells marked by FOLDER will be filled by folders with 27 app icons inside
public static final char FOLDER = 'Z';
// Empty space
public static final char EMPTY = '-';
// Widget that will be saved as "main widget" for easier retrieval
public static final char MAIN_WIDGET = 'm';
// Everything else will be consider a widget
}
@@ -1,37 +0,0 @@
/*
* Copyright (C) 2023 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.launcher3.celllayout.board;
import android.graphics.Point;
public class FolderPoint {
public Point coord;
public char mType;
public FolderPoint(Point coord, char type) {
this.coord = coord;
mType = type;
}
/**
* [A-Z]: Represents a folder and number of icons in the folder is represented by
* the order of letter in the alphabet, A=2, B=3, C=4 ... etc.
*/
public int getNumberIconsInside() {
return (mType - 'A') + 2;
}
}
@@ -1,45 +0,0 @@
/*
* Copyright (C) 2023 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.launcher3.celllayout.board;
import android.graphics.Point;
public class IconPoint {
public Point coord;
public char mType;
public IconPoint(Point coord, char type) {
this.coord = coord;
mType = type;
}
public char getType() {
return mType;
}
public void setType(char type) {
mType = type;
}
public Point getCoord() {
return coord;
}
public void setCoord(Point coord) {
this.coord = coord;
}
}
@@ -26,11 +26,11 @@ class IdenticalBoardComparator : Comparator<CellLayoutBoard> {
/** Converts a list of WidgetRect into a map of the count of different widget.bounds */
private fun widgetsToBoundsMap(widgets: List<WidgetRect>) =
widgets.groupingBy { it.mBounds }.eachCount()
widgets.groupingBy { it.bounds }.eachCount()
/** Converts a list of IconPoint into a map of the count of different icon.coord */
private fun iconsToPosCountMap(widgets: List<IconPoint>) =
widgets.groupingBy { it.getCoord() }.eachCount()
widgets.groupingBy { it.coord }.eachCount()
override fun compare(
cellLayoutBoard: CellLayoutBoard,
@@ -47,7 +47,7 @@ class IdenticalBoardComparator : Comparator<CellLayoutBoard> {
widgetsToBoundsMap(
otherCellLayoutBoard.widgets
.filter { !it.shouldIgnore() }
.filter { !overlapsWithIgnored(ignoredRectangles, it.mBounds) }
.filter { !overlapsWithIgnored(ignoredRectangles, it.bounds) }
)
if (widgetsMap != otherWidgetMap) {
@@ -1,192 +0,0 @@
/*
* Copyright (C) 2023 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.launcher3.celllayout.board;
import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
import static com.android.launcher3.ui.TestViewHelpers.findWidgetProvider;
import static com.android.launcher3.util.WidgetUtils.createWidgetInfo;
import android.content.ComponentName;
import android.content.Context;
import android.graphics.Rect;
import android.os.Process;
import android.os.UserHandle;
import android.util.Log;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.celllayout.FavoriteItemsTransaction;
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.model.data.FolderInfo;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
import java.util.function.Supplier;
import java.util.stream.IntStream;
public class TestWorkspaceBuilder {
private static final String TAG = "CellLayoutBoardBuilder";
private static final String TEST_ACTIVITY_PACKAGE_PREFIX = "com.android.launcher3.tests.";
private ComponentName mAppComponentName = new ComponentName(
"com.google.android.calculator", "com.android.calculator2.Calculator");
private UserHandle mMyUser;
private Context mContext;
public TestWorkspaceBuilder(Context context) {
mMyUser = Process.myUserHandle();
mContext = context;
}
/**
* Fills the given rect in WidgetRect with 1x1 widgets. This is useful to equalize cases.
*/
private FavoriteItemsTransaction fillWithWidgets(WidgetRect widgetRect,
FavoriteItemsTransaction transaction, int screenId) {
int initX = widgetRect.getCellX();
int initY = widgetRect.getCellY();
for (int x = initX; x < initX + widgetRect.getSpanX(); x++) {
for (int y = initY; y < initY + widgetRect.getSpanY(); y++) {
try {
// this widgets are filling, we don't care if we can't place them
transaction.addItem(createWidgetInCell(
new WidgetRect(CellType.IGNORE,
new Rect(x, y, x, y)), screenId));
} catch (Exception e) {
Log.d(TAG, "Unable to place filling widget at " + x + "," + y);
}
}
}
return transaction;
}
private AppInfo getApp() {
return new AppInfo(mAppComponentName, "test icon", mMyUser,
AppInfo.makeLaunchIntent(mAppComponentName));
}
/**
* Helper to set the app to use for the test workspace,
* using activity-alias from AndroidManifest-common.
* @param testAppName the android:name field of the test app activity-alias to use
*/
public void setTestAppActivityAlias(String testAppName) {
this.mAppComponentName = new ComponentName(
getInstrumentation().getContext().getPackageName(),
TEST_ACTIVITY_PACKAGE_PREFIX + testAppName
);
}
private void addCorrespondingWidgetRect(WidgetRect widgetRect,
FavoriteItemsTransaction transaction, int screenId) {
if (widgetRect.mType == 'x') {
fillWithWidgets(widgetRect, transaction, screenId);
} else {
transaction.addItem(createWidgetInCell(widgetRect, screenId));
}
}
/**
* Builds the given board into the transaction
*/
public FavoriteItemsTransaction buildFromBoard(CellLayoutBoard board,
FavoriteItemsTransaction transaction, final int screenId) {
board.getWidgets().forEach(
(widgetRect) -> addCorrespondingWidgetRect(widgetRect, transaction, screenId));
board.getIcons().forEach((iconPoint) ->
transaction.addItem(() -> createIconInCell(iconPoint, screenId))
);
board.getFolders().forEach((folderPoint) ->
transaction.addItem(() -> createFolderInCell(folderPoint, screenId))
);
return transaction;
}
/**
* Fills the hotseat row with apps instead of suggestions, for this to work the workspace should
* be clean otherwise this doesn't overrides the existing icons.
*/
public FavoriteItemsTransaction fillHotseatIcons(FavoriteItemsTransaction transaction) {
IntStream.range(0, InvariantDeviceProfile.INSTANCE.get(mContext).numDatabaseHotseatIcons)
.forEach(i -> transaction.addItem(() -> getHotseatValues(i)));
return transaction;
}
private Supplier<ItemInfo> createWidgetInCell(
WidgetRect widgetRect, int screenId) {
// Create the widget lazily since the appWidgetId can get lost during setup
return () -> {
LauncherAppWidgetProviderInfo info = findWidgetProvider(false);
LauncherAppWidgetInfo item = createWidgetInfo(info, getApplicationContext(), true);
item.cellX = widgetRect.getCellX();
item.cellY = widgetRect.getCellY();
item.spanX = widgetRect.getSpanX();
item.spanY = widgetRect.getSpanY();
item.screenId = screenId;
return item;
};
}
public FolderInfo createFolderInCell(FolderPoint folderPoint, int screenId) {
FolderInfo folderInfo = new FolderInfo();
folderInfo.screenId = screenId;
folderInfo.container = LauncherSettings.Favorites.CONTAINER_DESKTOP;
folderInfo.cellX = folderPoint.coord.x;
folderInfo.cellY = folderPoint.coord.y;
folderInfo.minSpanY = folderInfo.minSpanX = folderInfo.spanX = folderInfo.spanY = 1;
folderInfo.setOption(FolderInfo.FLAG_MULTI_PAGE_ANIMATION, true, null);
for (int i = 0; i < folderPoint.getNumberIconsInside(); i++) {
folderInfo.add(getDefaultWorkspaceItem(screenId), false);
}
return folderInfo;
}
private WorkspaceItemInfo getDefaultWorkspaceItem(int screenId) {
WorkspaceItemInfo item = new WorkspaceItemInfo(getApp());
item.screenId = screenId;
item.minSpanY = item.minSpanX = item.spanX = item.spanY = 1;
item.container = LauncherSettings.Favorites.CONTAINER_DESKTOP;
return item;
}
private ItemInfo createIconInCell(IconPoint iconPoint, int screenId) {
WorkspaceItemInfo item = new WorkspaceItemInfo(getApp());
item.screenId = screenId;
item.cellX = iconPoint.getCoord().x;
item.cellY = iconPoint.getCoord().y;
item.minSpanY = item.minSpanX = item.spanX = item.spanY = 1;
item.container = LauncherSettings.Favorites.CONTAINER_DESKTOP;
return item;
}
private ItemInfo getHotseatValues(int x) {
WorkspaceItemInfo item = new WorkspaceItemInfo(getApp());
item.cellX = x;
item.cellY = 0;
item.minSpanY = item.minSpanX = item.spanX = item.spanY = 1;
item.rank = x;
item.screenId = x;
item.container = LauncherSettings.Favorites.CONTAINER_HOTSEAT;
return item;
}
}
@@ -0,0 +1,191 @@
/*
* Copyright (C) 2023 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.launcher3.celllayout.board
import android.content.ComponentName
import android.content.Context
import android.graphics.Rect
import android.os.Process
import android.os.UserHandle
import android.util.Log
import androidx.test.core.app.ApplicationProvider
import androidx.test.platform.app.InstrumentationRegistry
import com.android.launcher3.InvariantDeviceProfile
import com.android.launcher3.LauncherSettings
import com.android.launcher3.celllayout.FavoriteItemsTransaction
import com.android.launcher3.model.data.AppInfo
import com.android.launcher3.model.data.FolderInfo
import com.android.launcher3.model.data.ItemInfo
import com.android.launcher3.model.data.WorkspaceItemInfo
import com.android.launcher3.ui.TestViewHelpers
import com.android.launcher3.util.WidgetUtils
import java.util.function.Supplier
class TestWorkspaceBuilder(private val mContext: Context) {
private var appComponentName =
ComponentName("com.google.android.calculator", "com.android.calculator2.Calculator")
private val myUser: UserHandle = Process.myUserHandle()
/** Fills the given rect in WidgetRect with 1x1 widgets. This is useful to equalize cases. */
private fun fillWithWidgets(
widgetRect: WidgetRect,
transaction: FavoriteItemsTransaction,
screenId: Int
): FavoriteItemsTransaction {
val initX = widgetRect.cellX
val initY = widgetRect.cellY
for (x in initX until initX + widgetRect.spanX) {
for (y in initY until initY + widgetRect.spanY) {
try {
// this widgets are filling, we don't care if we can't place them
transaction.addItem(
createWidgetInCell(WidgetRect(CellType.IGNORE, Rect(x, y, x, y)), screenId)
)
} catch (e: Exception) {
Log.d(TAG, "Unable to place filling widget at $x,$y")
}
}
}
return transaction
}
private fun app() =
AppInfo(appComponentName, "test icon", myUser, AppInfo.makeLaunchIntent(appComponentName))
/**
* Helper to set the app to use for the test workspace, using activity-alias from
* AndroidManifest-common.
*
* @param testAppName the android:name field of the test app activity-alias to use
*/
fun setTestAppActivityAlias(testAppName: String) {
appComponentName =
ComponentName(
InstrumentationRegistry.getInstrumentation().context.packageName,
TEST_ACTIVITY_PACKAGE_PREFIX + testAppName
)
}
private fun addCorrespondingWidgetRect(
widgetRect: WidgetRect,
transaction: FavoriteItemsTransaction,
screenId: Int
) {
if (widgetRect.type == 'x') {
fillWithWidgets(widgetRect, transaction, screenId)
} else {
transaction.addItem(createWidgetInCell(widgetRect, screenId))
}
}
/** Builds the given board into the transaction */
fun buildFromBoard(
board: CellLayoutBoard,
transaction: FavoriteItemsTransaction,
screenId: Int
): FavoriteItemsTransaction {
board.widgets.forEach { addCorrespondingWidgetRect(it, transaction, screenId) }
board.icons.forEach { transaction.addItem { createIconInCell(it, screenId) } }
board.folders.forEach { transaction.addItem { createFolderInCell(it, screenId) } }
return transaction
}
/**
* Fills the hotseat row with apps instead of suggestions, for this to work the workspace should
* be clean otherwise this doesn't overrides the existing icons.
*/
fun fillHotseatIcons(transaction: FavoriteItemsTransaction): FavoriteItemsTransaction {
for (i in 0..<InvariantDeviceProfile.INSTANCE[mContext].numDatabaseHotseatIcons) {
transaction.addItem { getHotseatValues(i) }
}
return transaction
}
private fun createWidgetInCell(widgetRect: WidgetRect, paramScreenId: Int): Supplier<ItemInfo> {
// Create the widget lazily since the appWidgetId can get lost during setup
return Supplier<ItemInfo> {
WidgetUtils.createWidgetInfo(
TestViewHelpers.findWidgetProvider(false),
ApplicationProvider.getApplicationContext(),
true
)
.apply {
cellX = widgetRect.cellX
cellY = widgetRect.cellY
spanX = widgetRect.spanX
spanY = widgetRect.spanY
screenId = paramScreenId
}
}
}
fun createFolderInCell(folderPoint: FolderPoint, paramScreenId: Int): FolderInfo =
FolderInfo().apply {
screenId = paramScreenId
container = LauncherSettings.Favorites.CONTAINER_DESKTOP
cellX = folderPoint.coord.x
cellY = folderPoint.coord.y
spanY = 1
spanX = 1
minSpanX = 1
minSpanY = 1
setOption(FolderInfo.FLAG_MULTI_PAGE_ANIMATION, true, null)
for (i in 0 until folderPoint.numberIconsInside) {
add(getDefaultWorkspaceItem(paramScreenId), false)
}
}
private fun getDefaultWorkspaceItem(paramScreenId: Int): WorkspaceItemInfo =
WorkspaceItemInfo(app()).apply {
screenId = paramScreenId
spanY = 1
spanX = 1
minSpanX = 1
minSpanY = 1
container = LauncherSettings.Favorites.CONTAINER_DESKTOP
}
private fun createIconInCell(iconPoint: IconPoint, paramScreenId: Int) =
WorkspaceItemInfo(app()).apply {
screenId = paramScreenId
cellX = iconPoint.coord.x
cellY = iconPoint.coord.y
spanY = 1
spanX = 1
minSpanX = 1
minSpanY = 1
container = LauncherSettings.Favorites.CONTAINER_DESKTOP
}
private fun getHotseatValues(x: Int) =
WorkspaceItemInfo(app()).apply {
cellX = x
cellY = 0
spanY = 1
spanX = 1
minSpanX = 1
minSpanY = 1
rank = x
screenId = x
container = LauncherSettings.Favorites.CONTAINER_HOTSEAT
}
companion object {
private const val TAG = "CellLayoutBoardBuilder"
private const val TEST_ACTIVITY_PACKAGE_PREFIX = "com.android.launcher3.tests."
}
}
@@ -1,59 +0,0 @@
/*
* Copyright (C) 2023 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.launcher3.celllayout.board;
import android.graphics.Rect;
public class WidgetRect {
public char mType;
public Rect mBounds;
public WidgetRect(char type, Rect bounds) {
this.mType = type;
this.mBounds = bounds;
}
public int getSpanX() {
return mBounds.right - mBounds.left + 1;
}
public int getSpanY() {
return mBounds.top - mBounds.bottom + 1;
}
public int getCellX() {
return mBounds.left;
}
public int getCellY() {
return mBounds.bottom;
}
boolean shouldIgnore() {
return this.mType == CellType.IGNORE;
}
boolean contains(int x, int y) {
return mBounds.contains(x, y);
}
@Override
public String toString() {
return "WidgetRect type = " + mType + " x = " + getCellX() + " | y " + getCellY()
+ " xs = " + getSpanX() + " ys = " + getSpanY();
}
}
@@ -65,7 +65,7 @@ class AllAppsRecyclerViewPoolTest<T> where T : Context, T : ActivityContext {
@Test
fun preinflate_success() {
underTest.preInflateAllAppsViewHolders(adapter, VIEW_TYPE, parent) { 10 }
underTest.preInflateAllAppsViewHolders(adapter, VIEW_TYPE, parent, 10) { 10 }
awaitTasksCompleted()
assertThat(underTest.getRecycledViewCount(VIEW_TYPE)).isEqualTo(10)
@@ -73,7 +73,7 @@ class AllAppsRecyclerViewPoolTest<T> where T : Context, T : ActivityContext {
@Test
fun preinflate_not_triggered() {
underTest.preInflateAllAppsViewHolders(adapter, VIEW_TYPE, parent) { 0 }
underTest.preInflateAllAppsViewHolders(adapter, VIEW_TYPE, parent, 0) { 0 }
awaitTasksCompleted()
assertThat(underTest.getRecycledViewCount(VIEW_TYPE)).isEqualTo(0)
@@ -81,7 +81,7 @@ class AllAppsRecyclerViewPoolTest<T> where T : Context, T : ActivityContext {
@Test
fun preinflate_cancel_before_runOnMainThread() {
underTest.preInflateAllAppsViewHolders(adapter, VIEW_TYPE, parent) { 10 }
underTest.preInflateAllAppsViewHolders(adapter, VIEW_TYPE, parent, 10) { 10 }
assertThat(underTest.mCancellableTask!!.canceled).isFalse()
underTest.clear()
@@ -94,7 +94,7 @@ class AllAppsRecyclerViewPoolTest<T> where T : Context, T : ActivityContext {
@Test
fun preinflate_cancel_after_run() {
underTest.preInflateAllAppsViewHolders(adapter, VIEW_TYPE, parent) { 10 }
underTest.preInflateAllAppsViewHolders(adapter, VIEW_TYPE, parent, 10) { 10 }
assertThat(underTest.mCancellableTask!!.canceled).isFalse()
awaitTasksCompleted()