diff --git a/quickstep/res/layout/taskbar_all_apps_button.xml b/quickstep/res/layout/taskbar_all_apps_button.xml index 6b665e5623..c50db2e24b 100644 --- a/quickstep/res/layout/taskbar_all_apps_button.xml +++ b/quickstep/res/layout/taskbar_all_apps_button.xml @@ -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" /> diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml index bd71a9feb6..126ab7c442 100644 --- a/quickstep/res/values/dimens.xml +++ b/quickstep/res/values/dimens.xml @@ -286,6 +286,8 @@ 48dp 48dp 32dp + 6dp + 72dp @@ -295,6 +297,7 @@ 40dp 10dp 32dp + 4dp 16dp diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarAutohideSuspendController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarAutohideSuspendController.java index 2bfc7dd05f..1a54576a7e 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarAutohideSuspendController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarAutohideSuspendController.java @@ -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(); } } diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java index 50f5d9e953..bbf861bd8b 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java @@ -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)) { diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java index c1e85aac2a..0b275a85ce 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java @@ -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. diff --git a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java index e8e83288cd..07fcf48a07 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java +++ b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java @@ -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, diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java index 933fb49371..ceb7d4bdab 100644 --- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java +++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java @@ -677,7 +677,7 @@ public abstract class AbsSwipeUpHandler, @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, } private void maybeUpdateRecentsAttachedState(boolean animate) { - maybeUpdateRecentsAttachedState(animate, false /* moveFocusedTask */); + maybeUpdateRecentsAttachedState(animate, false /* moveRunningTask */); } /** @@ -705,9 +705,9 @@ public abstract class AbsSwipeUpHandler, * * 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, } 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); diff --git a/quickstep/src/com/android/quickstep/BaseActivityInterface.java b/quickstep/src/com/android/quickstep/BaseActivityInterface.java index 998439e891..d7ff8ab3fc 100644 --- a/quickstep/src/com/android/quickstep/BaseActivityInterface.java +++ b/quickstep/src/com/android/quickstep/BaseActivityInterface.java @@ -231,17 +231,20 @@ public abstract class BaseActivityInterface visibleRecentsView = activityInterface.getVisibleRecentsView(); if (visibleRecentsView != null) { - visibleRecentsView.moveFocusedTaskToFront(); + visibleRecentsView.moveRunningTaskToFront(); } if (mTaskAnimationManager.isRecentsAnimationRunning()) { cmd.mActiveCallbacks = mTaskAnimationManager.continueRecentsAnimation(gestureState); diff --git a/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java b/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java index 54e4a0d3f1..5391f4d46c 100644 --- a/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java +++ b/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java @@ -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; } diff --git a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java index 062e50e30b..11b1ab8ec9 100644 --- a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java +++ b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java @@ -130,15 +130,9 @@ public class FallbackRecentsStateController implements StateHandler extends FrameLayo requestLayout(); - mSplitButton.setCompoundDrawablesWithIntrinsicBounds( + mSplitButton.setCompoundDrawablesRelativeWithIntrinsicBounds( (dp.isLandscape ? R.drawable.ic_split_horizontal : R.drawable.ic_split_vertical), 0, 0, 0); } diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java index b237f8315f..752c3d505e 100644 --- a/quickstep/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/src/com/android/quickstep/views/RecentsView.java @@ -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 0) { TaskView taskView = requireTaskViewAt(0); @@ -1733,12 +1720,12 @@ public abstract class RecentsView setCurrentPage(getRunningTaskIndex())); setRunningTaskViewShowScreenshot(false); setRunningTaskHidden(runningTaskTileHidden); @@ -2721,7 +2709,8 @@ public abstract class RecentsView 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 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 lastTaskScroll)) { pageScroll = lastTaskScroll; @@ -5283,8 +5258,7 @@ public abstract class RecentsView= 0 && (mIsRtl diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java index fb856058db..b9aaef63ca 100644 --- a/quickstep/src/com/android/quickstep/views/TaskView.java +++ b/quickstep/src/com/android/quickstep/views/TaskView.java @@ -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) { diff --git a/res/drawable-sw600dp/ic_transient_taskbar_all_apps_button.xml b/res/drawable-sw600dp/ic_transient_taskbar_all_apps_button.xml new file mode 100644 index 0000000000..6e740aed4f --- /dev/null +++ b/res/drawable-sw600dp/ic_transient_taskbar_all_apps_button.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + diff --git a/res/drawable/ic_all_apps_button.xml b/res/drawable-sw720dp/ic_transient_taskbar_all_apps_button.xml similarity index 100% rename from res/drawable/ic_all_apps_button.xml rename to res/drawable-sw720dp/ic_transient_taskbar_all_apps_button.xml diff --git a/res/drawable/ic_taskbar_all_apps_button.xml b/res/drawable/ic_taskbar_all_apps_button.xml new file mode 100644 index 0000000000..82fbbea617 --- /dev/null +++ b/res/drawable/ic_taskbar_all_apps_button.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java index 9e28608d8b..df38c26a1b 100644 --- a/src/com/android/launcher3/BubbleTextView.java +++ b/src/com/android/launcher3/BubbleTextView.java @@ -113,6 +113,8 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver, private float mScaleForReorderBounce = 1f; + private float mTranslationXForTaskbarAllAppsIcon = 0f; + private static final Property DOT_SCALE_PROPERTY = new Property(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(); diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 06ea72c7ee..de60d05b3f 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -1860,6 +1860,9 @@ public class Launcher extends StatefulActivity } 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 */ 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 */ 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); diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java index 13efa674f3..7b9f605d87 100644 --- a/src/com/android/launcher3/Utilities.java +++ b/src/com/android/launcher3/Utilities.java @@ -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. diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java index a9e3d8d4bd..0037283e62 100644 --- a/src/com/android/launcher3/config/FeatureFlags.java +++ b/src/com/android/launcher3/config/FeatureFlags.java @@ -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; /** diff --git a/src/com/android/launcher3/model/BaseLauncherBinder.java b/src/com/android/launcher3/model/BaseLauncherBinder.java index 9f8db51629..8519a3ef52 100644 --- a/src/com/android/launcher3/model/BaseLauncherBinder.java +++ b/src/com/android/launcher3/model/BaseLauncherBinder.java @@ -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( () -> { diff --git a/src/com/android/launcher3/views/IconButtonView.java b/src/com/android/launcher3/views/IconButtonView.java index 64e9327dfa..9969eebe06 100644 --- a/src/com/android/launcher3/views/IconButtonView.java +++ b/src/com/android/launcher3/views/IconButtonView.java @@ -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(); diff --git a/src_build_config/com/android/launcher3/BuildConfig.java b/src_build_config/com/android/launcher3/BuildConfig.java index 9a81d3f54c..1f2e0e5387 100644 --- a/src_build_config/com/android/launcher3/BuildConfig.java +++ b/src_build_config/com/android/launcher3/BuildConfig.java @@ -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; } diff --git a/tests/Android.bp b/tests/Android.bp index 7144d65d64..dfbaf86a50 100644 --- a/tests/Android.bp +++ b/tests/Android.bp @@ -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", diff --git a/tests/shared/com/android/launcher3/testing/shared/TestProtocol.java b/tests/shared/com/android/launcher3/testing/shared/TestProtocol.java index 65873f199e..cc6fa33609 100644 --- a/tests/shared/com/android/launcher3/testing/shared/TestProtocol.java +++ b/tests/shared/com/android/launcher3/testing/shared/TestProtocol.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"; diff --git a/tests/src/com/android/launcher3/celllayout/ReorderWidgets.java b/tests/src/com/android/launcher3/celllayout/ReorderWidgets.java index 77fca96f04..c2fe3de407 100644 --- a/tests/src/com/android/launcher3/celllayout/ReorderWidgets.java +++ b/tests/src/com/android/launcher3/celllayout/ReorderWidgets.java @@ -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); diff --git a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java index 393c54f2f0..66187659db 100644 --- a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java +++ b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java @@ -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) }; } diff --git a/tests/src/com/android/launcher3/util/rule/TISBindRule.java b/tests/src/com/android/launcher3/util/rule/TISBindRule.java new file mode 100644 index 0000000000..3ec4a29cdf --- /dev/null +++ b/tests/src/com/android/launcher3/util/rule/TISBindRule.java @@ -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); + } + } + }; + } +}