Snap for 9657362 from 4d95ac8c7e to udc-release

Change-Id: I1e7a5af2d673784ca56d5b4c08562c913a8cbe5a
This commit is contained in:
Android Build Coastguard Worker
2023-02-26 00:27:21 +00:00
35 changed files with 524 additions and 291 deletions
@@ -21,5 +21,4 @@
android:layout_height="@dimen/taskbar_icon_min_touch_size"
android:contentDescription="@string/all_apps_button_label"
android:backgroundTint="@android:color/transparent"
android:icon="@drawable/ic_all_apps_button"
/>
+3
View File
@@ -286,6 +286,8 @@
<dimen name="taskbar_back_button_left_margin_kids">48dp</dimen>
<dimen name="taskbar_home_button_left_margin_kids">48dp</dimen>
<dimen name="taskbar_icon_size_kids">32dp</dimen>
<dimen name="taskbar_all_apps_button_translation_x_offset">6dp</dimen>
<!-- Transient taskbar -->
<dimen name="transient_taskbar_size">72dp</dimen>
@@ -295,6 +297,7 @@
<dimen name="transient_taskbar_shadow_blur">40dp</dimen>
<dimen name="transient_taskbar_key_shadow_distance">10dp</dimen>
<dimen name="transient_taskbar_stashed_size">32dp</dimen>
<dimen name="transient_taskbar_all_apps_button_translation_x_offset">4dp</dimen>
<!-- An additional touch slop to prevent x-axis movement during the swipe up to show taskbar -->
<dimen name="transient_taskbar_clamped_offset_bound">16dp</dimen>
<!-- Taskbar swipe up thresholds -->
@@ -41,12 +41,15 @@ public class TaskbarAutohideSuspendController implements
public static final int FLAG_AUTOHIDE_SUSPEND_TOUCHING = 1 << 2;
// Taskbar EDU overlay is open above the Taskbar. */
public static final int FLAG_AUTOHIDE_SUSPEND_EDU_OPEN = 1 << 3;
// Taskbar in immersive mode in overview
public static final int FLAG_AUTOHIDE_SUSPEND_IN_LAUNCHER = 1 << 4;
@IntDef(flag = true, value = {
FLAG_AUTOHIDE_SUSPEND_FULLSCREEN,
FLAG_AUTOHIDE_SUSPEND_DRAGGING,
FLAG_AUTOHIDE_SUSPEND_TOUCHING,
FLAG_AUTOHIDE_SUSPEND_EDU_OPEN,
FLAG_AUTOHIDE_SUSPEND_IN_LAUNCHER,
})
@Retention(RetentionPolicy.SOURCE)
public @interface AutohideSuspendFlag {}
@@ -92,6 +95,10 @@ public class TaskbarAutohideSuspendController implements
return mAutohideSuspendFlags != 0;
}
public boolean isSuspendedForTransientTaskbarInOverview() {
return (mAutohideSuspendFlags & FLAG_AUTOHIDE_SUSPEND_IN_LAUNCHER) != 0;
}
@Override
public void dumpLogs(String prefix, PrintWriter pw) {
pw.println(prefix + "TaskbarAutohideSuspendController:");
@@ -106,6 +113,8 @@ public class TaskbarAutohideSuspendController implements
appendFlag(str, flags, FLAG_AUTOHIDE_SUSPEND_DRAGGING, "FLAG_AUTOHIDE_SUSPEND_DRAGGING");
appendFlag(str, flags, FLAG_AUTOHIDE_SUSPEND_TOUCHING, "FLAG_AUTOHIDE_SUSPEND_TOUCHING");
appendFlag(str, flags, FLAG_AUTOHIDE_SUSPEND_EDU_OPEN, "FLAG_AUTOHIDE_SUSPEND_EDU_OPEN");
appendFlag(str, flags, FLAG_AUTOHIDE_SUSPEND_IN_LAUNCHER,
"FLAG_AUTOHIDE_SUSPEND_IN_LAUNCHER");
return str.toString();
}
}
@@ -460,7 +460,9 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
return;
}
if (stash && mControllers.taskbarAutohideSuspendController.isSuspended()) {
if (stash && mControllers.taskbarAutohideSuspendController.isSuspended()
&& !mControllers.taskbarAutohideSuspendController
.isSuspendedForTransientTaskbarInOverview()) {
// Avoid stashing if autohide is currently suspended.
return;
}
@@ -955,6 +957,8 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
if (hasAnyFlag(changedFlags, FLAGS_STASHED_IN_APP | FLAGS_IN_APP)) {
notifyStashChange(/* visible */ hasAnyFlag(FLAGS_IN_APP),
/* stashed */ isStashedInApp());
mControllers.taskbarAutohideSuspendController.updateFlag(
TaskbarAutohideSuspendController.FLAG_AUTOHIDE_SUSPEND_IN_LAUNCHER, !isInApp());
}
if (hasAnyFlag(changedFlags, FLAG_STASHED_IN_APP_MANUAL)) {
if (hasAnyFlag(FLAG_STASHED_IN_APP_MANUAL)) {
@@ -89,6 +89,8 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar
private float mTransientTaskbarMinWidth;
private float mTransientTaskbarAllAppsButtonTranslationXOffset;
public TaskbarView(@NonNull Context context) {
this(context, null);
}
@@ -108,9 +110,14 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar
mActivityContext = ActivityContext.lookupContext(context);
mIconLayoutBounds = mActivityContext.getTransientTaskbarBounds();
Resources resources = getResources();
boolean isTransientTaskbar = DisplayController.isTransientTaskbar(mActivityContext);
mIsRtl = Utilities.isRtl(resources);
mTransientTaskbarMinWidth = mContext.getResources().getDimension(
R.dimen.transient_taskbar_min_width);
mTransientTaskbarAllAppsButtonTranslationXOffset =
resources.getDimension(isTransientTaskbar
? R.dimen.transient_taskbar_all_apps_button_translation_x_offset
: R.dimen.taskbar_all_apps_button_translation_x_offset);
int actualMargin = resources.getDimensionPixelSize(R.dimen.taskbar_icon_spacing);
int actualIconSize = mActivityContext.getDeviceProfile().iconSizePx;
@@ -130,9 +137,12 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar
if (!mActivityContext.getPackageManager().hasSystemFeature(FEATURE_PC)) {
mAllAppsButton = (IconButtonView) LayoutInflater.from(context)
.inflate(R.layout.taskbar_all_apps_button, this, false);
mAllAppsButton.setIconDrawable(resources.getDrawable(isTransientTaskbar
? R.drawable.ic_transient_taskbar_all_apps_button
: R.drawable.ic_taskbar_all_apps_button));
mAllAppsButton.setScaleX(mIsRtl ? -1 : 1);
mAllAppsButton.setForegroundTint(mActivityContext.getColor(
DisplayController.isTransientTaskbar(mActivityContext)
mAllAppsButton.setPadding(mItemPadding, mItemPadding, mItemPadding, mItemPadding);
mAllAppsButton.setForegroundTint(mActivityContext.getColor(isTransientTaskbar
? R.color.all_apps_button_color
: R.color.all_apps_button_color_dark));
@@ -276,6 +286,8 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar
}
if (mAllAppsButton != null) {
mAllAppsButton.setTranslationXForTaskbarAllAppsIcon(getChildCount() > 0
? mTransientTaskbarAllAppsButtonTranslationXOffset : 0f);
addView(mAllAppsButton, mIsRtl ? getChildCount() : 0);
// if only all apps button present, don't include divider view.
@@ -121,8 +121,7 @@ public final class RecentsViewStateController extends
private void handleSplitSelectionState(@NonNull LauncherState toState,
@NonNull PendingAnimation builder, boolean animate) {
if (toState != OVERVIEW_SPLIT_SELECT) {
// Not going to split, nothing to do but ensure taskviews are at correct offset
mRecentsView.resetSplitPrimaryScrollOffset();
// Not going to split
return;
}
@@ -153,8 +152,6 @@ public final class RecentsViewStateController extends
as.start();
as.end();
}
mRecentsView.applySplitPrimaryScrollOffset();
}
private void setAlphas(PropertySetter propertySetter, StateAnimationConfig config,
@@ -677,7 +677,7 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
@Override
public void onMotionPauseDetected() {
mHasMotionEverBeenPaused = true;
maybeUpdateRecentsAttachedState(true/* animate */, true/* moveFocusedTask */);
maybeUpdateRecentsAttachedState(true/* animate */, true/* moveRunningTask */);
Optional.ofNullable(mActivityInterface.getTaskbarController())
.ifPresent(TaskbarUIController::startTranslationSpring);
performHapticFeedback();
@@ -695,7 +695,7 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
}
private void maybeUpdateRecentsAttachedState(boolean animate) {
maybeUpdateRecentsAttachedState(animate, false /* moveFocusedTask */);
maybeUpdateRecentsAttachedState(animate, false /* moveRunningTask */);
}
/**
@@ -705,9 +705,9 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
*
* Note this method has no effect unless the navigation mode is NO_BUTTON.
* @param animate whether to animate when attaching RecentsView
* @param moveFocusedTask whether to move focused task to front when attaching
* @param moveRunningTask whether to move running task to front when attaching
*/
private void maybeUpdateRecentsAttachedState(boolean animate, boolean moveFocusedTask) {
private void maybeUpdateRecentsAttachedState(boolean animate, boolean moveRunningTask) {
if (!mDeviceState.isFullyGesturalNavMode() || mRecentsView == null) {
return;
}
@@ -726,11 +726,11 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
} else {
recentsAttachedToAppWindow = mHasMotionEverBeenPaused || mIsLikelyToStartNewTask;
}
if (moveFocusedTask && !mAnimationFactory.hasRecentsEverAttachedToAppWindow()
if (moveRunningTask && !mAnimationFactory.hasRecentsEverAttachedToAppWindow()
&& recentsAttachedToAppWindow) {
// Only move focused task if RecentsView has never been attached before, to avoid
// Only move running task if RecentsView has never been attached before, to avoid
// TaskView jumping to new position as we move the tasks.
mRecentsView.moveFocusedTaskToFront();
mRecentsView.moveRunningTaskToFront();
}
mAnimationFactory.setRecentsAttachedToAppWindow(recentsAttachedToAppWindow, animate);
@@ -231,17 +231,20 @@ public abstract class BaseActivityInterface<STATE_TYPE extends BaseState<STATE_T
/**
* Calculates the taskView size for the provided device configuration.
*/
public final void calculateTaskSize(Context context, DeviceProfile dp, Rect outRect) {
Resources res = context.getResources();
float maxScale = res.getFloat(R.dimen.overview_max_scale);
public final void calculateTaskSize(Context context, DeviceProfile dp, Rect outRect,
PagedOrientationHandler orientedState) {
if (dp.isTablet) {
Rect gridRect = new Rect();
calculateGridSize(dp, gridRect);
calculateTaskSizeInternal(context, dp, gridRect, maxScale, Gravity.CENTER, outRect);
if (FeatureFlags.ENABLE_GRID_ONLY_OVERVIEW.get()) {
calculateGridTaskSize(context, dp, outRect, orientedState);
} else {
calculateFocusTaskSize(context, dp, outRect);
}
} else {
Resources res = context.getResources();
float maxScale = res.getFloat(R.dimen.overview_max_scale);
int taskMargin = dp.overviewTaskMarginPx;
calculateTaskSizeInternal(context, dp,
calculateTaskSizeInternal(
dp,
dp.overviewTaskThumbnailTopMarginPx,
dp.getOverviewActionsClaimedSpace(),
res.getDimensionPixelSize(R.dimen.overview_minimum_next_prev_size) + taskMargin,
@@ -251,7 +254,15 @@ public abstract class BaseActivityInterface<STATE_TYPE extends BaseState<STATE_T
}
}
private void calculateTaskSizeInternal(Context context, DeviceProfile dp, int claimedSpaceAbove,
private void calculateFocusTaskSize(Context context, DeviceProfile dp, Rect outRect) {
Resources res = context.getResources();
float maxScale = res.getFloat(R.dimen.overview_max_scale);
Rect gridRect = new Rect();
calculateGridSize(dp, gridRect);
calculateTaskSizeInternal(dp, gridRect, maxScale, Gravity.CENTER, outRect);
}
private void calculateTaskSizeInternal(DeviceProfile dp, int claimedSpaceAbove,
int claimedSpaceBelow, int minimumHorizontalPadding, float maxScale, int gravity,
Rect outRect) {
Rect insets = dp.getInsets();
@@ -264,10 +275,10 @@ public abstract class BaseActivityInterface<STATE_TYPE extends BaseState<STATE_T
minimumHorizontalPadding,
claimedSpaceBelow);
calculateTaskSizeInternal(context, dp, potentialTaskRect, maxScale, gravity, outRect);
calculateTaskSizeInternal(dp, potentialTaskRect, maxScale, gravity, outRect);
}
private void calculateTaskSizeInternal(Context context, DeviceProfile dp,
private void calculateTaskSizeInternal(DeviceProfile dp,
Rect potentialTaskRect, float maxScale, int gravity, Rect outRect) {
PointF taskDimension = getTaskDimension(dp);
@@ -318,12 +329,15 @@ public abstract class BaseActivityInterface<STATE_TYPE extends BaseState<STATE_T
public final void calculateGridTaskSize(Context context, DeviceProfile dp, Rect outRect,
PagedOrientationHandler orientedState) {
Resources res = context.getResources();
Rect taskRect = new Rect();
calculateTaskSize(context, dp, taskRect);
Rect potentialTaskRect = new Rect();
if (FeatureFlags.ENABLE_GRID_ONLY_OVERVIEW.get()) {
calculateGridSize(dp, potentialTaskRect);
} else {
calculateFocusTaskSize(context, dp, potentialTaskRect);
}
float rowHeight =
(taskRect.height() + dp.overviewTaskThumbnailTopMarginPx - dp.overviewRowSpacing)
/ 2f;
float rowHeight = (potentialTaskRect.height() + dp.overviewTaskThumbnailTopMarginPx
- dp.overviewRowSpacing) / 2f;
PointF taskDimension = getTaskDimension(dp);
float scale = (rowHeight - dp.overviewTaskThumbnailTopMarginPx) / taskDimension.y;
@@ -332,14 +346,15 @@ public abstract class BaseActivityInterface<STATE_TYPE extends BaseState<STATE_T
int gravity = Gravity.TOP;
gravity |= orientedState.getRecentsRtlSetting(res) ? Gravity.RIGHT : Gravity.LEFT;
Gravity.apply(gravity, outWidth, outHeight, taskRect, outRect);
Gravity.apply(gravity, outWidth, outHeight, potentialTaskRect, outRect);
}
/**
* Calculates the modal taskView size for the provided device configuration
*/
public final void calculateModalTaskSize(Context context, DeviceProfile dp, Rect outRect) {
calculateTaskSize(context, dp, outRect);
public final void calculateModalTaskSize(Context context, DeviceProfile dp, Rect outRect,
PagedOrientationHandler orientedState) {
calculateTaskSize(context, dp, outRect, orientedState);
boolean isGridOnlyOverview = dp.isTablet && FeatureFlags.ENABLE_GRID_ONLY_OVERVIEW.get();
int claimedSpaceBelow = isGridOnlyOverview
? dp.overviewActionsTopMarginPx + dp.overviewActionsHeight + dp.stashedTaskbarSize
@@ -351,7 +366,7 @@ public abstract class BaseActivityInterface<STATE_TYPE extends BaseState<STATE_T
Math.round((dp.availableWidthPx - outRect.width() * maxScale) / 2);
}
calculateTaskSizeInternal(
context, dp,
dp,
dp.overviewTaskMarginPx,
claimedSpaceBelow,
minimumHorizontalPadding,
@@ -61,7 +61,7 @@ public final class FallbackActivityInterface extends
@Override
public int getSwipeUpDestinationAndLength(DeviceProfile dp, Context context, Rect outRect,
PagedOrientationHandler orientationHandler) {
calculateTaskSize(context, dp, outRect);
calculateTaskSize(context, dp, outRect, orientationHandler);
if (dp.isVerticalBarLayout() && DisplayController.getNavigationMode(context) != NO_BUTTON) {
return dp.isSeascape() ? outRect.left : (dp.widthPx - outRect.right);
} else {
@@ -18,7 +18,6 @@ package com.android.quickstep;
import static com.android.launcher3.LauncherState.BACKGROUND_APP;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW;
import static com.android.launcher3.LauncherState.QUICK_SWITCH_FROM_HOME;
import static com.android.launcher3.anim.AnimatorListeners.forEndCallback;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
@@ -73,7 +72,7 @@ public final class LauncherActivityInterface extends
@Override
public int getSwipeUpDestinationAndLength(DeviceProfile dp, Context context, Rect outRect,
PagedOrientationHandler orientationHandler) {
calculateTaskSize(context, dp, outRect);
calculateTaskSize(context, dp, outRect, orientationHandler);
if (dp.isVerticalBarLayout()
&& DisplayController.getNavigationMode(context) != NavigationMode.NO_BUTTON) {
return dp.isSeascape() ? outRect.left : (dp.widthPx - outRect.right);
@@ -284,7 +284,7 @@ public class OverviewCommandHelper {
RecentsView<?, ?> visibleRecentsView = activityInterface.getVisibleRecentsView();
if (visibleRecentsView != null) {
visibleRecentsView.moveFocusedTaskToFront();
visibleRecentsView.moveRunningTaskToFront();
}
if (mTaskAnimationManager.isRecentsAnimationRunning()) {
cmd.mActiveCallbacks = mTaskAnimationManager.continueRecentsAnimation(gestureState);
@@ -59,7 +59,7 @@ public class QuickstepTestInformationHandler extends TestInformationHandler {
}
Rect focusedTaskRect = new Rect();
LauncherActivityInterface.INSTANCE.calculateTaskSize(mContext, mDeviceProfile,
focusedTaskRect);
focusedTaskRect, PagedOrientationHandler.PORTRAIT);
response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, focusedTaskRect.height());
return response;
}
@@ -130,15 +130,9 @@ public class FallbackRecentsStateController implements StateHandler<RecentsState
mRecentsView.getPagedOrientationHandler().getSplitSelectTaskOffset(
TASK_PRIMARY_SPLIT_TRANSLATION, TASK_SECONDARY_SPLIT_TRANSLATION,
mActivity.getDeviceProfile());
setter.setFloat(mRecentsView, taskViewsFloat.first, isSplitSelectionState(state)
? mRecentsView.getSplitSelectTranslation() : 0, LINEAR);
setter.setFloat(mRecentsView, taskViewsFloat.second, 0, LINEAR);
if (isSplitSelectionState(state)) {
mRecentsView.applySplitPrimaryScrollOffset();
setter.setFloat(mRecentsView, taskViewsFloat.first,
mRecentsView.getSplitSelectTranslation(), LINEAR);
} else {
mRecentsView.resetSplitPrimaryScrollOffset();
setter.setFloat(mRecentsView, taskViewsFloat.first, 0, LINEAR);
}
}
/**
@@ -158,7 +158,8 @@ public class AnimatorControllerWithResistance {
Rect startRect = new Rect();
PagedOrientationHandler orientationHandler = params.recentsOrientedState
.getOrientationHandler();
LauncherActivityInterface.INSTANCE.calculateTaskSize(params.context, params.dp, startRect);
LauncherActivityInterface.INSTANCE.calculateTaskSize(params.context, params.dp, startRect,
orientationHandler);
long distanceToCover = startRect.bottom;
PendingAnimation resistAnim = params.resistAnim != null
? params.resistAnim
@@ -43,7 +43,8 @@ public class LayoutUtils {
PagedOrientationHandler orientationHandler) {
// Track the bottom of the window.
Rect taskSize = new Rect();
LauncherActivityInterface.INSTANCE.calculateTaskSize(context, dp, taskSize);
LauncherActivityInterface.INSTANCE.calculateTaskSize(context, dp, taskSize,
orientationHandler);
return orientationHandler.getDistanceToBottomOfRect(dp, taskSize);
}
@@ -157,7 +157,8 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy {
mSizeStrategy.calculateGridTaskSize(mContext, mDp, mTaskRect,
mOrientationState.getOrientationHandler());
} else {
mSizeStrategy.calculateTaskSize(mContext, mDp, mTaskRect);
mSizeStrategy.calculateTaskSize(mContext, mDp, mTaskRect,
mOrientationState.getOrientationHandler());
}
Rect fullTaskSize;
@@ -67,7 +67,6 @@ public class ClearAllButton extends Button {
private float mGridTranslationPrimary;
private float mGridScrollOffset;
private float mScrollOffsetPrimary;
private float mSplitSelectScrollOffsetPrimary;
private int mSidePadding;
@@ -176,10 +175,6 @@ public class ClearAllButton extends Button {
mScrollOffsetPrimary = scrollOffsetPrimary;
}
public void setSplitSelectScrollOffsetPrimary(float splitSelectScrollOffsetPrimary) {
mSplitSelectScrollOffsetPrimary = splitSelectScrollOffsetPrimary;
}
public float getScrollAdjustment(boolean fullscreenEnabled, boolean gridEnabled) {
float scrollAdjustment = 0;
if (fullscreenEnabled) {
@@ -189,7 +184,6 @@ public class ClearAllButton extends Button {
scrollAdjustment += mGridTranslationPrimary + mGridScrollOffset;
}
scrollAdjustment += mScrollOffsetPrimary;
scrollAdjustment += mSplitSelectScrollOffsetPrimary;
return scrollAdjustment;
}
@@ -324,7 +324,7 @@ public class OverviewActionsView<T extends OverlayUICallbacks> extends FrameLayo
requestLayout();
mSplitButton.setCompoundDrawablesWithIntrinsicBounds(
mSplitButton.setCompoundDrawablesRelativeWithIntrinsicBounds(
(dp.isLandscape ? R.drawable.ic_split_horizontal : R.drawable.ic_split_vertical),
0, 0, 0);
}
@@ -53,8 +53,6 @@ import static com.android.launcher3.touch.PagedOrientationHandler.CANVAS_TRANSLA
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import static com.android.launcher3.util.MultiPropertyFactory.MULTI_PROPERTY_VALUE;
import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT;
import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT;
import static com.android.launcher3.util.SystemUiController.UI_STATE_FULLSCREEN_TASK;
import static com.android.quickstep.TaskUtils.checkCurrentOrManagedUserId;
import static com.android.quickstep.views.ClearAllButton.DISMISS_ALPHA;
@@ -80,7 +78,6 @@ import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.WindowConfiguration;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.LocusId;
@@ -518,6 +515,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
private float mTaskThumbnailSplashAlpha = 0;
private boolean mShowAsGridLastOnLayout = false;
private final IntSet mTopRowIdSet = new IntSet();
private int mClearAllShortTotalWidthTranslation = 0;
// The GestureEndTarget that is still in progress.
@Nullable
@@ -1234,21 +1232,9 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
return clearAllScroll + (mIsRtl ? distance : -distance);
}
private int getSnapToFocusedTaskScrollDiff(boolean isClearAllHidden) {
int screenStart = mOrientationHandler.getPrimaryScroll(this);
int targetScroll = getScrollForPage(indexOfChild(getFocusedTaskView()));
if (!isClearAllHidden) {
int clearAllWidth = mOrientationHandler.getPrimarySize(mClearAllButton);
int taskGridHorizontalDiff = mLastComputedTaskSize.right - mLastComputedGridSize.right;
int clearAllFocusScrollDiff = taskGridHorizontalDiff - clearAllWidth;
targetScroll += mIsRtl ? clearAllFocusScrollDiff : -clearAllFocusScrollDiff;
}
return screenStart - targetScroll;
}
private boolean isTaskViewWithinBounds(TaskView tv, int start, int end) {
int taskStart = mOrientationHandler.getChildStart(tv) + (int) tv.getOffsetAdjustment(
showAsFullscreen(), showAsGrid());
showAsGrid());
int taskSize = (int) (mOrientationHandler.getMeasuredSize(tv) * tv.getSizeAdjustment(
showAsFullscreen()));
int taskEnd = taskStart + taskSize;
@@ -1258,7 +1244,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
private boolean isTaskViewFullyWithinBounds(TaskView tv, int start, int end) {
int taskStart = mOrientationHandler.getChildStart(tv) + (int) tv.getOffsetAdjustment(
showAsFullscreen(), showAsGrid());
showAsGrid());
int taskSize = (int) (mOrientationHandler.getMeasuredSize(tv) * tv.getSizeAdjustment(
showAsFullscreen()));
int taskEnd = taskStart + taskSize;
@@ -1494,20 +1480,20 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
}
/**
* Moves the focused task to the front of the carousel in tablets, to minimize animation
* required to focus the task in grid.
* Moves the running task to the front of the carousel in tablets, to minimize animation
* required to move the running task in grid.
*/
public void moveFocusedTaskToFront() {
public void moveRunningTaskToFront() {
if (!mActivity.getDeviceProfile().isTablet) {
return;
}
TaskView focusedTaskView = getFocusedTaskView();
if (focusedTaskView == null) {
TaskView runningTaskView = getRunningTaskView();
if (runningTaskView == null) {
return;
}
if (indexOfChild(focusedTaskView) != mCurrentPage) {
if (indexOfChild(runningTaskView) != mCurrentPage) {
return;
}
@@ -1519,20 +1505,20 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
int currentPageScroll = getScrollForPage(mCurrentPage);
mCurrentPageScrollDiff = primaryScroll - currentPageScroll;
mMovingTaskView = focusedTaskView;
removeView(focusedTaskView);
mMovingTaskView = runningTaskView;
removeView(runningTaskView);
mMovingTaskView = null;
focusedTaskView.resetPersistentViewTransforms();
runningTaskView.resetPersistentViewTransforms();
int frontTaskIndex = 0;
if (DesktopTaskView.DESKTOP_IS_PROTO2_ENABLED && !focusedTaskView.isDesktopTask()) {
if (DesktopTaskView.DESKTOP_IS_PROTO2_ENABLED && !runningTaskView.isDesktopTask()) {
// If desktop mode is enabled, desktop task view is pinned at first position.
// Move focused task to position 1
// Move running task to position 1
frontTaskIndex = 1;
}
addView(focusedTaskView, frontTaskIndex);
addView(runningTaskView, frontTaskIndex);
setCurrentPage(frontTaskIndex);
updateGridProperties();
updateTaskSize();
}
@Override
@@ -1565,7 +1551,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
return;
}
int currentTaskId = -1;
int currentTaskId = INVALID_TASK_ID;
TaskView currentTaskView = getTaskViewAt(mCurrentPage);
if (currentTaskView != null && currentTaskView.getTask() != null) {
currentTaskId = currentTaskView.getTask().key.id;
@@ -1575,7 +1561,8 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
unloadVisibleTaskData(TaskView.FLAG_UPDATE_ALL);
TaskView ignoreResetTaskView =
mIgnoreResetTaskId == -1 ? null : getTaskViewByTaskId(mIgnoreResetTaskId);
mIgnoreResetTaskId == INVALID_TASK_ID
? null : getTaskViewByTaskId(mIgnoreResetTaskId);
// Save running task ID if it exists before rebinding all taskViews, otherwise the task from
// the runningTaskView currently bound could get assigned to another TaskView
@@ -1678,20 +1665,20 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
newFocusedTaskView = getTaskViewAt(1);
}
}
mFocusedTaskViewId = newFocusedTaskView != null ?
newFocusedTaskView.getTaskViewId() : -1;
mFocusedTaskViewId = newFocusedTaskView != null && !ENABLE_GRID_ONLY_OVERVIEW.get()
? newFocusedTaskView.getTaskViewId() : INVALID_TASK_ID;
updateTaskSize();
updateChildTaskOrientations();
TaskView newRunningTaskView = null;
if (runningTaskId != -1) {
if (runningTaskId != INVALID_TASK_ID) {
// Update mRunningTaskViewId to be the new TaskView that was assigned by binding
// the full list of tasks to taskViews
newRunningTaskView = getTaskViewByTaskId(runningTaskId);
if (newRunningTaskView != null) {
mRunningTaskViewId = newRunningTaskView.getTaskViewId();
} else {
mRunningTaskViewId = -1;
mRunningTaskViewId = INVALID_TASK_ID;
}
}
@@ -1699,7 +1686,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
if (mNextPage != INVALID_PAGE) {
// Restore mCurrentPage but don't call setCurrentPage() as that clobbers the scroll.
mCurrentPage = previousCurrentPage;
if (currentTaskId != -1) {
if (currentTaskId != INVALID_TASK_ID) {
currentTaskView = getTaskViewByTaskId(currentTaskId);
if (currentTaskView != null) {
targetPage = indexOfChild(currentTaskView);
@@ -1707,7 +1694,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
}
} else {
// Set the current page to the running task, but not if settling on new task.
if (runningTaskId != -1) {
if (runningTaskId != INVALID_TASK_ID) {
targetPage = indexOfChild(newRunningTaskView);
} else if (getTaskViewCount() > 0) {
TaskView taskView = requireTaskViewAt(0);
@@ -1733,12 +1720,12 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
});
}
if (mIgnoreResetTaskId != -1 &&
if (mIgnoreResetTaskId != INVALID_TASK_ID &&
getTaskViewByTaskId(mIgnoreResetTaskId) != ignoreResetTaskView) {
// If the taskView mapping is changing, do not preserve the visuals. Since we are
// mostly preserving the first task, and new taskViews are added to the end, it should
// generally map to the same task.
mIgnoreResetTaskId = -1;
mIgnoreResetTaskId = INVALID_TASK_ID;
}
resetTaskVisuals();
onTaskStackUpdated();
@@ -1794,7 +1781,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
* Returns the number of tasks in the bottom row of the overview grid.
*/
public int getBottomRowTaskCountForTablet() {
return getTaskViewCount() - mTopRowIdSet.size() - 1;
return getTaskViewCount() - mTopRowIdSet.size() - (ENABLE_GRID_ONLY_OVERVIEW.get() ? 0 : 1);
}
protected void onTaskStackUpdated() {
@@ -2000,7 +1987,8 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
}
public void getTaskSize(Rect outRect) {
mSizeStrategy.calculateTaskSize(mActivity, mActivity.getDeviceProfile(), outRect);
mSizeStrategy.calculateTaskSize(mActivity, mActivity.getDeviceProfile(), outRect,
mOrientationHandler);
mLastComputedTaskSize.set(outRect);
}
@@ -2045,7 +2033,8 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
/** Gets the task size for modal state. */
public void getModalTaskSize(Rect outRect) {
mSizeStrategy.calculateModalTaskSize(mActivity, mActivity.getDeviceProfile(), outRect);
mSizeStrategy.calculateModalTaskSize(mActivity, mActivity.getDeviceProfile(), outRect,
mOrientationHandler);
}
@Override
@@ -2478,8 +2467,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
for (TaskViewSimulator tvs : taskViewSimulators) {
if (animatorSet == null) {
setGridProgress(1);
tvs.taskPrimaryTranslation.value =
runningTaskPrimaryGridTranslation;
tvs.taskPrimaryTranslation.value = runningTaskPrimaryGridTranslation;
} else {
animatorSet.play(ObjectAnimator.ofFloat(this, RECENTS_GRID_PROGRESS, 1));
animatorSet.play(tvs.taskPrimaryTranslation.animateToValue(
@@ -2588,7 +2576,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
boolean runningTaskTileHidden = mRunningTaskTileHidden;
setCurrentTask(runningTaskViewId);
mFocusedTaskViewId = runningTaskViewId;
mFocusedTaskViewId = ENABLE_GRID_ONLY_OVERVIEW.get() ? INVALID_TASK_ID : runningTaskViewId;
runOnPageScrollsInitialized(() -> setCurrentPage(getRunningTaskIndex()));
setRunningTaskViewShowScreenshot(false);
setRunningTaskHidden(runningTaskTileHidden);
@@ -2721,7 +2709,8 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
return;
}
int taskTopMargin = mActivity.getDeviceProfile().overviewTaskThumbnailTopMarginPx;
DeviceProfile deviceProfile = mActivity.getDeviceProfile();
int taskTopMargin = deviceProfile.overviewTaskThumbnailTopMarginPx;
int topRowWidth = 0;
int bottomRowWidth = 0;
@@ -2863,7 +2852,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
float snappedTaskGridTranslationX = 0;
if (snappedTaskView != null) {
snappedTaskNonGridScrollAdjustment = snappedTaskView.getScrollAdjustment(
/*fullscreenEnabled=*/true, /*gridEnabled=*/false);
/*gridEnabled=*/false);
snappedTaskGridTranslationX = gridTranslations[snappedPage];
}
@@ -2888,18 +2877,28 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
// 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;
float clearAllShortTotalWidthTranslation = 0;
int longRowWidth = Math.max(topRowWidth, bottomRowWidth);
if (longRowWidth < mLastComputedGridSize.width()) {
float shortTotalCompensation = mLastComputedGridSize.width() - longRowWidth;
clearAllShortTotalCompensation =
mIsRtl ? -shortTotalCompensation : shortTotalCompensation;
longRowWidth = mLastComputedGridSize.width();
mClearAllShortTotalWidthTranslation =
(mIsRtl
? mLastComputedTaskSize.right
: deviceProfile.widthPx - mLastComputedTaskSize.left)
- longRowWidth - deviceProfile.overviewGridSideMargin;
clearAllShortTotalWidthTranslation = mIsRtl
? -mClearAllShortTotalWidthTranslation : mClearAllShortTotalWidthTranslation;
if (snappedTaskRowWidth == longRowWidth) {
// Updated snappedTaskRowWidth as well if it's same as longRowWidth.
snappedTaskRowWidth += mClearAllShortTotalWidthTranslation;
}
longRowWidth += mClearAllShortTotalWidthTranslation;
} else {
mClearAllShortTotalWidthTranslation = 0;
}
float clearAllTotalTranslationX =
clearAllAccumulatedTranslation + clearAllShorterRowCompensation
+ clearAllShortTotalCompensation + snappedTaskNonGridScrollAdjustment;
+ clearAllShortTotalWidthTranslation + snappedTaskNonGridScrollAdjustment;
if (focusedTaskIndex < taskCount) {
// Shift by focused task's width and spacing if a task is focused.
clearAllTotalTranslationX +=
@@ -2909,11 +2908,15 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
// Make sure there are enough space between snapped page and ClearAllButton, for the case
// of swiping up after quick switch.
if (snappedTaskView != null) {
int distanceFromClearAll = longRowWidth - snappedTaskRowWidth + mPageSpacing;
int distanceFromClearAll = longRowWidth - snappedTaskRowWidth;
// ClearAllButton should be off screen when snapped task is in its snapped position.
int minimumDistance =
mTaskWidth - snappedTaskView.getLayoutParams().width
+ (mLastComputedGridSize.width() - mTaskWidth) / 2;
(mIsRtl
? mLastComputedTaskSize.left
: deviceProfile.widthPx - mLastComputedTaskSize.right)
- deviceProfile.overviewGridSideMargin - mPageSpacing
+ (mTaskWidth - snappedTaskView.getLayoutParams().width)
- mClearAllShortTotalWidthTranslation;
if (distanceFromClearAll < minimumDistance) {
int distanceDifference = minimumDistance - distanceFromClearAll;
snappedTaskGridTranslationX += mIsRtl ? distanceDifference : -distanceDifference;
@@ -3196,6 +3199,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
// Grid specific properties.
boolean isFocusedTaskDismissed = false;
boolean isStagingFocusedTask = false;
TaskView nextFocusedTaskView = null;
boolean nextFocusedTaskFromTop = false;
float dismissedTaskWidth = 0;
@@ -3210,26 +3214,30 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
if (showAsGrid) {
dismissedTaskWidth = dismissedTaskView.getLayoutParams().width + mPageSpacing;
isFocusedTaskDismissed = dismissedTaskViewId == mFocusedTaskViewId;
if (isFocusedTaskDismissed && !isSplitSelectionActive()) {
nextFocusedTaskFromTop =
mTopRowIdSet.size() > 0 && mTopRowIdSet.size() >= (taskCount - 1) / 2f;
// Pick the next focused task from the preferred row.
for (int i = 0; i < taskCount; i++) {
TaskView taskView = requireTaskViewAt(i);
if (taskView == dismissedTaskView) {
continue;
if (isFocusedTaskDismissed) {
if (isSplitSelectionActive()) {
isStagingFocusedTask = true;
} else {
nextFocusedTaskFromTop =
mTopRowIdSet.size() > 0 && mTopRowIdSet.size() >= (taskCount - 1) / 2f;
// Pick the next focused task from the preferred row.
for (int i = 0; i < taskCount; i++) {
TaskView taskView = requireTaskViewAt(i);
if (taskView == dismissedTaskView) {
continue;
}
boolean isTopRow = mTopRowIdSet.contains(taskView.getTaskViewId());
if ((nextFocusedTaskFromTop && isTopRow
|| (!nextFocusedTaskFromTop && !isTopRow))) {
nextFocusedTaskView = taskView;
break;
}
}
boolean isTopRow = mTopRowIdSet.contains(taskView.getTaskViewId());
if ((nextFocusedTaskFromTop && isTopRow
|| (!nextFocusedTaskFromTop && !isTopRow))) {
nextFocusedTaskView = taskView;
break;
if (nextFocusedTaskView != null) {
nextFocusedTaskWidth =
nextFocusedTaskView.getLayoutParams().width + mPageSpacing;
}
}
if (nextFocusedTaskView != null) {
nextFocusedTaskWidth =
nextFocusedTaskView.getLayoutParams().width + mPageSpacing;
}
}
} else {
getPageScrolls(oldScroll, false, SIMPLE_SCROLL_LOGIC);
@@ -3246,8 +3254,6 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
boolean snapToLastTask = false;
boolean isLandscapeSplit =
mActivity.getDeviceProfile().isLandscape && isSplitSelectionActive();
boolean isSplitPlaceholderFirstInGrid = isSplitPlaceholderFirstInGrid();
boolean isSplitPlaceholderLastInGrid = isSplitPlaceholderLastInGrid();
TaskView lastGridTaskView = showAsGrid ? getLastGridTaskView() : null;
int currentPageScroll = getScrollForPage(mCurrentPage);
int lastGridTaskScroll = getScrollForPage(indexOfChild(lastGridTaskView));
@@ -3259,42 +3265,69 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
float longGridRowWidthDiff = 0;
int topGridRowSize = mTopRowIdSet.size();
int bottomGridRowSize = taskCount - mTopRowIdSet.size() - 1;
int bottomGridRowSize = taskCount - mTopRowIdSet.size()
- (ENABLE_GRID_ONLY_OVERVIEW.get() ? 0 : 1);
boolean topRowLonger = topGridRowSize > bottomGridRowSize;
boolean bottomRowLonger = bottomGridRowSize > topGridRowSize;
boolean dismissedTaskFromTop = mTopRowIdSet.contains(dismissedTaskViewId);
boolean dismissedTaskFromBottom = !dismissedTaskFromTop && !isFocusedTaskDismissed;
if (dismissedTaskFromTop || (isFocusedTaskDismissed && nextFocusedTaskFromTop)) {
topGridRowSize--;
}
if (dismissedTaskFromBottom || (isFocusedTaskDismissed && !nextFocusedTaskFromTop)) {
bottomGridRowSize--;
}
int longRowWidth = Math.max(topGridRowSize, bottomGridRowSize)
* (mLastComputedGridTaskSize.width() + mPageSpacing);
if (!ENABLE_GRID_ONLY_OVERVIEW.get() && !isStagingFocusedTask) {
longRowWidth += mLastComputedTaskSize.width() + mPageSpacing;
}
float gapWidth = 0;
if ((topRowLonger && dismissedTaskFromTop)
|| (bottomRowLonger && dismissedTaskFromBottom)) {
gapWidth = dismissedTaskWidth;
} else if ((topRowLonger && nextFocusedTaskFromTop)
|| (bottomRowLonger && !nextFocusedTaskFromTop)) {
} else if (nextFocusedTaskView != null
&& ((topRowLonger && nextFocusedTaskFromTop)
|| (bottomRowLonger && !nextFocusedTaskFromTop))) {
gapWidth = nextFocusedTaskWidth;
}
if (gapWidth > 0) {
if (taskCount > 2) {
// Compensate the removed gap.
longGridRowWidthDiff += mIsRtl ? -gapWidth : gapWidth;
if (isClearAllHidden) {
// If ClearAllButton isn't fully shown, snap to the last task.
snapToLastTask = true;
if (mClearAllShortTotalWidthTranslation == 0) {
// Compensate the removed gap if we don't already have shortTotalCompensation,
// and adjust accordingly to the new shortTotalCompensation after dismiss.
int newClearAllShortTotalWidthTranslation = 0;
if (longRowWidth < mLastComputedGridSize.width()) {
DeviceProfile deviceProfile = mActivity.getDeviceProfile();
newClearAllShortTotalWidthTranslation =
(mIsRtl
? mLastComputedTaskSize.right
: deviceProfile.widthPx - mLastComputedTaskSize.left)
- longRowWidth - deviceProfile.overviewGridSideMargin;
}
} else {
// If only focused task will be left, snap to focused task instead.
longGridRowWidthDiff += getSnapToFocusedTaskScrollDiff(isClearAllHidden);
float gapCompensation = gapWidth - newClearAllShortTotalWidthTranslation;
longGridRowWidthDiff += mIsRtl ? -gapCompensation : gapCompensation;
}
if (isClearAllHidden) {
// If ClearAllButton isn't fully shown, snap to the last task.
snapToLastTask = true;
}
}
if (mClearAllButton.getAlpha() != 0f && isLandscapeSplit) {
// ClearAllButton will not be available in split select, snap to last task instead.
snapToLastTask = true;
if (isLandscapeSplit && !isStagingFocusedTask) {
// LastTask's scroll is the minimum scroll in split select, if current scroll is
// beyond that, we'll need to snap to last task instead.
TaskView lastTask = getLastGridTaskView();
if (lastTask != null) {
int primaryScroll = mOrientationHandler.getPrimaryScroll(this);
int lastTaskScroll = getScrollForPage(indexOfChild(lastTask));
if ((mIsRtl && primaryScroll < lastTaskScroll)
|| (!mIsRtl && primaryScroll > lastTaskScroll)) {
snapToLastTask = true;
}
}
}
if (snapToLastTask) {
longGridRowWidthDiff += getSnapToLastTaskScrollDiff();
if (isSplitPlaceholderLastInGrid) {
// Shift all the tasks to make space for split placeholder.
longGridRowWidthDiff += mIsRtl ? mSplitPlaceholderSize : -mSplitPlaceholderSize;
}
} else if (isLandscapeSplit && currentPageSnapsToEndOfGrid) {
// Use last task as reference point for scroll diff and snapping calculation as it's
// the only invariant point in landscape split screen.
@@ -3452,8 +3485,6 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
// dismissed index or next focused index. Offset successive task dismissal
// durations for a staggered effect.
distanceFromDismissedTask++;
boolean isStagingFocusedTask =
isFocusedTaskDismissed && nextFocusedTaskView == null;
int staggerColumn = isStagingFocusedTask
? (int) Math.ceil(distanceFromDismissedTask / 2f)
: distanceFromDismissedTask;
@@ -3509,11 +3540,6 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
int focusedTaskScrollDiff = primaryScroll - focusedTaskScroll;
primaryTranslation +=
mIsRtl ? focusedTaskScrollDiff : -focusedTaskScrollDiff;
if (isSplitPlaceholderFirstInGrid) {
// Moves less if split placeholder is at the start.
primaryTranslation +=
mIsRtl ? -mSplitPlaceholderSize : mSplitPlaceholderSize;
}
}
anim.setFloat(taskView, taskView.getPrimaryDismissTranslationProperty(),
@@ -3642,14 +3668,6 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
RecentsView.this);
int currentPageScroll = getScrollForPage(mCurrentPage);
mCurrentPageScrollDiff = primaryScroll - currentPageScroll;
// Compensate for coordinate shift by split placeholder.
if (isSplitPlaceholderFirstInGrid && !finalSnapToLastTask) {
mCurrentPageScrollDiff +=
mIsRtl ? -mSplitPlaceholderSize : mSplitPlaceholderSize;
} else if (isSplitPlaceholderLastInGrid && finalSnapToLastTask) {
mCurrentPageScrollDiff +=
mIsRtl ? mSplitPlaceholderSize : -mSplitPlaceholderSize;
}
}
}
} else if (dismissedIndex < pageToSnapTo || pageToSnapTo == taskCount - 1) {
@@ -3670,7 +3688,9 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
} else {
// Update focus task and its size.
if (finalIsFocusedTaskDismissed && finalNextFocusedTaskView != null) {
mFocusedTaskViewId = finalNextFocusedTaskView.getTaskViewId();
mFocusedTaskViewId = ENABLE_GRID_ONLY_OVERVIEW.get()
? INVALID_TASK_ID
: finalNextFocusedTaskView.getTaskViewId();
mTopRowIdSet.remove(mFocusedTaskViewId);
finalNextFocusedTaskView.animateIconScaleAndDimIntoView();
}
@@ -3689,8 +3709,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
int screenStart = mOrientationHandler.getPrimaryScroll(
RecentsView.this);
int taskStart = mOrientationHandler.getChildStart(taskView)
+ (int) taskView.getOffsetAdjustment(/*fullscreenEnabled=*/
false, /*gridEnabled=*/ true);
+ (int) taskView.getOffsetAdjustment(/*gridEnabled=*/ true);
// Rebalance only if there is a maximum gap between the task and the
// screen's edge; this ensures that rebalanced tasks are outside the
@@ -3853,14 +3872,6 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
REMOVE_TASK_WAIT_FOR_APP_STOP_MS);
}
/**
* Returns {@code true} if one of the task thumbnails would intersect/overlap with the
* {@link #mFirstFloatingTaskView}.
*/
public boolean shouldShiftThumbnailsForSplitSelect() {
return !mActivity.getDeviceProfile().isTablet || !mActivity.getDeviceProfile().isLandscape;
}
protected void onDismissAnimationEnds() {
AccessibilityManagerCompat.sendDismissAnimationEndsEventToTest(getContext());
}
@@ -4418,65 +4429,6 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
}
}
/**
* Apply scroll offset to children of RecentsView when entering split select.
*/
public void applySplitPrimaryScrollOffset() {
float taskSplitScrollOffsetPrimary = 0f;
float clearAllSplitScrollOffsetPrimar = 0f;
if (isSplitPlaceholderFirstInGrid()) {
taskSplitScrollOffsetPrimary = mIsRtl ? mSplitPlaceholderSize : -mSplitPlaceholderSize;
} else if (isSplitPlaceholderLastInGrid()) {
clearAllSplitScrollOffsetPrimar =
mIsRtl ? -mSplitPlaceholderSize : mSplitPlaceholderSize;
}
for (int i = 0; i < getTaskViewCount(); i++) {
requireTaskViewAt(i).setSplitScrollOffsetPrimary(taskSplitScrollOffsetPrimary);
}
mClearAllButton.setSplitSelectScrollOffsetPrimary(clearAllSplitScrollOffsetPrimar);
}
/**
* Returns if split placeholder is at the beginning of RecentsView. Always returns {@code false}
* if RecentsView is in portrait or RecentsView isn't shown as grid.
*/
private boolean isSplitPlaceholderFirstInGrid() {
if (!mActivity.getDeviceProfile().isLandscape || !showAsGrid()
|| !isSplitSelectionActive()) {
return false;
}
@StagePosition int position = mSplitSelectStateController.getActiveSplitStagePosition();
return mIsRtl
? position == STAGE_POSITION_BOTTOM_OR_RIGHT
: position == STAGE_POSITION_TOP_OR_LEFT;
}
/**
* Returns if split placeholder is at the end of RecentsView. Always returns {@code false} if
* RecentsView is in portrait or RecentsView isn't shown as grid.
*/
private boolean isSplitPlaceholderLastInGrid() {
if (!mActivity.getDeviceProfile().isLandscape || !showAsGrid()
|| !isSplitSelectionActive()) {
return false;
}
@StagePosition int position = mSplitSelectStateController.getActiveSplitStagePosition();
return mIsRtl
? position == STAGE_POSITION_TOP_OR_LEFT
: position == STAGE_POSITION_BOTTOM_OR_RIGHT;
}
/**
* Reset scroll offset on children of RecentsView when exiting split select.
*/
public void resetSplitPrimaryScrollOffset() {
for (int i = 0; i < getTaskViewCount(); i++) {
requireTaskViewAt(i).setSplitScrollOffsetPrimary(0);
}
mClearAllButton.setSplitSelectScrollOffsetPrimary(0);
}
/**
* Resets the visuals when exit modal state.
*/
@@ -4685,14 +4637,29 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
* Note that the translation can be its primary or secondary dimension.
*/
public float getSplitSelectTranslation() {
int splitPosition = getSplitSelectController().getActiveSplitStagePosition();
if (!shouldShiftThumbnailsForSplitSelect()) {
return 0f;
}
DeviceProfile deviceProfile = mActivity.getDeviceProfile();
PagedOrientationHandler orientationHandler = getPagedOrientationHandler();
int splitPosition = getSplitSelectController().getActiveSplitStagePosition();
int splitPlaceholderSize =
mActivity.getResources().getDimensionPixelSize(R.dimen.split_placeholder_size);
int direction = orientationHandler.getSplitTranslationDirectionFactor(
splitPosition, mActivity.getDeviceProfile());
return mActivity.getResources().getDimension(R.dimen.split_placeholder_size) * direction;
splitPosition, deviceProfile);
if (deviceProfile.isTablet && deviceProfile.isLandscape) {
// Only shift TaskViews if there is not enough space on the side of
// mLastComputedTaskSize to minimize motion.
int sideSpace = mIsRtl
? deviceProfile.widthPx - mLastComputedTaskSize.right
: mLastComputedTaskSize.left;
int extraSpace = splitPlaceholderSize + mPageSpacing - sideSpace;
if (extraSpace <= 0f) {
return 0f;
}
return extraSpace * direction;
}
return splitPlaceholderSize * direction;
}
protected void onRotateInSplitSelectionState() {
@@ -4714,8 +4681,6 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
if (mSplitInstructionsView != null) {
mSplitInstructionsView.ensureProperRotation();
}
applySplitPrimaryScrollOffset();
}
private void updateDeadZoneRects() {
@@ -5210,11 +5175,21 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
}
private int getLastViewIndex() {
return mDisallowScrollToClearAll
? mShowAsGridLastOnLayout
? indexOfChild(getLastGridTaskView())
: getTaskViewCount() - 1
: indexOfChild(mClearAllButton);
if (!mDisallowScrollToClearAll) {
return indexOfChild(mClearAllButton);
}
if (!mShowAsGridLastOnLayout) {
return getTaskViewCount() - 1;
}
TaskView lastGridTaskView = getLastGridTaskView();
if (lastGridTaskView != null) {
return indexOfChild(lastGridTaskView);
}
// Returns focus task if there are no grid tasks.
return indexOfChild(getFocusedTaskView());
}
/**
@@ -5255,11 +5230,11 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
}
final int taskCount = getTaskViewCount();
int lastTaskScroll = getLastTaskScroll(clearAllScroll, clearAllWidth);
for (int i = 0; i < taskCount; i++) {
TaskView taskView = requireTaskViewAt(i);
float scrollDiff = taskView.getScrollAdjustment(showAsFullscreen, showAsGrid);
float scrollDiff = taskView.getScrollAdjustment(showAsGrid);
int pageScroll = newPageScrolls[i] + (int) scrollDiff;
int lastTaskScroll = getLastTaskScroll(clearAllScroll, clearAllWidth);
if ((mIsRtl && pageScroll < lastTaskScroll)
|| (!mIsRtl && pageScroll > lastTaskScroll)) {
pageScroll = lastTaskScroll;
@@ -5283,8 +5258,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
int childOffset = super.getChildOffset(index);
View child = getChildAt(index);
if (child instanceof TaskView) {
childOffset += ((TaskView) child).getOffsetAdjustment(showAsFullscreen(),
showAsGrid());
childOffset += ((TaskView) child).getOffsetAdjustment(showAsGrid());
} else if (child instanceof ClearAllButton) {
childOffset += ((ClearAllButton) child).getOffsetAdjustment(mOverviewFullscreenEnabled,
showAsGrid());
@@ -5392,17 +5366,19 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
int gridTaskSizeAndSpacing = mLastComputedGridTaskSize.width() + mPageSpacing;
int positionDiff = gridTaskSizeAndSpacing * (lastGridTaskViewPosition - taskViewPosition);
int lastTaskEnd = (mIsRtl
? mLastComputedGridSize.left
: mLastComputedGridSize.right)
+ (mIsRtl ? mPageSpacing : -mPageSpacing);
int taskEnd = lastTaskEnd + (mIsRtl ? positionDiff : -positionDiff);
int taskEnd = getLastTaskEnd() + (mIsRtl ? positionDiff : -positionDiff);
int normalTaskEnd = mIsRtl
? mLastComputedGridTaskSize.left
: mLastComputedGridTaskSize.right;
return taskEnd - normalTaskEnd;
}
private int getLastTaskEnd() {
return mIsRtl
? mLastComputedGridSize.left + mPageSpacing + mClearAllShortTotalWidthTranslation
: mLastComputedGridSize.right - mPageSpacing - mClearAllShortTotalWidthTranslation;
}
private int getPositionInRow(
TaskView taskView, IntArray topRowIdArray, IntArray bottomRowIdArray) {
int position = topRowIdArray.indexOf(taskView.getTaskViewId());
@@ -5702,14 +5678,10 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
taskView = getTaskViewAt(--targetPage);
}
// Target a scroll where targetPage is on left of screen but still fully visible.
int lastTaskEnd = (mIsRtl
? mLastComputedGridSize.left
: mLastComputedGridSize.right)
+ (mIsRtl ? mPageSpacing : -mPageSpacing);
int normalTaskEnd = mIsRtl
? mLastComputedGridTaskSize.left
: mLastComputedGridTaskSize.right;
int targetScroll = getScrollForPage(targetPage) + normalTaskEnd - lastTaskEnd;
int targetScroll = getScrollForPage(targetPage) + normalTaskEnd - getLastTaskEnd();
// Find a page that is close to targetScroll while not over it.
while (targetPage - 1 >= 0
&& (mIsRtl
@@ -375,7 +375,6 @@ public class TaskView extends FrameLayout implements Reusable {
// Used when in SplitScreenSelectState
private float mSplitSelectTranslationY;
private float mSplitSelectTranslationX;
private float mSplitSelectScrollOffsetPrimary;
@Nullable
private ObjectAnimator mIconAndDimAnimator;
@@ -1297,10 +1296,6 @@ public class TaskView extends FrameLayout implements Reusable {
applyTranslationY();
}
public void setSplitScrollOffsetPrimary(float splitSelectScrollOffsetPrimary) {
mSplitSelectScrollOffsetPrimary = splitSelectScrollOffsetPrimary;
}
private void setDismissTranslationX(float x) {
mDismissTranslationX = x;
applyTranslationX();
@@ -1364,19 +1359,18 @@ public class TaskView extends FrameLayout implements Reusable {
applyTranslationX();
}
public float getScrollAdjustment(boolean fullscreenEnabled, boolean gridEnabled) {
public float getScrollAdjustment(boolean gridEnabled) {
float scrollAdjustment = 0;
if (gridEnabled) {
scrollAdjustment += mGridTranslationX;
} else {
scrollAdjustment += getPrimaryNonGridTranslationProperty().get(this);
}
scrollAdjustment += mSplitSelectScrollOffsetPrimary;
return scrollAdjustment;
}
public float getOffsetAdjustment(boolean fullscreenEnabled, boolean gridEnabled) {
return getScrollAdjustment(fullscreenEnabled, gridEnabled);
public float getOffsetAdjustment(boolean gridEnabled) {
return getScrollAdjustment(gridEnabled);
}
public float getSizeAdjustment(boolean fullscreenEnabled) {
@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 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.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="48dp"
android:height="48dp"
android:viewportWidth="48"
android:viewportHeight="48">
<path
android:pathData="M13.5,17C12.538,17 11.715,16.65 11.033,15.967C10.35,15.285 10,14.462 10,13.5C10,12.538 10.35,11.715 11.033,11.033C11.715,10.35 12.538,10 13.5,10C14.462,10 15.285,10.35 15.967,11.033C16.65,11.715 17,12.538 17,13.5C17,14.462 16.65,15.285 15.967,15.967C15.285,16.65 14.462,17 13.5,17Z"
android:fillColor="#40484B"/>
<path
android:pathData="M24,17C23.038,17 22.215,16.65 21.532,15.967C20.85,15.285 20.5,14.462 20.5,13.5C20.5,12.538 20.85,11.715 21.532,11.033C22.215,10.35 23.038,10 24,10C24.962,10 25.785,10.35 26.468,11.033C27.15,11.715 27.5,12.538 27.5,13.5C27.5,14.462 27.15,15.285 26.468,15.967C25.785,16.65 24.962,17 24,17Z"
android:fillColor="#40484B"/>
<path
android:pathData="M34.5,17C33.537,17 32.715,16.65 32.033,15.967C31.35,15.285 31,14.462 31,13.5C31,12.538 31.35,11.715 32.033,11.033C32.715,10.35 33.537,10 34.5,10C35.463,10 36.285,10.35 36.967,11.033C37.65,11.715 38,12.538 38,13.5C38,14.462 37.65,15.285 36.967,15.967C36.285,16.65 35.463,17 34.5,17Z"
android:fillColor="#40484B"/>
<path
android:pathData="M13.5,27.5C12.538,27.5 11.715,27.15 11.033,26.468C10.35,25.785 10,24.962 10,24C10,23.038 10.35,22.215 11.033,21.532C11.715,20.85 12.538,20.5 13.5,20.5C14.462,20.5 15.285,20.85 15.967,21.532C16.65,22.215 17,23.038 17,24C17,24.962 16.65,25.785 15.967,26.468C15.285,27.15 14.462,27.5 13.5,27.5Z"
android:fillColor="#40484B"/>
<path
android:pathData="M24,27.5C23.038,27.5 22.215,27.15 21.532,26.468C20.85,25.785 20.5,24.962 20.5,24C20.5,23.038 20.85,22.215 21.532,21.532C22.215,20.85 23.038,20.5 24,20.5C24.962,20.5 25.785,20.85 26.468,21.532C27.15,22.215 27.5,23.038 27.5,24C27.5,24.962 27.15,25.785 26.468,26.468C25.785,27.15 24.962,27.5 24,27.5Z"
android:fillColor="#40484B"/>
<path
android:pathData="M34.5,27.5C33.537,27.5 32.715,27.15 32.033,26.468C31.35,25.785 31,24.962 31,24C31,23.038 31.35,22.215 32.033,21.532C32.715,20.85 33.537,20.5 34.5,20.5C35.463,20.5 36.285,20.85 36.967,21.532C37.65,22.215 38,23.038 38,24C38,24.962 37.65,25.785 36.967,26.468C36.285,27.15 35.463,27.5 34.5,27.5Z"
android:fillColor="#40484B"/>
<path
android:pathData="M13.5,38C12.538,38 11.715,37.65 11.033,36.967C10.35,36.285 10,35.463 10,34.5C10,33.537 10.35,32.715 11.033,32.033C11.715,31.35 12.538,31 13.5,31C14.462,31 15.285,31.35 15.967,32.033C16.65,32.715 17,33.537 17,34.5C17,35.463 16.65,36.285 15.967,36.967C15.285,37.65 14.462,38 13.5,38Z"
android:fillColor="#40484B"/>
<path
android:pathData="M24,38C23.038,38 22.215,37.65 21.532,36.967C20.85,36.285 20.5,35.463 20.5,34.5C20.5,33.537 20.85,32.715 21.532,32.033C22.215,31.35 23.038,31 24,31C24.962,31 25.785,31.35 26.468,32.033C27.15,32.715 27.5,33.537 27.5,34.5C27.5,35.463 27.15,36.285 26.468,36.967C25.785,37.65 24.962,38 24,38Z"
android:fillColor="#40484B"/>
<path
android:pathData="M34.5,38C33.537,38 32.715,37.65 32.033,36.967C31.35,36.285 31,35.463 31,34.5C31,33.537 31.35,32.715 32.033,32.033C32.715,31.35 33.537,31 34.5,31C35.463,31 36.285,31.35 36.967,32.033C37.65,32.715 38,33.537 38,34.5C38,35.463 37.65,36.285 36.967,36.967C36.285,37.65 35.463,38 34.5,38Z"
android:fillColor="#40484B"/>
</vector>
@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 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.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="44dp"
android:height="44dp"
android:viewportWidth="44"
android:viewportHeight="44">
<path
android:pathData="M13,16C12.175,16 11.47,15.7 10.885,15.115C10.3,14.53 10,13.825 10,13C10,12.175 10.3,11.47 10.885,10.885C11.47,10.3 12.175,10 13,10C13.825,10 14.53,10.3 15.115,10.885C15.7,11.47 16,12.175 16,13C16,13.825 15.7,14.53 15.115,15.115C14.53,15.7 13.825,16 13,16Z"
android:fillColor="#40484B"/>
<path
android:pathData="M22,16C21.175,16 20.47,15.7 19.885,15.115C19.3,14.53 19,13.825 19,13C19,12.175 19.3,11.47 19.885,10.885C20.47,10.3 21.175,10 22,10C22.825,10 23.53,10.3 24.115,10.885C24.7,11.47 25,12.175 25,13C25,13.825 24.7,14.53 24.115,15.115C23.53,15.7 22.825,16 22,16Z"
android:fillColor="#40484B"/>
<path
android:pathData="M31,16C30.175,16 29.47,15.7 28.885,15.115C28.3,14.53 28,13.825 28,13C28,12.175 28.3,11.47 28.885,10.885C29.47,10.3 30.175,10 31,10C31.825,10 32.53,10.3 33.115,10.885C33.7,11.47 34,12.175 34,13C34,13.825 33.7,14.53 33.115,15.115C32.53,15.7 31.825,16 31,16Z"
android:fillColor="#40484B"/>
<path
android:pathData="M13,25C12.175,25 11.47,24.7 10.885,24.115C10.3,23.53 10,22.825 10,22C10,21.175 10.3,20.47 10.885,19.885C11.47,19.3 12.175,19 13,19C13.825,19 14.53,19.3 15.115,19.885C15.7,20.47 16,21.175 16,22C16,22.825 15.7,23.53 15.115,24.115C14.53,24.7 13.825,25 13,25Z"
android:fillColor="#40484B"/>
<path
android:pathData="M22,25C21.175,25 20.47,24.7 19.885,24.115C19.3,23.53 19,22.825 19,22C19,21.175 19.3,20.47 19.885,19.885C20.47,19.3 21.175,19 22,19C22.825,19 23.53,19.3 24.115,19.885C24.7,20.47 25,21.175 25,22C25,22.825 24.7,23.53 24.115,24.115C23.53,24.7 22.825,25 22,25Z"
android:fillColor="#40484B"/>
<path
android:pathData="M31,25C30.175,25 29.47,24.7 28.885,24.115C28.3,23.53 28,22.825 28,22C28,21.175 28.3,20.47 28.885,19.885C29.47,19.3 30.175,19 31,19C31.825,19 32.53,19.3 33.115,19.885C33.7,20.47 34,21.175 34,22C34,22.825 33.7,23.53 33.115,24.115C32.53,24.7 31.825,25 31,25Z"
android:fillColor="#40484B"/>
<path
android:pathData="M13,34C12.175,34 11.47,33.7 10.885,33.115C10.3,32.53 10,31.825 10,31C10,30.175 10.3,29.47 10.885,28.885C11.47,28.3 12.175,28 13,28C13.825,28 14.53,28.3 15.115,28.885C15.7,29.47 16,30.175 16,31C16,31.825 15.7,32.53 15.115,33.115C14.53,33.7 13.825,34 13,34Z"
android:fillColor="#40484B"/>
<path
android:pathData="M22,34C21.175,34 20.47,33.7 19.885,33.115C19.3,32.53 19,31.825 19,31C19,30.175 19.3,29.47 19.885,28.885C20.47,28.3 21.175,28 22,28C22.825,28 23.53,28.3 24.115,28.885C24.7,29.47 25,30.175 25,31C25,31.825 24.7,32.53 24.115,33.115C23.53,33.7 22.825,34 22,34Z"
android:fillColor="#40484B"/>
<path
android:pathData="M31,34C30.175,34 29.47,33.7 28.885,33.115C28.3,32.53 28,31.825 28,31C28,30.175 28.3,29.47 28.885,28.885C29.47,28.3 30.175,28 31,28C31.825,28 32.53,28.3 33.115,28.885C33.7,29.47 34,30.175 34,31C34,31.825 33.7,32.53 33.115,33.115C32.53,33.7 31.825,34 31,34Z"
android:fillColor="#40484B"/>
</vector>
@@ -113,6 +113,8 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
private float mScaleForReorderBounce = 1f;
private float mTranslationXForTaskbarAllAppsIcon = 0f;
private static final Property<BubbleTextView, Float> DOT_SCALE_PROPERTY
= new Property<BubbleTextView, Float>(Float.TYPE, "dotScale") {
@Override
@@ -961,6 +963,7 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
private void updateTranslation() {
super.setTranslationX(mTranslationForReorderBounce.x
+ mTranslationForReorderPreview.x
+ mTranslationXForTaskbarAllAppsIcon
+ mTranslationForMoveFromCenterAnimation.x
+ mTranslationXForTaskbarAlignmentAnimation
+ mTranslationXForTaskbarRevealAnimation
@@ -972,6 +975,14 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
+ mTranslationYForTaskbarRevealAnimation);
}
/**
* Sets translationX for taskbar all apps icon
*/
public void setTranslationXForTaskbarAllAppsIcon(float translationX) {
mTranslationXForTaskbarAllAppsIcon = translationX;
updateTranslation();
}
public void setReorderBounceOffset(float x, float y) {
mTranslationForReorderBounce.set(x, y);
updateTranslation();
+9
View File
@@ -1860,6 +1860,9 @@ public class Launcher extends StatefulActivity<LauncherState>
}
private void setWorkspaceLoading(boolean value) {
if (TestProtocol.sDebugTracing) {
Log.d(TestProtocol.FLAKY_BINDING, "running: setWorkspaceLoading=" + value);
}
mWorkspaceLoading = value;
}
@@ -2306,6 +2309,9 @@ public class Launcher extends StatefulActivity<LauncherState>
*/
public void startBinding() {
Object traceToken = TraceHelper.INSTANCE.beginSection("startBinding");
if (TestProtocol.sDebugTracing) {
Log.d(TestProtocol.FLAKY_BINDING, "running: startBinding");
}
// Floating panels (except the full widget sheet) are associated with individual icons. If
// we are starting a fresh bind, close all such panels as all the icons are about
// to go away.
@@ -2778,6 +2784,9 @@ public class Launcher extends StatefulActivity<LauncherState>
*/
public void finishBindingItems(IntSet pagesBoundFirst) {
Object traceToken = TraceHelper.INSTANCE.beginSection("finishBindingItems");
if (TestProtocol.sDebugTracing) {
Log.d(TestProtocol.FLAKY_BINDING, "running: finishBindingItems");
}
mWorkspace.restoreInstanceStateForRemainingPages();
setWorkspaceLoading(false);
+3 -3
View File
@@ -134,10 +134,10 @@ public final class Utilities {
/**
* Indicates if the device has a debug build. Should only be used to store additional info or
* add extra logging and not for changing the app behavior.
* @deprecated Use {@link BuildConfig#IS_DEBUG_DEVICE} directly
*/
public static final boolean IS_DEBUG_DEVICE =
Build.TYPE.toLowerCase(Locale.ROOT).contains("debug") ||
Build.TYPE.toLowerCase(Locale.ROOT).equals("eng");
@Deprecated
public static final boolean IS_DEBUG_DEVICE = BuildConfig.IS_DEBUG_DEVICE;
/**
* Returns true if theme is dark.
@@ -42,18 +42,22 @@ public final class FeatureFlags {
}
public static boolean showFlagTogglerUi(Context context) {
return Utilities.IS_DEBUG_DEVICE && Utilities.isDevelopersOptionsEnabled(context);
return BuildConfig.IS_DEBUG_DEVICE && Utilities.isDevelopersOptionsEnabled(context);
}
/**
* True when the build has come from Android Studio and is being used for local debugging.
* @deprecated Use {@link BuildConfig#IS_STUDIO_BUILD} directly
*/
public static final boolean IS_STUDIO_BUILD = BuildConfig.DEBUG;
@Deprecated
public static final boolean IS_STUDIO_BUILD = BuildConfig.IS_STUDIO_BUILD;
/**
* Enable moving the QSB on the 0th screen of the workspace. This is not a configuration feature
* and should be modified at a project level.
* @deprecated Use {@link BuildConfig#QSB_ON_FIRST_SCREEN} directly
*/
@Deprecated
public static final boolean QSB_ON_FIRST_SCREEN = BuildConfig.QSB_ON_FIRST_SCREEN;
/**
@@ -246,6 +246,9 @@ public abstract class BaseLauncherBinder {
sortWorkspaceItemsSpatially(idp, otherWorkspaceItems);
// Tell the workspace that we're about to start binding items
if (TestProtocol.sDebugTracing) {
Log.d(TestProtocol.FLAKY_BINDING, "scheduling: startBinding");
}
executeCallbacksTask(c -> {
c.clearPendingBinds();
c.startBinding();
@@ -264,6 +267,9 @@ public abstract class BaseLauncherBinder {
Executor pendingExecutor = pendingTasks::add;
bindWorkspaceItems(otherWorkspaceItems, pendingExecutor);
bindAppWidgets(otherAppWidgets, pendingExecutor);
if (TestProtocol.sDebugTracing) {
Log.d(TestProtocol.FLAKY_BINDING, "scheduling: finishBindingItems");
}
executeCallbacksTask(c -> c.finishBindingItems(currentScreenIds), pendingExecutor);
pendingExecutor.execute(
() -> {
@@ -31,6 +31,7 @@ import android.os.Build;
import android.util.AttributeSet;
import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
import com.android.launcher3.BubbleTextView;
import com.android.launcher3.icons.BaseIconFactory;
@@ -70,6 +71,15 @@ public class IconButtonView extends BubbleTextView {
}
}
/** Sets given Drawable as icon */
public void setIconDrawable(@NonNull Drawable drawable) {
ColorStateList tintList = getBackgroundTintList();
int tint = tintList == null ? Color.WHITE : tintList.getDefaultColor();
try (BaseIconFactory factory = LauncherIcons.obtain(getContext())) {
setIcon(new IconDrawable(factory.getWhiteShadowLayer(), tint, drawable));
}
}
/** Updates the color of the icon's foreground layer. */
public void setForegroundTint(@ColorInt int tintColor) {
FastBitmapDrawable icon = getIcon();
@@ -18,10 +18,16 @@ package com.android.launcher3;
public final class BuildConfig {
public static final String APPLICATION_ID = "com.android.launcher3";
public static final boolean DEBUG = false;
public static final boolean IS_STUDIO_BUILD = false;
/**
* Flag to state if the QSB is on the first screen and placed on the top,
* this can be overwritten in other launchers with a different value, if needed.
*/
public static final boolean QSB_ON_FIRST_SCREEN = true;
/**
* Flag to control various developer centric features
*/
public static final boolean IS_DEBUG_DEVICE = false;
}
+2 -1
View File
@@ -44,6 +44,7 @@ filegroup {
srcs: [
"src/com/android/launcher3/ui/AbstractLauncherUiTest.java",
"src/com/android/launcher3/ui/PortraitLandscapeRunner.java",
"src/com/android/launcher3/ui/TaplTestsLauncher3.java",
"src/com/android/launcher3/util/TestUtil.java",
"src/com/android/launcher3/util/Wait.java",
"src/com/android/launcher3/util/WidgetUtils.java",
@@ -54,7 +55,7 @@ filegroup {
"src/com/android/launcher3/util/rule/ShellCommandRule.java",
"src/com/android/launcher3/util/rule/SimpleActivityRule.java",
"src/com/android/launcher3/util/rule/TestStabilityRule.java",
"src/com/android/launcher3/ui/TaplTestsLauncher3.java",
"src/com/android/launcher3/util/rule/TISBindRule.java",
"src/com/android/launcher3/testcomponent/BaseTestingActivity.java",
"src/com/android/launcher3/testcomponent/OtherBaseTestingActivity.java",
"src/com/android/launcher3/testcomponent/CustomShortcutConfigActivity.java",
@@ -154,6 +154,7 @@ public final class TestProtocol {
public static final String MISSING_PROMISE_ICON = "b/202985412";
public static final String TASKBAR_IN_APP_STATE = "b/227657604";
public static final String NPE_TRANSIENT_TASKBAR = "b/257549303";
public static final String FLAKY_BINDING = "b/270216650";
public static final String REQUEST_EMULATE_DISPLAY = "emulate-display";
public static final String REQUEST_STOP_EMULATE_DISPLAY = "stop-emulate-display";
@@ -33,6 +33,7 @@ import com.android.launcher3.celllayout.testcases.ReorderTestCase;
import com.android.launcher3.celllayout.testcases.SimpleReorderCase;
import com.android.launcher3.tapl.Widget;
import com.android.launcher3.tapl.WidgetResizeFrame;
import com.android.launcher3.testing.shared.TestProtocol;
import com.android.launcher3.ui.AbstractLauncherUiTest;
import com.android.launcher3.ui.TaplTestsLauncher3;
import com.android.launcher3.util.rule.ShellCommandRule;
@@ -118,7 +119,14 @@ public class ReorderWidgets extends AbstractLauncherUiTest {
// waitForLauncherCondition to wait for that condition, otherwise the condition would
// always be true and it wouldn't wait for the changes to be applied.
resetLoaderState();
waitForLauncherCondition("Workspace didn't finish loading", l -> !l.isWorkspaceLoading());
Log.d(TestProtocol.FLAKY_BINDING, "waiting for: isWorkspaceLoading=false");
waitForLauncherCondition("Workspace didn't finish loading", l -> {
boolean isWorkspaceLoading = l.isWorkspaceLoading();
Log.d(TestProtocol.FLAKY_BINDING, "checking: isWorkspaceLoading=" + isWorkspaceLoading);
return !isWorkspaceLoading;
});
Widget widget = mLauncher.getWorkspace().getWidgetAtCell(mainWidgetCellPos.getCellX(),
mainWidgetCellPos.getCellY());
assertNotNull(widget);
@@ -52,11 +52,13 @@ import com.android.launcher3.tapl.Widgets;
import com.android.launcher3.tapl.Workspace;
import com.android.launcher3.util.TestUtil;
import com.android.launcher3.util.rule.ScreenRecordRule.ScreenRecord;
import com.android.launcher3.util.rule.TISBindRule;
import com.android.launcher3.widget.picker.WidgetsFullSheet;
import com.android.launcher3.widget.picker.WidgetsRecyclerView;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -72,6 +74,9 @@ public class TaplTestsLauncher3 extends AbstractLauncherUiTest {
private static final String STORE_APP_NAME = "Play Store";
private static final String GMAIL_APP_NAME = "Gmail";
@Rule
public TISBindRule mTISBindRule = new TISBindRule();
@Before
public void setUp() throws Exception {
super.setUp();
@@ -215,7 +220,7 @@ public class TaplTestsLauncher3 extends AbstractLauncherUiTest {
false /* tapRight */);
}
@IwTest(focusArea="launcher")
@IwTest(focusArea = "launcher")
@Test
@ScreenRecord // b/202433017
public void testWorkspace() throws Exception {
@@ -342,7 +347,7 @@ public class TaplTestsLauncher3 extends AbstractLauncherUiTest {
}
}
@IwTest(focusArea="launcher")
@IwTest(focusArea = "launcher")
@Test
@PortraitLandscape
@ScreenRecord // b/256898879
@@ -614,16 +619,16 @@ public class TaplTestsLauncher3 extends AbstractLauncherUiTest {
/**
* @return List of workspace grid coordinates. Those are not pixels. See {@link
* Workspace#getIconGridDimensions()}
* Workspace#getIconGridDimensions()}
*/
private Point[] getCornersAndCenterPositions() {
final Point dimensions = mLauncher.getWorkspace().getIconGridDimensions();
return new Point[] {
new Point(0, 1),
new Point(0, dimensions.y - 2),
new Point(dimensions.x - 1, 1),
new Point(dimensions.x - 1, dimensions.y - 2),
new Point(dimensions.x / 2, dimensions.y / 2)
return new Point[]{
new Point(0, 1),
new Point(0, dimensions.y - 2),
new Point(dimensions.x - 1, 1),
new Point(dimensions.x - 1, dimensions.y - 2),
new Point(dimensions.x / 2, dimensions.y / 2)
};
}
@@ -0,0 +1,81 @@
/*
* 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.util.rule;
import android.app.UiAutomation;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.test.platform.app.InstrumentationRegistry;
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
public class TISBindRule implements TestRule {
public static String TAG = "TISBindRule";
public static String INTENT_FILTER = "android.intent.action.QUICKSTEP_SERVICE";
public static String TIS_PERMISSIONS = "android.permission.STATUS_BAR_SERVICE";
private String getLauncherPackageName(Context context) {
return ComponentName.unflattenFromString(context.getString(
com.android.internal.R.string.config_recentsComponentName)).getPackageName();
}
private ServiceConnection createConnection() {
return new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
Log.d(TAG, "Connected to TouchInteractionService");
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
Log.d(TAG, "Disconnected from TouchInteractionService");
}
};
}
@NonNull
@Override
public Statement apply(@NonNull Statement base, @NonNull Description description) {
return new Statement() {
@Override
public void evaluate() throws Throwable {
Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
final ServiceConnection connection = createConnection();
UiAutomation uiAutomation =
InstrumentationRegistry.getInstrumentation().getUiAutomation();
uiAutomation.adoptShellPermissionIdentity(TIS_PERMISSIONS);
Intent launchIntent = new Intent(INTENT_FILTER);
launchIntent.setPackage(getLauncherPackageName(context));
context.bindService(launchIntent, connection, Context.BIND_AUTO_CREATE);
uiAutomation.dropShellPermissionIdentity();
try {
base.evaluate();
} finally {
context.unbindService(connection);
}
}
};
}
}