use of com.android.launcher3.tapl.Overview in project android_packages_apps_Launcher3 by crdroidandroid.
the class TaplTestsQuickstep method testOverview.
@Test
@PortraitLandscape
public void testOverview() throws Exception {
startTestAppsWithCheck();
// mLauncher.pressHome() also tests an important case of pressing home while in background.
Overview overview = mLauncher.pressHome().switchToOverview();
assertTrue("Launcher internal state didn't switch to Overview", isInState(() -> LauncherState.OVERVIEW));
executeOnLauncher(launcher -> assertTrue("Don't have at least 3 tasks", getTaskCount(launcher) >= 3));
// Test flinging forward and backward.
executeOnLauncher(launcher -> assertEquals("Current task in Overview is not 0", 0, getCurrentOverviewPage(launcher)));
overview.flingForward();
assertTrue("Launcher internal state is not Overview", isInState(() -> LauncherState.OVERVIEW));
final Integer currentTaskAfterFlingForward = getFromLauncher(launcher -> getCurrentOverviewPage(launcher));
executeOnLauncher(launcher -> assertTrue("Current task in Overview is still 0", currentTaskAfterFlingForward > 0));
overview.flingBackward();
assertTrue("Launcher internal state is not Overview", isInState(() -> LauncherState.OVERVIEW));
executeOnLauncher(launcher -> assertTrue("Flinging back in Overview did nothing", getCurrentOverviewPage(launcher) < currentTaskAfterFlingForward));
// Test opening a task.
OverviewTask task = mLauncher.pressHome().switchToOverview().getCurrentTask();
assertNotNull("overview.getCurrentTask() returned null (1)", task);
assertNotNull("OverviewTask.open returned null", task.open());
assertTrue("Test activity didn't open from Overview", mDevice.wait(Until.hasObject(By.pkg(getAppPackageName()).text("TestActivity2")), DEFAULT_UI_TIMEOUT));
executeOnLauncher(launcher -> assertTrue("Launcher activity is the top activity; expecting another activity to be the top " + "one", isInBackground(launcher)));
// Test dismissing a task.
overview = mLauncher.pressHome().switchToOverview();
assertTrue("Launcher internal state didn't switch to Overview", isInState(() -> LauncherState.OVERVIEW));
final Integer numTasks = getFromLauncher(launcher -> getTaskCount(launcher));
task = overview.getCurrentTask();
assertNotNull("overview.getCurrentTask() returned null (2)", task);
task.dismiss();
executeOnLauncher(launcher -> assertEquals("Dismissing a task didn't remove 1 task from Overview", numTasks - 1, getTaskCount(launcher)));
// Test UIDevice.pressHome, once we are in AllApps.
mDevice.pressHome();
waitForState("Launcher internal state didn't switch to Home", () -> LauncherState.NORMAL);
// Test dismissing all tasks.
mLauncher.getWorkspace().switchToOverview().dismissAllTasks();
waitForState("Launcher internal state didn't switch to Home", () -> LauncherState.NORMAL);
executeOnLauncher(launcher -> assertEquals("Still have tasks after dismissing all", 0, getTaskCount(launcher)));
}
use of com.android.launcher3.tapl.Overview in project android_packages_apps_Launcher3 by crdroidandroid.
the class RecentsView method updateGridProperties.
/**
* Updates TaskView and ClearAllButton scaling and translation required to turn into grid
* layout.
* This method only calculates the potential position and depends on {@link #setGridProgress} to
* apply the actual scaling and translation.
*
* @param isTaskDismissal indicates if update was called due to task dismissal
*/
private void updateGridProperties(boolean isTaskDismissal) {
int taskCount = getTaskViewCount();
if (taskCount == 0) {
return;
}
final int boxLength = Math.max(mLastComputedGridTaskSize.width(), mLastComputedGridTaskSize.height());
int taskTopMargin = mActivity.getDeviceProfile().overviewTaskThumbnailTopMarginPx;
/*
* taskGridVerticalDiff is used to position the top of a task in the top row of the grid
* heightOffset is the vertical space one grid task takes + space between top and
* bottom row
* Summed together they provide the top position for bottom row of grid tasks
*/
final float taskGridVerticalDiff = mLastComputedGridTaskSize.top - mLastComputedTaskSize.top;
final float heightOffset = (boxLength + taskTopMargin) + mRowSpacing;
int topRowWidth = 0;
int bottomRowWidth = 0;
float topAccumulatedTranslationX = 0;
float bottomAccumulatedTranslationX = 0;
// Contains whether the child index is in top or bottom of grid (for non-focused task)
// Different from mTopRowIdSet, which contains the taskId of what task is in top row
IntSet topSet = new IntSet();
IntSet bottomSet = new IntSet();
// Horizontal grid translation for each task
float[] gridTranslations = new float[taskCount];
int focusedTaskIndex = Integer.MAX_VALUE;
int focusedTaskShift = 0;
int focusedTaskWidthAndSpacing = 0;
int snappedTaskRowWidth = 0;
int snappedPage = getNextPage();
TaskView snappedTaskView = getTaskViewAtByAbsoluteIndex(snappedPage);
if (!isTaskDismissal) {
mTopRowIdSet.clear();
}
for (int i = 0; i < taskCount; i++) {
TaskView taskView = getTaskViewAt(i);
int taskWidthAndSpacing = taskView.getLayoutParams().width + mPageSpacing;
// the grid.
if (taskView.isFocusedTask()) {
topRowWidth += taskWidthAndSpacing;
bottomRowWidth += taskWidthAndSpacing;
focusedTaskIndex = i;
focusedTaskWidthAndSpacing = taskWidthAndSpacing;
gridTranslations[i] += focusedTaskShift;
gridTranslations[i] += mIsRtl ? taskWidthAndSpacing : -taskWidthAndSpacing;
// Center view vertically in case it's from different orientation.
taskView.setGridTranslationY((mLastComputedTaskSize.height() + taskTopMargin - taskView.getLayoutParams().height) / 2f);
if (taskView == snappedTaskView) {
// If focused task is snapped, the row width is just task width and spacing.
snappedTaskRowWidth = taskWidthAndSpacing;
}
} else {
if (i > focusedTaskIndex) {
// For tasks after the focused task, shift by focused task's width and spacing.
gridTranslations[i] += mIsRtl ? focusedTaskWidthAndSpacing : -focusedTaskWidthAndSpacing;
} else {
// For task before the focused task, accumulate the width and spacing to
// calculate the distance focused task need to shift.
focusedTaskShift += mIsRtl ? taskWidthAndSpacing : -taskWidthAndSpacing;
}
int taskId = taskView.getTask().key.id;
boolean isTopRow = isTaskDismissal ? mTopRowIdSet.contains(taskId) : topRowWidth <= bottomRowWidth;
if (isTopRow) {
topRowWidth += taskWidthAndSpacing;
topSet.add(i);
mTopRowIdSet.add(taskId);
taskView.setGridTranslationY(taskGridVerticalDiff);
// Move horizontally into empty space.
float widthOffset = 0;
for (int j = i - 1; !topSet.contains(j) && j >= 0; j--) {
if (j == focusedTaskIndex) {
continue;
}
widthOffset += getTaskViewAt(j).getLayoutParams().width + mPageSpacing;
}
float currentTaskTranslationX = mIsRtl ? widthOffset : -widthOffset;
gridTranslations[i] += topAccumulatedTranslationX + currentTaskTranslationX;
topAccumulatedTranslationX += currentTaskTranslationX;
} else {
bottomRowWidth += taskWidthAndSpacing;
bottomSet.add(i);
// Move into bottom row.
taskView.setGridTranslationY(heightOffset + taskGridVerticalDiff);
// Move horizontally into empty space.
float widthOffset = 0;
for (int j = i - 1; !bottomSet.contains(j) && j >= 0; j--) {
if (j == focusedTaskIndex) {
continue;
}
widthOffset += getTaskViewAt(j).getLayoutParams().width + mPageSpacing;
}
float currentTaskTranslationX = mIsRtl ? widthOffset : -widthOffset;
gridTranslations[i] += bottomAccumulatedTranslationX + currentTaskTranslationX;
bottomAccumulatedTranslationX += currentTaskTranslationX;
}
if (taskView == snappedTaskView) {
snappedTaskRowWidth = isTopRow ? topRowWidth : bottomRowWidth;
}
}
}
// We need to maintain snapped task's page scroll invariant between quick switch and
// overview, so we sure snapped task's grid translation is 0, and add a non-fullscreen
// translationX that is the same as snapped task's full scroll adjustment.
float snappedTaskFullscreenScrollAdjustment = 0;
float snappedTaskGridTranslationX = 0;
if (snappedTaskView != null) {
snappedTaskFullscreenScrollAdjustment = snappedTaskView.getScrollAdjustment(/*fullscreenEnabled=*/
true, /*gridEnabled=*/
false);
snappedTaskGridTranslationX = gridTranslations[snappedPage - mTaskViewStartIndex];
}
for (int i = 0; i < taskCount; i++) {
TaskView taskView = getTaskViewAt(i);
taskView.setGridTranslationX(gridTranslations[i] - snappedTaskGridTranslationX);
taskView.getPrimaryNonFullscreenTranslationProperty().set(taskView, snappedTaskFullscreenScrollAdjustment);
taskView.getSecondaryNonFullscreenTranslationProperty().set(taskView, 0f);
}
// Use the accumulated translation of the row containing the last task.
float clearAllAccumulatedTranslation = topSet.contains(taskCount - 1) ? topAccumulatedTranslationX : bottomAccumulatedTranslationX;
// If the last task is on the shorter row, ClearAllButton will embed into the shorter row
// which is not what we want. Compensate the width difference of the 2 rows in that case.
float shorterRowCompensation = 0;
if (topRowWidth <= bottomRowWidth) {
if (topSet.contains(taskCount - 1)) {
shorterRowCompensation = bottomRowWidth - topRowWidth;
}
} else {
if (bottomSet.contains(taskCount - 1)) {
shorterRowCompensation = topRowWidth - bottomRowWidth;
}
}
float clearAllShorterRowCompensation = mIsRtl ? -shorterRowCompensation : shorterRowCompensation;
// If the total width is shorter than one grid's width, move ClearAllButton further away
// accordingly. Update longRowWidth if ClearAllButton has been moved.
float clearAllShortTotalCompensation = 0;
int longRowWidth = Math.max(topRowWidth, bottomRowWidth);
if (longRowWidth < mLastComputedGridSize.width()) {
float shortTotalCompensation = mLastComputedGridSize.width() - longRowWidth;
clearAllShortTotalCompensation = mIsRtl ? -shortTotalCompensation : shortTotalCompensation;
longRowWidth = mLastComputedGridSize.width();
}
float clearAllTotalTranslationX = clearAllAccumulatedTranslation + clearAllShorterRowCompensation + clearAllShortTotalCompensation + snappedTaskFullscreenScrollAdjustment;
if (focusedTaskIndex < taskCount) {
// Shift by focused task's width and spacing if a task is focused.
clearAllTotalTranslationX += mIsRtl ? focusedTaskWidthAndSpacing : -focusedTaskWidthAndSpacing;
}
// of swiping up after quick switch.
if (snappedTaskView != null) {
int distanceFromClearAll = longRowWidth - snappedTaskRowWidth;
int minimumDistance = mLastComputedGridSize.width() - snappedTaskView.getLayoutParams().width;
if (distanceFromClearAll < minimumDistance) {
int distanceDifference = minimumDistance - distanceFromClearAll;
clearAllTotalTranslationX += mIsRtl ? -distanceDifference : distanceDifference;
}
}
setGridProgress(mGridProgress);
}
use of com.android.launcher3.tapl.Overview in project android_packages_apps_Launcher3 by crdroidandroid.
the class RecentsView method createTaskLaunchAnimation.
public PendingAnimation createTaskLaunchAnimation(TaskView tv, long duration, Interpolator interpolator) {
if (FeatureFlags.IS_STUDIO_BUILD && mPendingAnimation != null) {
throw new IllegalStateException("Another pending animation is still running");
}
int count = getTaskViewCount();
if (count == 0) {
return new PendingAnimation(duration);
}
// When swiping down from overview to tasks, ensures the snapped page's scroll maintain
// invariant between quick switch and overview, to ensure a smooth animation transition.
updateGridProperties();
updateScrollSynchronously();
int targetSysUiFlags = tv.getThumbnail().getSysUiStatusNavFlags();
final boolean[] passedOverviewThreshold = new boolean[] { false };
ValueAnimator progressAnim = ValueAnimator.ofFloat(0, 1);
progressAnim.addUpdateListener(animator -> {
// tasks' flags
if (animator.getAnimatedFraction() > UPDATE_SYSUI_FLAGS_THRESHOLD) {
mActivity.getSystemUiController().updateUiState(UI_STATE_FULLSCREEN_TASK, targetSysUiFlags);
} else {
mActivity.getSystemUiController().updateUiState(UI_STATE_FULLSCREEN_TASK, 0);
}
// Passing the threshold from taskview to fullscreen app will vibrate
final boolean passed = animator.getAnimatedFraction() >= SUCCESS_TRANSITION_PROGRESS;
if (passed != passedOverviewThreshold[0]) {
passedOverviewThreshold[0] = passed;
performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY, HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
}
});
AnimatorSet anim = createAdjacentPageAnimForTaskLaunch(tv);
DepthController depthController = getDepthController();
if (depthController != null) {
ObjectAnimator depthAnimator = ObjectAnimator.ofFloat(depthController, DEPTH, BACKGROUND_APP.getDepth(mActivity));
anim.play(depthAnimator);
}
anim.play(progressAnim);
anim.setInterpolator(interpolator);
mPendingAnimation = new PendingAnimation(duration);
mPendingAnimation.add(anim);
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
mLiveTileTaskViewSimulator.addOverviewToAppAnim(mPendingAnimation, interpolator);
mPendingAnimation.addOnFrameCallback(this::redrawLiveTile);
}
mPendingAnimation.addEndListener(isSuccess -> {
if (isSuccess) {
if (ENABLE_QUICKSTEP_LIVE_TILE.get() && tv.isRunningTask()) {
finishRecentsAnimation(false, /* toRecents */
null);
onTaskLaunchAnimationEnd(true);
} else {
tv.launchTask(this::onTaskLaunchAnimationEnd);
}
Task task = tv.getTask();
if (task != null) {
mActivity.getStatsLogManager().logger().withItemInfo(tv.getItemInfo()).log(LAUNCHER_TASK_LAUNCH_SWIPE_DOWN);
}
} else {
onTaskLaunchAnimationEnd(false);
}
mPendingAnimation = null;
});
return mPendingAnimation;
}
use of com.android.launcher3.tapl.Overview in project android_packages_apps_Launcher3 by crdroidandroid.
the class TaskView method onTaskListVisibilityChanged.
/**
* See {@link TaskDataChanges}
* @param visible If this task view will be visible to the user in overview or hidden
*/
public void onTaskListVisibilityChanged(boolean visible, @TaskDataChanges int changes) {
if (mTask == null) {
return;
}
cancelPendingLoadTasks();
if (visible) {
// These calls are no-ops if the data is already loaded, try and load the high
// resolution thumbnail if the state permits
RecentsModel model = RecentsModel.INSTANCE.get(getContext());
TaskThumbnailCache thumbnailCache = model.getThumbnailCache();
TaskIconCache iconCache = model.getIconCache();
if (needsUpdate(changes, FLAG_UPDATE_THUMBNAIL)) {
mThumbnailLoadRequest = thumbnailCache.updateThumbnailInBackground(mTask, thumbnail -> {
mSnapshotView.setThumbnail(mTask, thumbnail);
});
}
if (needsUpdate(changes, FLAG_UPDATE_ICON)) {
mIconLoadRequest = iconCache.updateIconInBackground(mTask, (task) -> {
setIcon(task.icon);
mDigitalWellBeingToast.initialize(mTask);
});
}
} else {
if (needsUpdate(changes, FLAG_UPDATE_THUMBNAIL)) {
mSnapshotView.setThumbnail(null, null);
// Reset the task thumbnail reference as well (it will be fetched from the cache or
// reloaded next time we need it)
mTask.thumbnail = null;
}
if (needsUpdate(changes, FLAG_UPDATE_ICON)) {
setIcon(null);
}
}
}
use of com.android.launcher3.tapl.Overview in project android_packages_apps_Launcher3 by crdroidandroid.
the class ItemLongClickListener method onAllAppsItemLongClick.
private static boolean onAllAppsItemLongClick(View v) {
TestLogging.recordEvent(TestProtocol.SEQUENCE_MAIN, "onAllAppsItemLongClick");
v.cancelLongPress();
Launcher launcher = Launcher.getLauncher(v.getContext());
if (!canStartDrag(launcher))
return false;
// When we have exited all apps or are in transition, disregard long clicks
if (!launcher.isInState(ALL_APPS) && !launcher.isInState(OVERVIEW))
return false;
if (launcher.getWorkspace().isSwitchingState())
return false;
StatsLogger logger = launcher.getStatsLogManager().logger();
if (v.getTag() instanceof ItemInfo) {
logger.withItemInfo((ItemInfo) v.getTag());
}
logger.log(LAUNCHER_ALLAPPS_ITEM_LONG_PRESSED);
// Start the drag
final DragController dragController = launcher.getDragController();
dragController.addDragListener(new DragController.DragListener() {
@Override
public void onDragStart(DropTarget.DragObject dragObject, DragOptions options) {
v.setVisibility(INVISIBLE);
}
@Override
public void onDragEnd() {
v.setVisibility(VISIBLE);
dragController.removeDragListener(this);
}
});
DeviceProfile grid = launcher.getDeviceProfile();
DragOptions options = new DragOptions();
options.intrinsicIconScaleFactor = (float) grid.allAppsIconSizePx / grid.iconSizePx;
launcher.getWorkspace().beginDragShared(v, launcher.getAppsView(), options);
return false;
}
Aggregations