From e543818bb61246f5eae3159104134b193431ec85 Mon Sep 17 00:00:00 2001 From: Jon Miranda Date: Mon, 20 May 2019 10:01:15 -0700 Subject: [PATCH 01/21] Fix bug where FolderIcon stays visible during swipe up to home animation. This can happen when opening an app from a folder, and then immediately swiping up back to home. This happens because when we swipe up to go home, there's a race condition where the folder close animation finishes and sets the FolderIcon to VISIBLE right before FloatingIconView sets it to INVISIBLE. To fix it, in OverviewState#onStateEnabled we call AbstractFloatingView#closeAllOpenViews(animate=false). Then we added logic to cancel any Folder closing animation (which there is, from WindowTransformSwipeHandler#onLauncherStart) and to just close the folder right then and there. Bug: 132588097 Change-Id: I4379431815e7cbddede5ea0213fe9323f001484b --- .../launcher3/uioverrides/states/BackgroundAppState.java | 8 ++++++++ src/com/android/launcher3/folder/Folder.java | 4 ++++ 2 files changed, 12 insertions(+) diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java index f429ce5b04..a662d7433e 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java @@ -17,6 +17,7 @@ package com.android.launcher3.uioverrides.states; import static com.android.launcher3.LauncherAnimUtils.OVERVIEW_TRANSITION_MS; +import com.android.launcher3.AbstractFloatingView; import com.android.launcher3.Launcher; import com.android.launcher3.allapps.AllAppsTransitionController; import com.android.launcher3.userevent.nano.LauncherLogProto; @@ -41,6 +42,13 @@ public class BackgroundAppState extends OverviewState { super(id, logContainer, OVERVIEW_TRANSITION_MS, STATE_FLAGS); } + @Override + public void onStateEnabled(Launcher launcher) { + RecentsView rv = launcher.getOverviewPanel(); + rv.setOverviewStateEnabled(true); + AbstractFloatingView.closeAllOpenViews(launcher, false); + } + @Override public float getVerticalProgress(Launcher launcher) { if (launcher.getDeviceProfile().isVerticalBarLayout()) { diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java index 389e85269b..2ef6d707e3 100644 --- a/src/com/android/launcher3/folder/Folder.java +++ b/src/com/android/launcher3/folder/Folder.java @@ -593,6 +593,10 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo protected void handleClose(boolean animate) { mIsOpen = false; + if (!animate && mCurrentAnimator != null && mCurrentAnimator.isRunning()) { + mCurrentAnimator.cancel(); + } + if (isEditingName()) { mFolderName.dispatchBackKey(); } From 1b40b731b2967d47b9d3f4606f97e87a0978e3db Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Mon, 20 May 2019 10:08:34 -0700 Subject: [PATCH 02/21] Using different resource size for touch region in landscape Bug: 132917885 Change-Id: Ib702fd17fecff980db2e1d00f05cd055bcc3185a --- .../quickstep/TouchInteractionService.java | 18 +++++++++++++----- src/com/android/launcher3/ResourceUtils.java | 6 ++++-- .../launcher3/ui/AbstractLauncherUiTest.java | 2 +- .../com/android/launcher3/tapl/AllApps.java | 2 +- .../com/android/launcher3/tapl/Widgets.java | 2 +- 5 files changed, 20 insertions(+), 10 deletions(-) diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java index 0fd74bb26e..0c997dd598 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java @@ -331,21 +331,29 @@ public class TouchInteractionService extends Service implements defaultDisplay.getRealSize(realSize); mSwipeTouchRegion.set(0, 0, realSize.x, realSize.y); if (mMode == Mode.NO_BUTTON) { - mSwipeTouchRegion.top = mSwipeTouchRegion.bottom - getNavbarSize( - ResourceUtils.NAVBAR_VERTICAL_SIZE); + switch (defaultDisplay.getRotation()) { + case Surface.ROTATION_90: + case Surface.ROTATION_270: + mSwipeTouchRegion.top = mSwipeTouchRegion.bottom - getNavbarSize( + ResourceUtils.NAVBAR_LANDSCAPE_BOTTOM_SIZE); + break; + default: + mSwipeTouchRegion.top = mSwipeTouchRegion.bottom - getNavbarSize( + ResourceUtils.NAVBAR_PORTRAIT_BOTTOM_SIZE); + } } else { switch (defaultDisplay.getRotation()) { case Surface.ROTATION_90: mSwipeTouchRegion.left = mSwipeTouchRegion.right - - getNavbarSize(ResourceUtils.NAVBAR_HORIZONTAL_SIZE); + - getNavbarSize(ResourceUtils.NAVBAR_LANDSCAPE_LEFT_RIGHT_SIZE); break; case Surface.ROTATION_270: mSwipeTouchRegion.right = mSwipeTouchRegion.left - + getNavbarSize(ResourceUtils.NAVBAR_HORIZONTAL_SIZE); + + getNavbarSize(ResourceUtils.NAVBAR_LANDSCAPE_LEFT_RIGHT_SIZE); break; default: mSwipeTouchRegion.top = mSwipeTouchRegion.bottom - - getNavbarSize(ResourceUtils.NAVBAR_VERTICAL_SIZE); + - getNavbarSize(ResourceUtils.NAVBAR_PORTRAIT_BOTTOM_SIZE); } } } diff --git a/src/com/android/launcher3/ResourceUtils.java b/src/com/android/launcher3/ResourceUtils.java index 8df3290fd0..0c80d130ea 100644 --- a/src/com/android/launcher3/ResourceUtils.java +++ b/src/com/android/launcher3/ResourceUtils.java @@ -21,8 +21,10 @@ import android.util.DisplayMetrics; import android.util.TypedValue; public class ResourceUtils { - public static final String NAVBAR_VERTICAL_SIZE = "navigation_bar_frame_height"; - public static final String NAVBAR_HORIZONTAL_SIZE = "navigation_bar_width"; + public static final String NAVBAR_PORTRAIT_BOTTOM_SIZE = "navigation_bar_frame_height"; + public static final String NAVBAR_LANDSCAPE_LEFT_RIGHT_SIZE = "navigation_bar_width"; + public static final String NAVBAR_LANDSCAPE_BOTTOM_SIZE + = "navigation_bar_frame_height_landscape"; public static int getNavbarSize(String resName, Resources res) { return getDimenByName(resName, res, 48); diff --git a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java index ca6d968cc1..74cece836c 100644 --- a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java +++ b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java @@ -243,7 +243,7 @@ public abstract class AbstractLauncherUiTest { */ protected UiObject2 scrollAndFind(UiObject2 container, BySelector condition) { final int margin = ResourceUtils.getNavbarSize( - ResourceUtils.NAVBAR_VERTICAL_SIZE, mLauncher.getResources()) + 1; + ResourceUtils.NAVBAR_PORTRAIT_BOTTOM_SIZE, mLauncher.getResources()) + 1; container.setGestureMargins(0, 0, 0, margin); int i = 0; diff --git a/tests/tapl/com/android/launcher3/tapl/AllApps.java b/tests/tapl/com/android/launcher3/tapl/AllApps.java index a296975c3c..096a1d8cc3 100644 --- a/tests/tapl/com/android/launcher3/tapl/AllApps.java +++ b/tests/tapl/com/android/launcher3/tapl/AllApps.java @@ -69,7 +69,7 @@ public class AllApps extends LauncherInstrumentation.VisibleContainer { "want to get app icon on all apps")) { final UiObject2 allAppsContainer = verifyActiveContainer(); allAppsContainer.setGestureMargins(0, 0, 0, - ResourceUtils.getNavbarSize(ResourceUtils.NAVBAR_VERTICAL_SIZE, + ResourceUtils.getNavbarSize(ResourceUtils.NAVBAR_PORTRAIT_BOTTOM_SIZE, mLauncher.getResources()) + 1); final BySelector appIconSelector = AppIcon.getAppIconSelector(appName, mLauncher); if (!hasClickableIcon(allAppsContainer, appIconSelector)) { diff --git a/tests/tapl/com/android/launcher3/tapl/Widgets.java b/tests/tapl/com/android/launcher3/tapl/Widgets.java index f7e0b6c4e8..b780df4adb 100644 --- a/tests/tapl/com/android/launcher3/tapl/Widgets.java +++ b/tests/tapl/com/android/launcher3/tapl/Widgets.java @@ -41,7 +41,7 @@ public final class Widgets extends LauncherInstrumentation.VisibleContainer { LauncherInstrumentation.log("Widgets.flingForward enter"); final UiObject2 widgetsContainer = verifyActiveContainer(); widgetsContainer.setGestureMargins(0, 0, 0, - ResourceUtils.getNavbarSize(ResourceUtils.NAVBAR_VERTICAL_SIZE, + ResourceUtils.getNavbarSize(ResourceUtils.NAVBAR_PORTRAIT_BOTTOM_SIZE, mLauncher.getResources()) + 1); widgetsContainer.fling(Direction.DOWN, (int) (FLING_SPEED * mLauncher.getDisplayDensity())); From 418b9bc5fc1ce93711663754a15d157d2094331a Mon Sep 17 00:00:00 2001 From: Zak Cohen Date: Fri, 17 May 2019 15:51:44 -0700 Subject: [PATCH 03/21] Adapt the task footer container to be a named container. Bug: 126744445 Test: manual Change-Id: Id00ffac4581bbbe5dfd73a63b05c4512394745c1 --- quickstep/res/layout/task.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/quickstep/res/layout/task.xml b/quickstep/res/layout/task.xml index ecf1b0a19b..ba4ea8bc6d 100644 --- a/quickstep/res/layout/task.xml +++ b/quickstep/res/layout/task.xml @@ -36,6 +36,7 @@ android:importantForAccessibility="no" /> From ae975a613d93811daf47cec8e29d39e932d9332d Mon Sep 17 00:00:00 2001 From: Jon Miranda Date: Mon, 20 May 2019 11:10:25 -0700 Subject: [PATCH 04/21] Swipe up to home into FolderIcon animation bug fixes. - Fixes clipping issues. - Fixes badge being shifted. Bug: 124510042 Change-Id: I2520d963fb2041a049650c2b8c12ddb3de7b8d87 --- .../android/launcher3/folder/FolderIcon.java | 4 ++ .../launcher3/views/FloatingIconView.java | 43 +++++++++++-------- 2 files changed, 28 insertions(+), 19 deletions(-) diff --git a/src/com/android/launcher3/folder/FolderIcon.java b/src/com/android/launcher3/folder/FolderIcon.java index 8d9c52065b..0a9bc722d1 100644 --- a/src/com/android/launcher3/folder/FolderIcon.java +++ b/src/com/android/launcher3/folder/FolderIcon.java @@ -203,6 +203,10 @@ public class FolderIcon extends FrameLayout implements FolderListener { mBackground.getBounds(outBounds); } + public float getBackgroundStrokeWidth() { + return mBackground.getStrokeWidth(); + } + public Folder getFolder() { return mFolder; } diff --git a/src/com/android/launcher3/views/FloatingIconView.java b/src/com/android/launcher3/views/FloatingIconView.java index e5c75c3fca..a9e8f1733c 100644 --- a/src/com/android/launcher3/views/FloatingIconView.java +++ b/src/com/android/launcher3/views/FloatingIconView.java @@ -259,8 +259,6 @@ public class FloatingIconView extends View implements mFgSpringX.animateToFinalPosition(diffX); mFgSpringY.animateToFinalPosition(diffY); } - - } invalidate(); invalidateOutline(); @@ -368,10 +366,13 @@ public class FloatingIconView extends View implements drawable = v.getBackground(); } } else { + boolean isFolderIcon = v instanceof FolderIcon; + int width = isFolderIcon ? v.getWidth() : lp.width; + int height = isFolderIcon ? v.getHeight() : lp.height; if (supportsAdaptiveIcons) { - drawable = Utilities.getFullDrawable(mLauncher, info, lp.width, lp.height, - false, sTmpObjArray); - if ((drawable instanceof AdaptiveIconDrawable)) { + drawable = Utilities.getFullDrawable(mLauncher, info, width, height, false, + sTmpObjArray); + if (drawable instanceof AdaptiveIconDrawable) { mBadge = getBadge(mLauncher, info, sTmpObjArray[0]); } else { // The drawable we get back is not an adaptive icon, so we need to use the @@ -383,8 +384,8 @@ public class FloatingIconView extends View implements // Similar to DragView, we simply use the BubbleTextView icon here. drawable = btvIcon; } else { - drawable = Utilities.getFullDrawable(mLauncher, info, lp.width, lp.height, - false, sTmpObjArray); + drawable = Utilities.getFullDrawable(mLauncher, info, width, height, false, + sTmpObjArray); } } } @@ -412,13 +413,6 @@ public class FloatingIconView extends View implements } mForeground = foreground; - if (mForeground instanceof ShiftedBitmapDrawable && v instanceof FolderIcon) { - ShiftedBitmapDrawable sbd = (ShiftedBitmapDrawable) mForeground; - ((FolderIcon) v).getPreviewBounds(sTmpRect); - sbd.setShiftX(sbd.getShiftX() - sTmpRect.left); - sbd.setShiftY(sbd.getShiftY() - sTmpRect.top); - } - final int originalHeight = lp.height; final int originalWidth = lp.width; @@ -434,13 +428,25 @@ public class FloatingIconView extends View implements if (mBadge != null) { mBadge.setBounds(mStartRevealRect); - if (!isOpening) { + if (!isOpening && !isFolderIcon) { DRAWABLE_ALPHA.set(mBadge, 0); } - } - if (!isFolderIcon) { + if (isFolderIcon) { + ((FolderIcon) v).getPreviewBounds(sTmpRect); + float bgStroke = ((FolderIcon) v).getBackgroundStrokeWidth(); + if (mForeground instanceof ShiftedBitmapDrawable) { + ShiftedBitmapDrawable sbd = (ShiftedBitmapDrawable) mForeground; + sbd.setShiftX(sbd.getShiftX() - sTmpRect.left - bgStroke); + sbd.setShiftY(sbd.getShiftY() - sTmpRect.top - bgStroke); + } + if (mBadge instanceof ShiftedBitmapDrawable) { + ShiftedBitmapDrawable sbd = (ShiftedBitmapDrawable) mBadge; + sbd.setShiftX(sbd.getShiftX() - sTmpRect.left - bgStroke); + sbd.setShiftY(sbd.getShiftY() - sTmpRect.top - bgStroke); + } + } else { Utilities.scaleRectAboutCenter(mStartRevealRect, IconShape.getNormalizationScale()); } @@ -665,7 +671,7 @@ public class FloatingIconView extends View implements } }); - if (mBadge != null) { + if (mBadge != null && !(mOriginalIcon instanceof FolderIcon)) { ObjectAnimator badgeFade = ObjectAnimator.ofInt(mBadge, DRAWABLE_ALPHA, 255); badgeFade.addUpdateListener(valueAnimator -> invalidate()); fade.play(badgeFade); @@ -691,7 +697,6 @@ public class FloatingIconView extends View implements @Override public void onAnimationEnd(Animator animation) { folderIcon.setBackgroundVisible(true); - folderIcon.animateBgShadowAndStroke(); if (folderIcon.hasDot()) { folderIcon.animateDotScale(0, 1f); } From c79bd214719f73c55da5e3ecc744f58dd97f5156 Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Fri, 17 May 2019 16:12:37 -0700 Subject: [PATCH 05/21] Fixing inset map in case of display cutouts Change-Id: Ia2969688d9ae4c89a2da45eb6361f4476e1877ec --- .../launcher3/uioverrides/RecentsUiFactory.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsUiFactory.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsUiFactory.java index ebae1cd968..336cdc93fe 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsUiFactory.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsUiFactory.java @@ -76,8 +76,13 @@ public abstract class RecentsUiFactory { @Override public void mapInsets(Context context, Rect insets, Rect out) { + // If there is a display cutout, the top insets in portrait would also include the + // cutout, which we will get as the left inset in landscape. Using the max of left and + // top allows us to cover both cases (with or without cutout). if (SysUINavigationMode.getMode(context) == NO_BUTTON) { - out.set(insets); + out.top = Math.max(insets.top, insets.left); + out.bottom = Math.max(insets.right, insets.bottom); + out.left = out.right = 0; } else { out.top = Math.max(insets.top, insets.left); out.bottom = insets.right; @@ -99,7 +104,9 @@ public abstract class RecentsUiFactory { @Override public void mapInsets(Context context, Rect insets, Rect out) { if (SysUINavigationMode.getMode(context) == NO_BUTTON) { - out.set(insets); + out.top = Math.max(insets.top, insets.right); + out.bottom = Math.max(insets.left, insets.bottom); + out.left = out.right = 0; } else { out.top = Math.max(insets.top, insets.right); out.bottom = insets.left; From b063775eb90928ae3b0555025ca6d9c8ba2edebb Mon Sep 17 00:00:00 2001 From: Miranda Kephart Date: Thu, 16 May 2019 16:56:12 -0400 Subject: [PATCH 06/21] Pass in fling velocity for gesture progress Calls SystemUIProxy.onGestureCompletion for a completed gesture (either drag or fling) and passes in the velocity (0 for drags). Bug: 132356358 Test: manual Change-Id: I080adc401e19a6141627d1806b425056f7eefcbd --- .../AssistantTouchConsumer.java | 59 ++++++++++++------- 1 file changed, 37 insertions(+), 22 deletions(-) diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/AssistantTouchConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/AssistantTouchConsumer.java index 20ea3a1694..c864307299 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/AssistantTouchConsumer.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/AssistantTouchConsumer.java @@ -218,31 +218,35 @@ public class AssistantTouchConsumer extends DelegateInputConsumer private void updateAssistantProgress() { if (!mLaunchedAssistant) { mLastProgress = Math.min(mDistance * 1f / mDistThreshold, 1) * mTimeFraction; - updateAssistant(SWIPE); + try { + if (mDistance >= mDistThreshold && mTimeFraction >= 1) { + mSysUiProxy.onAssistantGestureCompletion(0); + startAssistantInternal(SWIPE); + + Bundle args = new Bundle(); + args.putInt(INVOCATION_TYPE_KEY, INVOCATION_TYPE_GESTURE); + mSysUiProxy.startAssistant(args); + mLaunchedAssistant = true; + } else { + mSysUiProxy.onAssistantProgress(mLastProgress); + } + } catch (RemoteException e) { + Log.w(TAG, "Failed to send SysUI start/send assistant progress: " + mLastProgress, + e); + } } } - private void updateAssistant(int gestureType) { - try { - mSysUiProxy.onAssistantProgress(mLastProgress); - if (gestureType == FLING || (mDistance >= mDistThreshold && mTimeFraction >= 1)) { - UserEventDispatcher.newInstance(mContext) - .logActionOnContainer(gestureType, mDirection, NAVBAR); - Bundle args = new Bundle(); - args.putInt(INVOCATION_TYPE_KEY, INVOCATION_TYPE_GESTURE); + private void startAssistantInternal(int gestureType) { + UserEventDispatcher.newInstance(mContext) + .logActionOnContainer(gestureType, mDirection, NAVBAR); - BaseDraggingActivity launcherActivity = mActivityControlHelper.getCreatedActivity(); - if (launcherActivity != null) { - launcherActivity.getRootView().performHapticFeedback( - 13, // HapticFeedbackConstants.GESTURE_END - HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING); - } - - mSysUiProxy.startAssistant(args); - mLaunchedAssistant = true; - } - } catch (RemoteException e) { - Log.w(TAG, "Failed to send SysUI start/send assistant progress: " + mLastProgress, e); + BaseDraggingActivity launcherActivity = mActivityControlHelper + .getCreatedActivity(); + if (launcherActivity != null) { + launcherActivity.getRootView().performHapticFeedback( + 13, // HapticFeedbackConstants.GESTURE_END + HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING); } } @@ -268,7 +272,18 @@ public class AssistantTouchConsumer extends DelegateInputConsumer public void onDragEnd(float velocity, boolean fling) { if (fling && !mLaunchedAssistant) { mLastProgress = 1; - updateAssistant(FLING); + try { + mSysUiProxy.onAssistantGestureCompletion(velocity); + startAssistantInternal(FLING); + + Bundle args = new Bundle(); + args.putInt(INVOCATION_TYPE_KEY, INVOCATION_TYPE_GESTURE); + mSysUiProxy.startAssistant(args); + mLaunchedAssistant = true; + } catch (RemoteException e) { + Log.w(TAG, "Failed to send SysUI start/send assistant progress: " + mLastProgress, + e); + } } } } From 878aa335673aefaaf84f474733fb18fa063be62f Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Mon, 20 May 2019 12:40:42 -0700 Subject: [PATCH 07/21] Using squared hypot to optimize some comparisions Change-Id: Ia5b99c2e60eedf02dea26857819f0e13127db4e2 --- .../inputconsumers/AssistantTouchConsumer.java | 9 ++++++--- .../inputconsumers/DeviceLockedInputConsumer.java | 11 +++++------ .../inputconsumers/OtherActivityInputConsumer.java | 8 +++++--- .../src/com/android/quickstep/views/RecentsView.java | 9 ++++++--- src/com/android/launcher3/Utilities.java | 10 ++++++++++ .../launcher3/popup/PopupContainerWithArrow.java | 8 +++++--- 6 files changed, 37 insertions(+), 18 deletions(-) diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/AssistantTouchConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/AssistantTouchConsumer.java index 20ea3a1694..248df34e79 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/AssistantTouchConsumer.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/AssistantTouchConsumer.java @@ -23,6 +23,7 @@ import static android.view.MotionEvent.ACTION_POINTER_DOWN; import static android.view.MotionEvent.ACTION_POINTER_UP; import static android.view.MotionEvent.ACTION_UP; +import static com.android.launcher3.Utilities.squaredHypot; import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction.UPLEFT; import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction.UPRIGHT; import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch.FLING; @@ -81,7 +82,7 @@ public class AssistantTouchConsumer extends DelegateInputConsumer private final float mDistThreshold; private final long mTimeThreshold; private final int mAngleThreshold; - private final float mSlop; + private final float mSquaredSlop; private final ISystemUiProxy mSysUiProxy; private final Context mContext; private final SwipeDetector mSwipeDetector; @@ -96,7 +97,8 @@ public class AssistantTouchConsumer extends DelegateInputConsumer mDistThreshold = res.getDimension(R.dimen.gestures_assistant_drag_threshold); mTimeThreshold = res.getInteger(R.integer.assistant_gesture_min_time_threshold); mAngleThreshold = res.getInteger(R.integer.assistant_gesture_corner_deg_threshold); - mSlop = QuickStepContract.getQuickStepDragSlopPx(); + float slop = QuickStepContract.getQuickStepDragSlopPx(); + mSquaredSlop = slop * slop; mActivityControlHelper = activityControlHelper; mSwipeDetector = new SwipeDetector(mContext, this, SwipeDetector.VERTICAL); mSwipeDetector.setDetectableScrollConditions(SwipeDetector.DIRECTION_POSITIVE, false); @@ -155,7 +157,8 @@ public class AssistantTouchConsumer extends DelegateInputConsumer if (!mPassedSlop) { // Normal gesture, ensure we pass the slop before we start tracking the gesture - if (Math.hypot(mLastPos.x - mDownPos.x, mLastPos.y - mDownPos.y) > mSlop) { + if (squaredHypot(mLastPos.x - mDownPos.x, mLastPos.y - mDownPos.y) + > mSquaredSlop) { mPassedSlop = true; mStartDragPos.set(mLastPos.x, mLastPos.y); diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java index b1d175df85..d01b5ec19d 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java @@ -15,11 +15,13 @@ */ package com.android.quickstep.inputconsumers; +import static com.android.launcher3.Utilities.squaredHypot; +import static com.android.launcher3.Utilities.squaredTouchSlop; + import android.content.Context; import android.content.Intent; import android.graphics.PointF; import android.view.MotionEvent; -import android.view.ViewConfiguration; /** * A dummy input consumer used when the device is still locked, e.g. from secure camera. @@ -32,8 +34,7 @@ public class DeviceLockedInputConsumer implements InputConsumer { public DeviceLockedInputConsumer(Context context) { mContext = context; - float touchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); - mTouchSlopSquared = touchSlop * touchSlop; + mTouchSlopSquared = squaredTouchSlop(context); } @Override @@ -48,9 +49,7 @@ public class DeviceLockedInputConsumer implements InputConsumer { if (ev.getAction() == MotionEvent.ACTION_DOWN) { mTouchDown.set(x, y); } else if (ev.getAction() == MotionEvent.ACTION_MOVE) { - float xSquared = (x - mTouchDown.x) * (x - mTouchDown.x); - float ySquared = (y - mTouchDown.y) * (y - mTouchDown.y); - if (xSquared + ySquared > mTouchSlopSquared) { + if (squaredHypot(x - mTouchDown.x, y - mTouchDown.y) > mTouchSlopSquared) { // For now, just start the home intent so user is prompted to unlock the device. mContext.startActivity(new Intent(Intent.ACTION_MAIN) .addCategory(Intent.CATEGORY_HOME) diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java index eb5366ca0f..b0acffa398 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java @@ -23,6 +23,7 @@ import static android.view.MotionEvent.ACTION_POINTER_UP; import static android.view.MotionEvent.ACTION_UP; import static android.view.MotionEvent.INVALID_POINTER_ID; import static com.android.launcher3.Utilities.EDGE_NAV_BAR; +import static com.android.launcher3.Utilities.squaredHypot; import static com.android.launcher3.uioverrides.RecentsUiFactory.ROTATION_LANDSCAPE; import static com.android.launcher3.uioverrides.RecentsUiFactory.ROTATION_SEASCAPE; import static com.android.launcher3.util.RaceConditionTracker.ENTER; @@ -109,7 +110,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC private int mActivePointerId = INVALID_POINTER_ID; private final float mDragSlop; - private final float mTouchSlop; + private final float mSquaredTouchSlop; // Slop used to check when we start moving window. private boolean mPassedDragSlop; @@ -157,7 +158,8 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC mDisplayRotation = getSystemService(WindowManager.class).getDefaultDisplay().getRotation(); mDragSlop = QuickStepContract.getQuickStepDragSlopPx(); - mTouchSlop = QuickStepContract.getQuickStepTouchSlopPx(); + float slop = QuickStepContract.getQuickStepTouchSlopPx(); + mSquaredTouchSlop = slop * slop; mPassedTouchSlop = mPassedDragSlop = continuingPreviousGesture; } @@ -256,7 +258,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC } if (!mPassedTouchSlop) { - if (Math.hypot(displacementX, mLastPos.y - mDownPos.y) >= mTouchSlop) { + if (squaredHypot(displacementX, mLastPos.y - mDownPos.y) >= mSquaredTouchSlop) { mPassedTouchSlop = true; if (mIsDeferredDownTarget) { diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java index a835680c2b..661468ac62 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java @@ -20,6 +20,8 @@ import static com.android.launcher3.BaseActivity.STATE_HANDLER_INVISIBILITY_FLAG import static com.android.launcher3.InvariantDeviceProfile.CHANGE_FLAG_ICON_PARAMS; import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY; import static com.android.launcher3.Utilities.EDGE_NAV_BAR; +import static com.android.launcher3.Utilities.squaredHypot; +import static com.android.launcher3.Utilities.squaredTouchSlop; import static com.android.launcher3.anim.Interpolators.ACCEL; import static com.android.launcher3.anim.Interpolators.ACCEL_2; import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN; @@ -281,7 +283,7 @@ public abstract class RecentsView extends PagedView impl private boolean mHandleTaskStackChanges; private boolean mSwipeDownShouldLaunchApp; private boolean mTouchDownToStartHome; - private final int mTouchSlop; + private final float mSquaredTouchSlop; private int mDownX; private int mDownY; @@ -339,7 +341,7 @@ public abstract class RecentsView extends PagedView impl setLayoutDirection(mIsRtl ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR); mTaskTopMargin = getResources() .getDimensionPixelSize(R.dimen.task_thumbnail_top_margin); - mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); + mSquaredTouchSlop = squaredTouchSlop(context); mEmptyIcon = context.getDrawable(R.drawable.ic_empty_recents); mEmptyIcon.setCallback(this); @@ -496,7 +498,8 @@ public abstract class RecentsView extends PagedView impl case MotionEvent.ACTION_MOVE: // Passing the touch slop will not allow dismiss to home if (mTouchDownToStartHome && - (isHandlingTouch() || Math.hypot(mDownX - x, mDownY - y) > mTouchSlop)) { + (isHandlingTouch() || + squaredHypot(mDownX - x, mDownY - y) > mSquaredTouchSlop)) { mTouchDownToStartHome = false; } break; diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java index 796fd25057..cc9bda7106 100644 --- a/src/com/android/launcher3/Utilities.java +++ b/src/com/android/launcher3/Utilities.java @@ -61,6 +61,7 @@ import android.util.Pair; import android.util.TypedValue; import android.view.MotionEvent; import android.view.View; +import android.view.ViewConfiguration; import android.view.animation.Interpolator; import com.android.launcher3.compat.LauncherAppsCompat; @@ -726,6 +727,15 @@ public final class Utilities { return str.toString(); } + public static float squaredHypot(float x, float y) { + return x * x + y * y; + } + + public static float squaredTouchSlop(Context context) { + float slop = ViewConfiguration.get(context).getScaledTouchSlop(); + return slop * slop; + } + private static class FixedSizeEmptyDrawable extends ColorDrawable { private final int mSize; diff --git a/src/com/android/launcher3/popup/PopupContainerWithArrow.java b/src/com/android/launcher3/popup/PopupContainerWithArrow.java index 047f4862b6..7b14fa2491 100644 --- a/src/com/android/launcher3/popup/PopupContainerWithArrow.java +++ b/src/com/android/launcher3/popup/PopupContainerWithArrow.java @@ -16,6 +16,8 @@ package com.android.launcher3.popup; +import static com.android.launcher3.Utilities.squaredHypot; +import static com.android.launcher3.Utilities.squaredTouchSlop; import static com.android.launcher3.notification.NotificationMainView.NOTIFICATION_ITEM_INFO; import static com.android.launcher3.popup.PopupPopulator.MAX_SHORTCUTS; import static com.android.launcher3.popup.PopupPopulator.MAX_SHORTCUTS_IF_NOTIFICATIONS; @@ -37,7 +39,6 @@ import android.util.AttributeSet; import android.util.Pair; import android.view.MotionEvent; import android.view.View; -import android.view.ViewConfiguration; import android.view.ViewGroup; import android.widget.ImageView; @@ -51,6 +52,7 @@ import com.android.launcher3.ItemInfoWithIcon; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherModel; import com.android.launcher3.R; +import com.android.launcher3.Utilities; import com.android.launcher3.accessibility.LauncherAccessibilityDelegate; import com.android.launcher3.accessibility.ShortcutMenuAccessibilityDelegate; import com.android.launcher3.dot.DotInfo; @@ -136,8 +138,8 @@ public class PopupContainerWithArrow extends ArrowPopup implements DragSource, return true; } // Stop sending touch events to deep shortcut views if user moved beyond touch slop. - return Math.hypot(mInterceptTouchDown.x - ev.getX(), mInterceptTouchDown.y - ev.getY()) - > ViewConfiguration.get(getContext()).getScaledTouchSlop(); + return squaredHypot(mInterceptTouchDown.x - ev.getX(), mInterceptTouchDown.y - ev.getY()) + > squaredTouchSlop(getContext()); } @Override From 982ea561225d9859f1dd7518fe434fec81e1c0dd Mon Sep 17 00:00:00 2001 From: vadimt Date: Fri, 17 May 2019 19:42:45 -0700 Subject: [PATCH 08/21] Making sure that the icon in all apps is not under search box Bug: 133011252 Bug: 133010447 Change-Id: Ie735ac36fa063d0d9290c59f6ad4af9e05600ddf --- .../com/android/launcher3/tapl/AllApps.java | 24 +++++++++++++++---- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/tests/tapl/com/android/launcher3/tapl/AllApps.java b/tests/tapl/com/android/launcher3/tapl/AllApps.java index 096a1d8cc3..a4d0e75320 100644 --- a/tests/tapl/com/android/launcher3/tapl/AllApps.java +++ b/tests/tapl/com/android/launcher3/tapl/AllApps.java @@ -53,7 +53,14 @@ public class AllApps extends LauncherInstrumentation.VisibleContainer { if (icon == null) return false; if (mLauncher.getNavigationModel() == ZERO_BUTTON) return true; final UiObject2 navBar = mLauncher.waitForSystemUiObject("navigation_bar_frame"); - return icon.getVisibleBounds().bottom < navBar.getVisibleBounds().top; + if (icon.getVisibleBounds().bottom >= navBar.getVisibleBounds().top) return false; + if (iconIntersectsWithSearchBox(allAppsContainer, icon)) return false; + return true; + } + + private boolean iconIntersectsWithSearchBox(UiObject2 allAppsContainer, UiObject2 icon) { + return Rect.intersects(icon.getVisibleBounds(), + getSearchBox(allAppsContainer).getVisibleBounds()); } /** @@ -68,7 +75,10 @@ public class AllApps extends LauncherInstrumentation.VisibleContainer { try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer( "want to get app icon on all apps")) { final UiObject2 allAppsContainer = verifyActiveContainer(); - allAppsContainer.setGestureMargins(0, 0, 0, + allAppsContainer.setGestureMargins( + 0, + getSearchBox(allAppsContainer).getVisibleBounds().bottom + 1, + 0, ResourceUtils.getNavbarSize(ResourceUtils.NAVBAR_PORTRAIT_BOTTOM_SIZE, mLauncher.getResources()) + 1); final BySelector appIconSelector = AppIcon.getAppIconSelector(appName, mLauncher); @@ -98,9 +108,7 @@ public class AllApps extends LauncherInstrumentation.VisibleContainer { try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer( "want to scroll back in all apps")) { final UiObject2 allAppsContainer = verifyActiveContainer(); - final UiObject2 searchBox = - mLauncher.waitForObjectInContainer(allAppsContainer, - "search_container_all_apps"); + final UiObject2 searchBox = getSearchBox(allAppsContainer); int attempts = 0; final Rect margins = new Rect(0, searchBox.getVisibleBounds().bottom + 1, 0, 5); @@ -141,6 +149,12 @@ public class AllApps extends LauncherInstrumentation.VisibleContainer { verifyActiveContainer(); } } + mLauncher.assertTrue("Couldn't scroll app icon to not intersect with the search box", + !iconIntersectsWithSearchBox(allAppsContainer, appIcon)); + } + + private UiObject2 getSearchBox(UiObject2 allAppsContainer) { + return mLauncher.waitForObjectInContainer(allAppsContainer, "search_container_all_apps"); } /** From 1053de165e9d04d547f7ed19335c58bc4c368b35 Mon Sep 17 00:00:00 2001 From: vadimt Date: Tue, 21 May 2019 11:10:03 -0700 Subject: [PATCH 09/21] Marking sure the center of icon is not under search box in all apps Change-Id: I9cfc9941be2bed7834d58039fbfc2741fcf50cba --- tests/tapl/com/android/launcher3/tapl/AllApps.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/tests/tapl/com/android/launcher3/tapl/AllApps.java b/tests/tapl/com/android/launcher3/tapl/AllApps.java index a4d0e75320..988e67486e 100644 --- a/tests/tapl/com/android/launcher3/tapl/AllApps.java +++ b/tests/tapl/com/android/launcher3/tapl/AllApps.java @@ -18,6 +18,7 @@ package com.android.launcher3.tapl; import static com.android.launcher3.tapl.LauncherInstrumentation.NavigationModel.ZERO_BUTTON; +import android.graphics.Point; import android.graphics.Rect; import androidx.annotation.NonNull; @@ -54,13 +55,14 @@ public class AllApps extends LauncherInstrumentation.VisibleContainer { if (mLauncher.getNavigationModel() == ZERO_BUTTON) return true; final UiObject2 navBar = mLauncher.waitForSystemUiObject("navigation_bar_frame"); if (icon.getVisibleBounds().bottom >= navBar.getVisibleBounds().top) return false; - if (iconIntersectsWithSearchBox(allAppsContainer, icon)) return false; + if (iconCenterInSearchBox(allAppsContainer, icon)) return false; return true; } - private boolean iconIntersectsWithSearchBox(UiObject2 allAppsContainer, UiObject2 icon) { - return Rect.intersects(icon.getVisibleBounds(), - getSearchBox(allAppsContainer).getVisibleBounds()); + private boolean iconCenterInSearchBox(UiObject2 allAppsContainer, UiObject2 icon) { + final Point iconCenter = icon.getVisibleCenter(); + return getSearchBox(allAppsContainer).getVisibleBounds().contains( + iconCenter.x, iconCenter.y); } /** @@ -150,7 +152,7 @@ public class AllApps extends LauncherInstrumentation.VisibleContainer { } } mLauncher.assertTrue("Couldn't scroll app icon to not intersect with the search box", - !iconIntersectsWithSearchBox(allAppsContainer, appIcon)); + !iconCenterInSearchBox(allAppsContainer, appIcon)); } private UiObject2 getSearchBox(UiObject2 allAppsContainer) { From a1a417c99445e7590983b267eff41113a1775808 Mon Sep 17 00:00:00 2001 From: vadimt Date: Tue, 21 May 2019 11:47:27 -0700 Subject: [PATCH 10/21] Searching icons only in apps_list_view This should help avoiding situations when an icon is intermittently found in the suggested row vs. the recycler. Change-Id: I71b17caa5f827999f0901d5c4d4348de7e16f053 --- .../com/android/launcher3/tapl/AllApps.java | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/tests/tapl/com/android/launcher3/tapl/AllApps.java b/tests/tapl/com/android/launcher3/tapl/AllApps.java index 988e67486e..792ec43134 100644 --- a/tests/tapl/com/android/launcher3/tapl/AllApps.java +++ b/tests/tapl/com/android/launcher3/tapl/AllApps.java @@ -49,8 +49,9 @@ public class AllApps extends LauncherInstrumentation.VisibleContainer { return LauncherInstrumentation.ContainerType.ALL_APPS; } - private boolean hasClickableIcon(UiObject2 allAppsContainer, BySelector appIconSelector) { - final UiObject2 icon = allAppsContainer.findObject(appIconSelector); + private boolean hasClickableIcon( + UiObject2 allAppsContainer, UiObject2 appListRecycler, BySelector appIconSelector) { + final UiObject2 icon = appListRecycler.findObject(appIconSelector); if (icon == null) return false; if (mLauncher.getNavigationModel() == ZERO_BUTTON) return true; final UiObject2 navBar = mLauncher.waitForSystemUiObject("navigation_bar_frame"); @@ -77,6 +78,8 @@ public class AllApps extends LauncherInstrumentation.VisibleContainer { try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer( "want to get app icon on all apps")) { final UiObject2 allAppsContainer = verifyActiveContainer(); + final UiObject2 appListRecycler = mLauncher.waitForObjectInContainer(allAppsContainer, + "apps_list_view"); allAppsContainer.setGestureMargins( 0, getSearchBox(allAppsContainer).getVisibleBounds().bottom + 1, @@ -84,11 +87,11 @@ public class AllApps extends LauncherInstrumentation.VisibleContainer { ResourceUtils.getNavbarSize(ResourceUtils.NAVBAR_PORTRAIT_BOTTOM_SIZE, mLauncher.getResources()) + 1); final BySelector appIconSelector = AppIcon.getAppIconSelector(appName, mLauncher); - if (!hasClickableIcon(allAppsContainer, appIconSelector)) { + if (!hasClickableIcon(allAppsContainer, appListRecycler, appIconSelector)) { scrollBackToBeginning(); int attempts = 0; try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer("scrolled")) { - while (!hasClickableIcon(allAppsContainer, appIconSelector) && + while (!hasClickableIcon(allAppsContainer, appListRecycler, appIconSelector) && allAppsContainer.scroll(Direction.DOWN, 0.8f)) { mLauncher.assertTrue( "Exceeded max scroll attempts: " + MAX_SCROLL_ATTEMPTS, @@ -101,7 +104,7 @@ public class AllApps extends LauncherInstrumentation.VisibleContainer { final UiObject2 appIcon = mLauncher.getObjectInContainer(allAppsContainer, appIconSelector); - ensureIconVisible(appIcon, allAppsContainer); + ensureIconVisible(appIcon, allAppsContainer, appListRecycler); return new AppIcon(mLauncher, appIcon); } } @@ -138,13 +141,14 @@ public class AllApps extends LauncherInstrumentation.VisibleContainer { getInt(TestProtocol.SCROLL_Y_FIELD, -1); } - private void ensureIconVisible(UiObject2 appIcon, UiObject2 allAppsContainer) { + private void ensureIconVisible( + UiObject2 appIcon, UiObject2 allAppsContainer, UiObject2 appListRecycler) { final int appHeight = appIcon.getVisibleBounds().height(); if (appHeight < MIN_INTERACT_SIZE) { // Try to figure out how much percentage of the container needs to be scrolled in order // to reveal the app icon to have the MIN_INTERACT_SIZE final float pct = Math.max(((float) (MIN_INTERACT_SIZE - appHeight)) / mHeight, 0.2f); - mLauncher.scroll(allAppsContainer, Direction.DOWN, pct, null, 10); + mLauncher.scroll(appListRecycler, Direction.DOWN, pct, null, 10); try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer( "scrolled an icon in all apps to make it visible - and then")) { mLauncher.waitForIdle(); From 3479cf80e7c5edc06eab3b57662084a4e4f15d8e Mon Sep 17 00:00:00 2001 From: vadimt Date: Tue, 21 May 2019 12:08:15 -0700 Subject: [PATCH 11/21] More logging in AllApps + a fix Change-Id: Iebcb336beee36b0aea47404f8c5d31dec14e7383 --- .../com/android/launcher3/tapl/AllApps.java | 26 ++++++++++++++----- 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/tests/tapl/com/android/launcher3/tapl/AllApps.java b/tests/tapl/com/android/launcher3/tapl/AllApps.java index 792ec43134..70405fed8a 100644 --- a/tests/tapl/com/android/launcher3/tapl/AllApps.java +++ b/tests/tapl/com/android/launcher3/tapl/AllApps.java @@ -52,11 +52,24 @@ public class AllApps extends LauncherInstrumentation.VisibleContainer { private boolean hasClickableIcon( UiObject2 allAppsContainer, UiObject2 appListRecycler, BySelector appIconSelector) { final UiObject2 icon = appListRecycler.findObject(appIconSelector); - if (icon == null) return false; - if (mLauncher.getNavigationModel() == ZERO_BUTTON) return true; - final UiObject2 navBar = mLauncher.waitForSystemUiObject("navigation_bar_frame"); - if (icon.getVisibleBounds().bottom >= navBar.getVisibleBounds().top) return false; - if (iconCenterInSearchBox(allAppsContainer, icon)) return false; + if (icon == null) { + LauncherInstrumentation.log("hasClickableIcon: icon not visible"); + return false; + } + final Rect iconBounds = icon.getVisibleBounds(); + LauncherInstrumentation.log("hasClickableIcon: icon bounds: " + iconBounds); + if (mLauncher.getNavigationModel() != ZERO_BUTTON) { + final UiObject2 navBar = mLauncher.waitForSystemUiObject("navigation_bar_frame"); + if (iconBounds.bottom >= navBar.getVisibleBounds().top) { + LauncherInstrumentation.log("hasClickableIcon: icon intersects with nav bar"); + return false; + } + } + if (iconCenterInSearchBox(allAppsContainer, icon)) { + LauncherInstrumentation.log("hasClickableIcon: icon center is under search box"); + return false; + } + LauncherInstrumentation.log("hasClickableIcon: icon is clickable"); return true; } @@ -76,7 +89,7 @@ public class AllApps extends LauncherInstrumentation.VisibleContainer { @NonNull public AppIcon getAppIcon(String appName) { try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer( - "want to get app icon on all apps")) { + "want to get app icon " + appName + " on all apps")) { final UiObject2 allAppsContainer = verifyActiveContainer(); final UiObject2 appListRecycler = mLauncher.waitForObjectInContainer(allAppsContainer, "apps_list_view"); @@ -112,6 +125,7 @@ public class AllApps extends LauncherInstrumentation.VisibleContainer { private void scrollBackToBeginning() { try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer( "want to scroll back in all apps")) { + LauncherInstrumentation.log("Scrolling to the beginning"); final UiObject2 allAppsContainer = verifyActiveContainer(); final UiObject2 searchBox = getSearchBox(allAppsContainer); From da6dad51014d867faf83191d83f1f4fc4207fdab Mon Sep 17 00:00:00 2001 From: vadimt Date: Tue, 21 May 2019 13:24:23 -0700 Subject: [PATCH 12/21] Not allowing applying dot state to override "disabled" description Disabled apps were always accessibility-marked like "Disabled Messenger" With introduction of dots, this degraded, the the "Disabled" part was never added. Restoring the old behavior here. Bug: 129036789 Change-Id: Icb97ea9a190643449d90f558a78039df30c53cbf --- src/com/android/launcher3/BubbleTextView.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java index bff7f42131..2f801e04b9 100644 --- a/src/com/android/launcher3/BubbleTextView.java +++ b/src/com/android/launcher3/BubbleTextView.java @@ -51,7 +51,6 @@ import com.android.launcher3.graphics.PreloadIconDrawable; import com.android.launcher3.icons.DotRenderer; import com.android.launcher3.icons.IconCache.IconLoadRequest; import com.android.launcher3.icons.IconCache.ItemInfoUpdateReceiver; -import com.android.launcher3.icons.LauncherIcons; import com.android.launcher3.model.PackageItemInfo; import com.android.launcher3.views.ActivityContext; @@ -561,7 +560,10 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver, } } if (itemInfo.contentDescription != null) { - if (hasDot()) { + if (itemInfo.isDisabled()) { + setContentDescription(getContext().getString(R.string.disabled_app_label, + itemInfo.contentDescription)); + } else if (hasDot()) { int count = mDotInfo.getNotificationCount(); setContentDescription(getContext().getResources().getQuantityString( R.plurals.dotted_app_label, count, itemInfo.contentDescription, count)); From 8f7d2b0dfd4aa0ab060b6e0be893eee136e5f2a4 Mon Sep 17 00:00:00 2001 From: Adam Cohen Date: Tue, 21 May 2019 15:45:43 -0700 Subject: [PATCH 13/21] Fix issue where Assistant could be invoked at the same time as all apps issue 132366412 -> First, we shouldn't accept flings when the delegate has intercepted. This prevents any situation where both are triggered. -> Modified the slop to be the standard 8dp. This acts as a standalone fix because it means that there are no situations where we cross all apps slop before assistant slop. ie. in a purely vertical gesture from the corner, without this change, it's possible to trigger all apps instead of Assistant. Change-Id: I39e3d8a525e165024399d9802d4cc1d7ae329ee6 --- .../quickstep/inputconsumers/AssistantTouchConsumer.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/AssistantTouchConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/AssistantTouchConsumer.java index 2ff5e23865..bf276e1e16 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/AssistantTouchConsumer.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/AssistantTouchConsumer.java @@ -41,6 +41,7 @@ import android.os.SystemClock; import android.util.Log; import android.view.HapticFeedbackConstants; import android.view.MotionEvent; +import android.view.ViewConfiguration; import com.android.launcher3.BaseDraggingActivity; import com.android.launcher3.R; @@ -97,7 +98,9 @@ public class AssistantTouchConsumer extends DelegateInputConsumer mDistThreshold = res.getDimension(R.dimen.gestures_assistant_drag_threshold); mTimeThreshold = res.getInteger(R.integer.assistant_gesture_min_time_threshold); mAngleThreshold = res.getInteger(R.integer.assistant_gesture_corner_deg_threshold); - float slop = QuickStepContract.getQuickStepDragSlopPx(); + + float slop = ViewConfiguration.get(context).getScaledTouchSlop(); + mSquaredSlop = slop * slop; mActivityControlHelper = activityControlHelper; mSwipeDetector = new SwipeDetector(mContext, this, SwipeDetector.VERTICAL); @@ -273,7 +276,7 @@ public class AssistantTouchConsumer extends DelegateInputConsumer @Override public void onDragEnd(float velocity, boolean fling) { - if (fling && !mLaunchedAssistant) { + if (fling && !mLaunchedAssistant && mState != STATE_DELEGATE_ACTIVE) { mLastProgress = 1; try { mSysUiProxy.onAssistantGestureCompletion(velocity); From e17d1feb791a383c5c12f1da02055b07eb832f02 Mon Sep 17 00:00:00 2001 From: vadimt Date: Tue, 21 May 2019 17:19:23 -0700 Subject: [PATCH 14/21] Adding tracing for a lab-only flake We had a resolved case in the past where an app's context menu didn't open on a long click (thanks to app updates), now the menu opens, but the drag gesture doesn't drag the icon. Bug: 133009122 Change-Id: I45d104a92fab6556ecd937aef76f0a8147e67f56 --- .../android/quickstep/TestInformationProvider.java | 8 ++++++++ src/com/android/launcher3/LauncherStateManager.java | 8 ++++++++ src/com/android/launcher3/TestProtocol.java | 4 ++++ src/com/android/launcher3/Workspace.java | 8 ++++++++ .../android/launcher3/dragndrop/DragController.java | 12 ++++++++++++ src/com/android/launcher3/views/BaseDragLayer.java | 8 ++++++++ tests/tapl/com/android/launcher3/tapl/Workspace.java | 2 ++ 7 files changed, 50 insertions(+) diff --git a/quickstep/src/com/android/quickstep/TestInformationProvider.java b/quickstep/src/com/android/quickstep/TestInformationProvider.java index b37ddda097..a948570d2a 100644 --- a/quickstep/src/com/android/quickstep/TestInformationProvider.java +++ b/quickstep/src/com/android/quickstep/TestInformationProvider.java @@ -111,6 +111,14 @@ public class TestInformationProvider extends ContentProvider { response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, (int) distance); break; } + + case TestProtocol.REQUEST_ENABLE_DRAG_LOGGING: + TestProtocol.sDebugTracing = true; + break; + + case TestProtocol.REQUEST_DISABLE_DRAG_LOGGING: + TestProtocol.sDebugTracing = false; + break; } return response; } diff --git a/src/com/android/launcher3/LauncherStateManager.java b/src/com/android/launcher3/LauncherStateManager.java index b1a3fc992e..49ae33894a 100644 --- a/src/com/android/launcher3/LauncherStateManager.java +++ b/src/com/android/launcher3/LauncherStateManager.java @@ -447,6 +447,10 @@ public class LauncherStateManager { } private void onStateTransitionStart(LauncherState state) { + if (com.android.launcher3.TestProtocol.sDebugTracing) { + android.util.Log.d(com.android.launcher3.TestProtocol.NO_DRAG_TAG, + "onStateTransitionStart"); + } if (mState != state) { mState.onStateDisabled(mLauncher); } @@ -572,6 +576,10 @@ public class LauncherStateManager { private final AnimatorSet mAnim; public StartAnimRunnable(AnimatorSet anim) { + if (com.android.launcher3.TestProtocol.sDebugTracing) { + android.util.Log.d(com.android.launcher3.TestProtocol.NO_DRAG_TAG, + "StartAnimRunnable"); + } mAnim = anim; } diff --git a/src/com/android/launcher3/TestProtocol.java b/src/com/android/launcher3/TestProtocol.java index eefecda5d7..081150db04 100644 --- a/src/com/android/launcher3/TestProtocol.java +++ b/src/com/android/launcher3/TestProtocol.java @@ -64,4 +64,8 @@ public final class TestProtocol { "all-apps-to-overview-swipe-height"; public static final String REQUEST_HOME_TO_ALL_APPS_SWIPE_HEIGHT = "home-to-all-apps-swipe-height"; + public static boolean sDebugTracing = false; + public static final String REQUEST_ENABLE_DRAG_LOGGING = "enable-drag-logging"; + public static final String REQUEST_DISABLE_DRAG_LOGGING = "disable-drag-logging"; + public static final String NO_DRAG_TAG = "b/133009122"; } diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java index a508ce52bd..d19f9cd73f 100644 --- a/src/com/android/launcher3/Workspace.java +++ b/src/com/android/launcher3/Workspace.java @@ -371,6 +371,10 @@ public class Workspace extends PagedView @Override public void onDragStart(DropTarget.DragObject dragObject, DragOptions options) { + if (com.android.launcher3.TestProtocol.sDebugTracing) { + android.util.Log.d(com.android.launcher3.TestProtocol.NO_DRAG_TAG, + "onDragStart 1"); + } if (ENFORCE_DRAG_EVENT_ORDER) { enforceDragParity("onDragStart", 0, 0); } @@ -421,6 +425,10 @@ public class Workspace extends PagedView } // Always enter the spring loaded mode + if (com.android.launcher3.TestProtocol.sDebugTracing) { + android.util.Log.d(com.android.launcher3.TestProtocol.NO_DRAG_TAG, + "onDragStart 2"); + } mLauncher.getStateManager().goToState(SPRING_LOADED); } diff --git a/src/com/android/launcher3/dragndrop/DragController.java b/src/com/android/launcher3/dragndrop/DragController.java index f92e00acba..bf692fe472 100644 --- a/src/com/android/launcher3/dragndrop/DragController.java +++ b/src/com/android/launcher3/dragndrop/DragController.java @@ -472,6 +472,10 @@ public class DragController implements DragDriver.EventListener, TouchController } private void handleMoveEvent(int x, int y) { + if (com.android.launcher3.TestProtocol.sDebugTracing) { + android.util.Log.d(com.android.launcher3.TestProtocol.NO_DRAG_TAG, + "handleMoveEvent 1"); + } mDragObject.dragView.move(x, y); // Drop on someone? @@ -488,6 +492,10 @@ public class DragController implements DragDriver.EventListener, TouchController if (mIsInPreDrag && mOptions.preDragCondition != null && mOptions.preDragCondition.shouldStartDrag(mDistanceSinceScroll)) { + if (com.android.launcher3.TestProtocol.sDebugTracing) { + android.util.Log.d(com.android.launcher3.TestProtocol.NO_DRAG_TAG, + "handleMoveEvent 2"); + } callOnDragStart(); } } @@ -525,6 +533,10 @@ public class DragController implements DragDriver.EventListener, TouchController * Call this from a drag source view. */ public boolean onControllerTouchEvent(MotionEvent ev) { + if (com.android.launcher3.TestProtocol.sDebugTracing) { + android.util.Log.d(com.android.launcher3.TestProtocol.NO_DRAG_TAG, + "onControllerTouchEvent"); + } if (mDragDriver == null || mOptions == null || mOptions.isAccessibleDrag) { return false; } diff --git a/src/com/android/launcher3/views/BaseDragLayer.java b/src/com/android/launcher3/views/BaseDragLayer.java index 3c81bcf399..4964182409 100644 --- a/src/com/android/launcher3/views/BaseDragLayer.java +++ b/src/com/android/launcher3/views/BaseDragLayer.java @@ -213,6 +213,10 @@ public abstract class BaseDragLayer @Override public boolean onTouchEvent(MotionEvent ev) { + if (com.android.launcher3.TestProtocol.sDebugTracing) { + android.util.Log.d(com.android.launcher3.TestProtocol.NO_DRAG_TAG, + "onTouchEvent " + ev); + } int action = ev.getAction(); if (action == ACTION_UP || action == ACTION_CANCEL) { if (mTouchCompleteListener != null) { @@ -222,6 +226,10 @@ public abstract class BaseDragLayer } if (mActiveController != null) { + if (com.android.launcher3.TestProtocol.sDebugTracing) { + android.util.Log.d(com.android.launcher3.TestProtocol.NO_DRAG_TAG, + "onTouchEvent 1"); + } return mActiveController.onControllerTouchEvent(ev); } else { // In case no child view handled the touch event, we may not get onIntercept anymore diff --git a/tests/tapl/com/android/launcher3/tapl/Workspace.java b/tests/tapl/com/android/launcher3/tapl/Workspace.java index 11c07943fe..f1dd0136da 100644 --- a/tests/tapl/com/android/launcher3/tapl/Workspace.java +++ b/tests/tapl/com/android/launcher3/tapl/Workspace.java @@ -148,6 +148,7 @@ public final class Workspace extends Home { static void dragIconToWorkspace( LauncherInstrumentation launcher, Launchable launchable, Point dest, String longPressIndicator) { + launcher.getTestInfo(TestProtocol.REQUEST_ENABLE_DRAG_LOGGING); LauncherInstrumentation.log("dragIconToWorkspace: begin"); final Point launchableCenter = launchable.getObject().getVisibleCenter(); final long downTime = SystemClock.uptimeMillis(); @@ -162,6 +163,7 @@ public final class Workspace extends Home { downTime, SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, dest); LauncherInstrumentation.log("dragIconToWorkspace: end"); launcher.waitUntilGone("drop_target_bar"); + launcher.getTestInfo(TestProtocol.REQUEST_DISABLE_DRAG_LOGGING); } /** From cfc2e02a94d44d380d78c65b4803ff047f14066d Mon Sep 17 00:00:00 2001 From: vadimt Date: Tue, 21 May 2019 18:29:19 -0700 Subject: [PATCH 15/21] TAPL: switching all swipes to model time Bug: 133010773 Change-Id: I3334ac4ac434bf1c6470c806bb216eb7bd8e22c2 --- .../launcher3/tapl/AllAppsFromOverview.java | 4 +-- .../android/launcher3/tapl/Background.java | 3 +- .../tapl/LauncherInstrumentation.java | 31 +++++-------------- 3 files changed, 12 insertions(+), 26 deletions(-) diff --git a/tests/tapl/com/android/launcher3/tapl/AllAppsFromOverview.java b/tests/tapl/com/android/launcher3/tapl/AllAppsFromOverview.java index c3b671bcc2..a472d31344 100644 --- a/tests/tapl/com/android/launcher3/tapl/AllAppsFromOverview.java +++ b/tests/tapl/com/android/launcher3/tapl/AllAppsFromOverview.java @@ -53,9 +53,9 @@ public final class AllAppsFromOverview extends AllApps { TestProtocol.REQUEST_ALL_APPS_TO_OVERVIEW_SWIPE_HEIGHT). getInt(TestProtocol.TEST_INFO_RESPONSE_FIELD); - final int endY = start.y + swipeHeight + mLauncher.getTouchSlop(); + final int endY = start.y + swipeHeight; LauncherInstrumentation.log("AllAppsFromOverview.switchBackToOverview before swipe"); - mLauncher.swipe(start.x, start.y, start.x, endY, OVERVIEW_STATE_ORDINAL); + mLauncher.swipeToState(start.x, start.y, start.x, endY, 60, OVERVIEW_STATE_ORDINAL); try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer("swiped down")) { return new Overview(mLauncher); diff --git a/tests/tapl/com/android/launcher3/tapl/Background.java b/tests/tapl/com/android/launcher3/tapl/Background.java index 8f5e7fed0d..55e14cc80c 100644 --- a/tests/tapl/com/android/launcher3/tapl/Background.java +++ b/tests/tapl/com/android/launcher3/tapl/Background.java @@ -86,9 +86,10 @@ public class Background extends LauncherInstrumentation.VisibleContainer { final int swipeHeight = mLauncher.getTestInfo(getSwipeHeightRequestName()). getInt(TestProtocol.TEST_INFO_RESPONSE_FIELD); - mLauncher.swipe( + mLauncher.swipeToState( centerX, startY, centerX, startY - swipeHeight - mLauncher.getTouchSlop(), + 60, expectedState); break; } diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java index 57fd4b9216..a4711f5f19 100644 --- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java +++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java @@ -584,18 +584,15 @@ public final class LauncherInstrumentation { return mDevice; } - void swipe(int startX, int startY, int endX, int endY, int expectedState) { - swipe(startX, startY, endX, endY, expectedState, 60); - } - - void swipe(int startX, int startY, int endX, int endY, int expectedState, int steps) { - changeStateViaGesture(startX, startY, endX, endY, expectedState, - () -> mDevice.swipe(startX, startY, endX, endY, steps)); - } - void swipeToState(int startX, int startY, int endX, int endY, int steps, int expectedState) { - changeStateViaGesture(startX, startY, endX, endY, expectedState, - () -> linearGesture(startX, startY, endX, endY, steps)); + final Bundle parcel = (Bundle) executeAndWaitForEvent( + () -> linearGesture(startX, startY, endX, endY, steps), + event -> TestProtocol.SWITCHED_TO_STATE_MESSAGE.equals(event.getClassName()), + "Swipe failed to receive an event for the swipe end: " + startX + ", " + startY + + ", " + endX + ", " + endY); + assertEquals("Swipe switched launcher to a wrong state;", + TestProtocol.stateOrdinalToString(expectedState), + TestProtocol.stateOrdinalToString(parcel.getInt(TestProtocol.STATE_FIELD))); } void scroll(UiObject2 container, Direction direction, float percent, Rect margins, int steps) { @@ -652,18 +649,6 @@ public final class LauncherInstrumentation { sendPointer(downTime, endTime, MotionEvent.ACTION_UP, end); } - private void changeStateViaGesture(int startX, int startY, int endX, int endY, - int expectedState, Runnable gesture) { - final Bundle parcel = (Bundle) executeAndWaitForEvent( - gesture, - event -> TestProtocol.SWITCHED_TO_STATE_MESSAGE.equals(event.getClassName()), - "Swipe failed to receive an event for the swipe end: " + startX + ", " + startY - + ", " + endX + ", " + endY); - assertEquals("Swipe switched launcher to a wrong state;", - TestProtocol.stateOrdinalToString(expectedState), - TestProtocol.stateOrdinalToString(parcel.getInt(TestProtocol.STATE_FIELD))); - } - void waitForIdle() { mDevice.waitForIdle(); } From e246dff69f1d0751ee760b442d02c90f088f3fb9 Mon Sep 17 00:00:00 2001 From: Tony Date: Tue, 21 May 2019 19:30:59 -0700 Subject: [PATCH 16/21] Fix some issues with shelf jumping/duration Don't use OvershootParams for 0 button mode, since that interpolator assumes the shelf is moving in conjunction with recents/app window. Instead, use OVERSHOOT_1_2 like we do when not flinging. Also bound the duration when entering recents, since scroller duration could be 750ms if we are snapping to the current page. Now we cap at MAX_SWIPE_DURATION (350ms). This case is most likely to be hit when ending a slow swipe near the final recents scale, since in that case duration is close to 0 and the scroller duration is taken instead. Test: - Artificially always detect a pause, fling up in 0 button mode; ensure shelf doesn't jump - Either with the above artifical change in 0 button, or 2 button mode, end a swipe to recents near its final scale with a slight scroll to the right; ensure duration is 350 instead of 750 Bug: 132283018 Bug: 127783075 Change-Id: I8d5fbd0b30af21b9587fba47d141ba90b3b6e778 --- .../android/quickstep/WindowTransformSwipeHandler.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java index d69262e2c6..2ff5c0c6a5 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java @@ -902,7 +902,7 @@ public class WindowTransformSwipeHandler float minFlingVelocity = mContext.getResources() .getDimension(R.dimen.quickstep_fling_min_velocity); if (Math.abs(endVelocity) > minFlingVelocity && mTransitionDragLength > 0) { - if (endTarget == RECENTS) { + if (endTarget == RECENTS && mMode != Mode.NO_BUTTON) { Interpolators.OvershootParams overshoot = new Interpolators.OvershootParams( startShift, endShift, endShift, velocityPxPerMs.y, mTransitionDragLength); @@ -918,6 +918,10 @@ public class WindowTransformSwipeHandler // derivative of the scroll interpolator at zero, ie. 2. long baseDuration = Math.round(Math.abs(distanceToTravel / velocityPxPerMs.y)); duration = Math.min(MAX_SWIPE_DURATION, 2 * baseDuration); + + if (endTarget == RECENTS) { + interpolator = OVERSHOOT_1_2; + } } } } @@ -932,7 +936,8 @@ public class WindowTransformSwipeHandler } else if (endTarget == RECENTS) { mLiveTileOverlay.startIconAnimation(); if (mRecentsView != null) { - duration = Math.max(duration, mRecentsView.getScroller().getDuration()); + duration = Utilities.boundToRange(mRecentsView.getScroller().getDuration(), + duration, MAX_SWIPE_DURATION); } if (mMode == Mode.NO_BUTTON) { setShelfState(ShelfAnimState.OVERVIEW, interpolator, duration); From 4c76bb8b3efe6369581b7105819459b9efd52b79 Mon Sep 17 00:00:00 2001 From: Jon Miranda Date: Wed, 22 May 2019 07:33:31 -0700 Subject: [PATCH 17/21] Fix bug where recycled FloatingIconView stays clipped to outline. Bug: 123900446 Change-Id: I9507dab86cc0da27626d1b48e0f6a236f2b3f219 --- src/com/android/launcher3/views/FloatingIconView.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/com/android/launcher3/views/FloatingIconView.java b/src/com/android/launcher3/views/FloatingIconView.java index a9e8f1733c..3d5877a597 100644 --- a/src/com/android/launcher3/views/FloatingIconView.java +++ b/src/com/android/launcher3/views/FloatingIconView.java @@ -481,6 +481,7 @@ public class FloatingIconView extends View implements setClipToOutline(true); } else { setBackground(finalDrawable); + setClipToOutline(false); } if (!loadIconSignal.isCanceled()) { @@ -751,5 +752,6 @@ public class FloatingIconView extends View implements mFgTransX = 0; mFgSpringY.cancel(); mBadge = null; + sTmpObjArray[0] = null; } } From 3ab80bb734e8c5d942db834ec44b33e872fcb44d Mon Sep 17 00:00:00 2001 From: vadimt Date: Wed, 22 May 2019 12:58:35 -0700 Subject: [PATCH 18/21] Enable debug tracing for a lab-only non-starting app from all apps Bug: 132900132 Change-Id: I9c5bb51e49f865ea1e1d3d2209a8dfb149f66e87 --- .../quickstep/TestInformationProvider.java | 4 ++-- .../launcher3/BaseDraggingActivity.java | 8 ++++++++ src/com/android/launcher3/Launcher.java | 4 ++++ src/com/android/launcher3/TestProtocol.java | 5 +++-- .../launcher3/touch/ItemClickHandler.java | 20 +++++++++++++++++++ .../android/launcher3/tapl/Launchable.java | 4 ++++ .../com/android/launcher3/tapl/Workspace.java | 4 ++-- 7 files changed, 43 insertions(+), 6 deletions(-) diff --git a/quickstep/src/com/android/quickstep/TestInformationProvider.java b/quickstep/src/com/android/quickstep/TestInformationProvider.java index a948570d2a..d96f9af6fe 100644 --- a/quickstep/src/com/android/quickstep/TestInformationProvider.java +++ b/quickstep/src/com/android/quickstep/TestInformationProvider.java @@ -112,11 +112,11 @@ public class TestInformationProvider extends ContentProvider { break; } - case TestProtocol.REQUEST_ENABLE_DRAG_LOGGING: + case TestProtocol.REQUEST_ENABLE_DEBUG_TRACING: TestProtocol.sDebugTracing = true; break; - case TestProtocol.REQUEST_DISABLE_DRAG_LOGGING: + case TestProtocol.REQUEST_DISABLE_DEBUG_TRACING: TestProtocol.sDebugTracing = false; break; } diff --git a/src/com/android/launcher3/BaseDraggingActivity.java b/src/com/android/launcher3/BaseDraggingActivity.java index ccd9e2529e..bd6ac90f39 100644 --- a/src/com/android/launcher3/BaseDraggingActivity.java +++ b/src/com/android/launcher3/BaseDraggingActivity.java @@ -134,6 +134,10 @@ public abstract class BaseDraggingActivity extends BaseActivity public boolean startActivitySafely(View v, Intent intent, @Nullable ItemInfo item, @Nullable String sourceContainer) { + if (com.android.launcher3.TestProtocol.sDebugTracing) { + android.util.Log.d(com.android.launcher3.TestProtocol.NO_START_TAG, + "startActivitySafely 1"); + } if (mIsSafeModeEnabled && !Utilities.isSystemApp(this, intent)) { Toast.makeText(this, R.string.safemode_shortcut_error, Toast.LENGTH_SHORT).show(); return false; @@ -157,6 +161,10 @@ public abstract class BaseDraggingActivity extends BaseActivity startShortcutIntentSafely(intent, optsBundle, item, sourceContainer); } else if (user == null || user.equals(Process.myUserHandle())) { // Could be launching some bookkeeping activity + if (com.android.launcher3.TestProtocol.sDebugTracing) { + android.util.Log.d(com.android.launcher3.TestProtocol.NO_START_TAG, + "startActivitySafely 2"); + } startActivity(intent, optsBundle); AppLaunchTracker.INSTANCE.get(this).onStartApp(intent.getComponent(), Process.myUserHandle(), sourceContainer); diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 40eb912df5..a59189beaa 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -1782,6 +1782,10 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, public boolean startActivitySafely(View v, Intent intent, ItemInfo item, @Nullable String sourceContainer) { + if (com.android.launcher3.TestProtocol.sDebugTracing) { + android.util.Log.d(com.android.launcher3.TestProtocol.NO_START_TAG, + "startActivitySafely outer"); + } boolean success = super.startActivitySafely(v, intent, item, sourceContainer); if (success && v instanceof BubbleTextView) { // This is set to the view that launched the activity that navigated the user away diff --git a/src/com/android/launcher3/TestProtocol.java b/src/com/android/launcher3/TestProtocol.java index 081150db04..a0440e877e 100644 --- a/src/com/android/launcher3/TestProtocol.java +++ b/src/com/android/launcher3/TestProtocol.java @@ -65,7 +65,8 @@ public final class TestProtocol { public static final String REQUEST_HOME_TO_ALL_APPS_SWIPE_HEIGHT = "home-to-all-apps-swipe-height"; public static boolean sDebugTracing = false; - public static final String REQUEST_ENABLE_DRAG_LOGGING = "enable-drag-logging"; - public static final String REQUEST_DISABLE_DRAG_LOGGING = "disable-drag-logging"; + public static final String REQUEST_ENABLE_DEBUG_TRACING = "enable-debug-tracing"; + public static final String REQUEST_DISABLE_DEBUG_TRACING = "disable-debug-tracing"; public static final String NO_DRAG_TAG = "b/133009122"; + public static final String NO_START_TAG = "b/132900132"; } diff --git a/src/com/android/launcher3/touch/ItemClickHandler.java b/src/com/android/launcher3/touch/ItemClickHandler.java index 06500018d5..99b9f25b18 100644 --- a/src/com/android/launcher3/touch/ItemClickHandler.java +++ b/src/com/android/launcher3/touch/ItemClickHandler.java @@ -66,14 +66,26 @@ public class ItemClickHandler { } private static void onClick(View v, String sourceContainer) { + if (com.android.launcher3.TestProtocol.sDebugTracing) { + android.util.Log.d(com.android.launcher3.TestProtocol.NO_START_TAG, + "onClick 1"); + } // Make sure that rogue clicks don't get through while allapps is launching, or after the // view has detached (it's possible for this to happen if the view is removed mid touch). if (v.getWindowToken() == null) { + if (com.android.launcher3.TestProtocol.sDebugTracing) { + android.util.Log.d(com.android.launcher3.TestProtocol.NO_START_TAG, + "onClick 2"); + } return; } Launcher launcher = Launcher.getLauncher(v.getContext()); if (!launcher.getWorkspace().isFinishedSwitchingState()) { + if (com.android.launcher3.TestProtocol.sDebugTracing) { + android.util.Log.d(com.android.launcher3.TestProtocol.NO_START_TAG, + "onClick 3"); + } return; } @@ -85,6 +97,10 @@ public class ItemClickHandler { onClickFolderIcon(v); } } else if (tag instanceof AppInfo) { + if (com.android.launcher3.TestProtocol.sDebugTracing) { + android.util.Log.d(com.android.launcher3.TestProtocol.NO_START_TAG, + "onClick 4"); + } startAppShortcutOrInfoActivity(v, (AppInfo) tag, launcher, sourceContainer == null ? CONTAINER_ALL_APPS: sourceContainer); } else if (tag instanceof LauncherAppWidgetInfo) { @@ -216,6 +232,10 @@ public class ItemClickHandler { private static void startAppShortcutOrInfoActivity(View v, ItemInfo item, Launcher launcher, @Nullable String sourceContainer) { + if (com.android.launcher3.TestProtocol.sDebugTracing) { + android.util.Log.d(com.android.launcher3.TestProtocol.NO_START_TAG, + "startAppShortcutOrInfoActivity"); + } Intent intent; if (item instanceof PromiseAppInfo) { PromiseAppInfo promiseAppInfo = (PromiseAppInfo) item; diff --git a/tests/tapl/com/android/launcher3/tapl/Launchable.java b/tests/tapl/com/android/launcher3/tapl/Launchable.java index 1b372ec134..3295ddbef4 100644 --- a/tests/tapl/com/android/launcher3/tapl/Launchable.java +++ b/tests/tapl/com/android/launcher3/tapl/Launchable.java @@ -24,6 +24,8 @@ import androidx.test.uiautomator.UiDevice; import androidx.test.uiautomator.UiObject2; import androidx.test.uiautomator.Until; +import com.android.launcher3.TestProtocol; + /** * Ancestor for AppIcon and AppMenuItem. */ @@ -51,9 +53,11 @@ abstract class Launchable { private Background launch(BySelector selector) { LauncherInstrumentation.log("Launchable.launch before click " + mObject.getVisibleCenter()); + mLauncher.getTestInfo(TestProtocol.REQUEST_ENABLE_DEBUG_TRACING); mLauncher.assertTrue( "Launching an app didn't open a new window: " + mObject.getText(), mObject.clickAndWait(Until.newWindow(), LauncherInstrumentation.WAIT_TIME_MS)); + mLauncher.getTestInfo(TestProtocol.REQUEST_DISABLE_DEBUG_TRACING); mLauncher.assertTrue( "App didn't start: " + selector, mLauncher.getDevice().wait(Until.hasObject(selector), diff --git a/tests/tapl/com/android/launcher3/tapl/Workspace.java b/tests/tapl/com/android/launcher3/tapl/Workspace.java index f1dd0136da..10b253d443 100644 --- a/tests/tapl/com/android/launcher3/tapl/Workspace.java +++ b/tests/tapl/com/android/launcher3/tapl/Workspace.java @@ -148,7 +148,7 @@ public final class Workspace extends Home { static void dragIconToWorkspace( LauncherInstrumentation launcher, Launchable launchable, Point dest, String longPressIndicator) { - launcher.getTestInfo(TestProtocol.REQUEST_ENABLE_DRAG_LOGGING); + launcher.getTestInfo(TestProtocol.REQUEST_ENABLE_DEBUG_TRACING); LauncherInstrumentation.log("dragIconToWorkspace: begin"); final Point launchableCenter = launchable.getObject().getVisibleCenter(); final long downTime = SystemClock.uptimeMillis(); @@ -163,7 +163,7 @@ public final class Workspace extends Home { downTime, SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, dest); LauncherInstrumentation.log("dragIconToWorkspace: end"); launcher.waitUntilGone("drop_target_bar"); - launcher.getTestInfo(TestProtocol.REQUEST_DISABLE_DRAG_LOGGING); + launcher.getTestInfo(TestProtocol.REQUEST_DISABLE_DEBUG_TRACING); } /** From 3c7d5fb9dbc6396f67430d5c9e66d775576f2926 Mon Sep 17 00:00:00 2001 From: Kevin Date: Thu, 16 May 2019 11:48:09 -0700 Subject: [PATCH 19/21] Recents Go: Conform to device default style System apps in Q should attempt to conform to device style, so naturally Recents Go should also conform to this so that text changes with the device style changing. This CL ensures all text views change font based off system theming title fonts. Bug: 131839392 Fix: 131839392 Test: Change device theme body font, see that change is propogated to Recents Go app texts, clear all, and empty recents message Change-Id: Ib85ff49383221ef18ed8aa9e53eff129129e37c2 --- go/quickstep/res/layout/clear_all_button.xml | 3 ++- go/quickstep/res/layout/icon_recents_root_view.xml | 1 + go/quickstep/res/layout/task_item_view.xml | 3 ++- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/go/quickstep/res/layout/clear_all_button.xml b/go/quickstep/res/layout/clear_all_button.xml index 2f7c8ae208..eef66add45 100644 --- a/go/quickstep/res/layout/clear_all_button.xml +++ b/go/quickstep/res/layout/clear_all_button.xml @@ -29,5 +29,6 @@ android:text="@string/recents_clear_all" android:textAllCaps="false" android:textColor="@color/clear_all_button_text" - android:textSize="14sp"/> + android:textSize="14sp" + style="@style/TextTitle"/> diff --git a/go/quickstep/res/layout/icon_recents_root_view.xml b/go/quickstep/res/layout/icon_recents_root_view.xml index 595a380bd8..8381ebc631 100644 --- a/go/quickstep/res/layout/icon_recents_root_view.xml +++ b/go/quickstep/res/layout/icon_recents_root_view.xml @@ -36,5 +36,6 @@ android:text="@string/recents_empty_message" android:textColor="@android:color/white" android:textSize="25sp" + style="@style/TextTitle" android:visibility="gone"/> \ No newline at end of file diff --git a/go/quickstep/res/layout/task_item_view.xml b/go/quickstep/res/layout/task_item_view.xml index ab2cf2804b..aeac47786a 100644 --- a/go/quickstep/res/layout/task_item_view.xml +++ b/go/quickstep/res/layout/task_item_view.xml @@ -41,5 +41,6 @@ android:layout_gravity="center_vertical" android:singleLine="true" android:textColor="@android:color/white" - android:textSize="24sp"/> + android:textSize="24sp" + style="@style/TextTitle"/> From a09cfe23403ae7002961dd2cd02f49b338696a4d Mon Sep 17 00:00:00 2001 From: Adam Cohen Date: Wed, 22 May 2019 14:16:36 -0700 Subject: [PATCH 20/21] Fix issue where AllAppsContainerView was blocking touches to part of the home screen => After the scrubber was engaged, it would continue to intercept touches forever (seems like a long standing issue) => Also fixed issue where the All Apps scrubber could be engaged from the Home / Overview states b/133265591 b/132716177 Change-Id: I8c7b9d45be65216f2f1a69f69ab1636accd812c0 --- .../android/launcher3/allapps/AllAppsContainerView.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java index 41252aab54..63682c73ac 100644 --- a/src/com/android/launcher3/allapps/AllAppsContainerView.java +++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java @@ -41,6 +41,7 @@ import com.android.launcher3.Insettable; import com.android.launcher3.InsettableFrameLayout; import com.android.launcher3.ItemInfo; import com.android.launcher3.Launcher; +import com.android.launcher3.LauncherState; import com.android.launcher3.R; import com.android.launcher3.TestProtocol; import com.android.launcher3.Utilities; @@ -193,11 +194,18 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo @Override public boolean onInterceptTouchEvent(MotionEvent ev) { + + // The AllAppsContainerView houses the QSB and is hence visible from the Workspace + // Overview states. We shouldn't intercept for the scrubber in these cases. + if (!mLauncher.isInState(LauncherState.ALL_APPS)) return false; + if (ev.getAction() == MotionEvent.ACTION_DOWN) { AllAppsRecyclerView rv = getActiveRecyclerView(); if (rv != null && rv.getScrollbar().isHitInParent(ev.getX(), ev.getY(), mFastScrollerOffset)) { mTouchHandler = rv.getScrollbar(); + } else { + mTouchHandler = null; } } if (mTouchHandler != null) { From 5686333117ff6e2e4add6b2f32edcf047f241466 Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Wed, 22 May 2019 14:13:53 -0700 Subject: [PATCH 21/21] Adding a utility class to cache views at an activity level Bug: 122345781 Change-Id: I9a939e0b19c06c1089c1ceb515f8b97fb5dbb49e --- .../LauncherActivityControllerHelper.java | 3 +- .../android/quickstep/views/RecentsView.java | 11 --- .../QuickstepAppTransitionManagerImpl.java | 11 ++- res/layout/floating_icon_view.xml | 19 +++++ res/values/config.xml | 1 - src/com/android/launcher3/BaseActivity.java | 7 ++ .../android/launcher3/dragndrop/DragView.java | 5 +- .../android/launcher3/folder/FolderIcon.java | 1 - src/com/android/launcher3/util/ViewCache.java | 73 +++++++++++++++++++ .../launcher3/views/FloatingIconView.java | 44 +++++++---- 10 files changed, 138 insertions(+), 37 deletions(-) create mode 100644 res/layout/floating_icon_view.xml create mode 100644 src/com/android/launcher3/util/ViewCache.java diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java index 90b55360ef..4b2e487da9 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java @@ -118,7 +118,8 @@ public final class LauncherActivityControllerHelper implements ActivityControlHe final RectF iconLocation = new RectF(); boolean canUseWorkspaceView = workspaceView != null && workspaceView.isAttachedToWindow(); FloatingIconView floatingIconView = canUseWorkspaceView - ? recentsView.getFloatingIconView(activity, workspaceView, iconLocation) + ? FloatingIconView.getFloatingIconView(activity, workspaceView, + true /* hideOriginal */, iconLocation, false /* isOpening */) : null; return new HomeAnimationFactory() { diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java index 661468ac62..1e1007e686 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java @@ -66,7 +66,6 @@ import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; -import android.view.ViewConfiguration; import android.view.ViewDebug; import android.view.ViewGroup; import android.view.accessibility.AccessibilityEvent; @@ -77,7 +76,6 @@ import com.android.launcher3.BaseActivity; import com.android.launcher3.DeviceProfile; import com.android.launcher3.Insettable; import com.android.launcher3.InvariantDeviceProfile; -import com.android.launcher3.Launcher; import com.android.launcher3.LauncherAnimUtils.ViewProgressProperty; import com.android.launcher3.LauncherState; import com.android.launcher3.PagedView; @@ -95,7 +93,6 @@ import com.android.launcher3.util.OverScroller; import com.android.launcher3.util.PendingAnimation; import com.android.launcher3.util.Themes; import com.android.launcher3.util.ViewPool; -import com.android.launcher3.views.FloatingIconView; import com.android.quickstep.RecentsAnimationWrapper; import com.android.quickstep.RecentsModel; import com.android.quickstep.RecentsModel.TaskThumbnailChangeListener; @@ -308,8 +305,6 @@ public abstract class RecentsView extends PagedView impl private Layout mEmptyTextLayout; private LiveTileOverlay mLiveTileOverlay; - private FloatingIconView mFloatingIconView; - private BaseActivity.MultiWindowModeChangedListener mMultiWindowModeChangedListener = (inMultiWindowMode) -> { if (!inMultiWindowMode && mOverviewStateEnabled) { @@ -1687,12 +1682,6 @@ public abstract class RecentsView extends PagedView impl } } - public FloatingIconView getFloatingIconView(Launcher launcher, View view, RectF iconLocation) { - mFloatingIconView = FloatingIconView.getFloatingIconView(launcher, view, - true /* hideOriginal */, iconLocation, false /* isOpening */, mFloatingIconView); - return mFloatingIconView; - } - public ClipAnimationHelper getTempClipAnimationHelper() { return mTempClipAnimationHelper; } diff --git a/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java b/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java index 91c460148d..95ae312891 100644 --- a/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java +++ b/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java @@ -142,7 +142,6 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans private final float mClosingWindowTransY; private DeviceProfile mDeviceProfile; - private FloatingIconView mFloatingView; private RemoteAnimationProvider mRemoteAnimationProvider; @@ -411,15 +410,15 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans private ValueAnimator getOpeningWindowAnimators(View v, RemoteAnimationTargetCompat[] targets, Rect windowTargetBounds, boolean toggleVisibility) { RectF bounds = new RectF(); - mFloatingView = FloatingIconView.getFloatingIconView(mLauncher, v, toggleVisibility, - bounds, true /* isOpening */, mFloatingView); + FloatingIconView floatingView = FloatingIconView.getFloatingIconView(mLauncher, v, + toggleVisibility, bounds, true /* isOpening */); Rect crop = new Rect(); Matrix matrix = new Matrix(); RemoteAnimationTargetSet openingTargets = new RemoteAnimationTargetSet(targets, MODE_OPENING); SyncRtSurfaceTransactionApplierCompat surfaceApplier = - new SyncRtSurfaceTransactionApplierCompat(mFloatingView); + new SyncRtSurfaceTransactionApplierCompat(floatingView); openingTargets.addDependentTransactionApplier(surfaceApplier); // Scale the app icon to take up the entire screen. This simplifies the math when @@ -463,7 +462,7 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans ValueAnimator appAnimator = ValueAnimator.ofFloat(0, 1); appAnimator.setDuration(APP_LAUNCH_DURATION); appAnimator.setInterpolator(LINEAR); - appAnimator.addListener(mFloatingView); + appAnimator.addListener(floatingView); appAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { @@ -557,7 +556,7 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans } else { currentBounds.bottom -= croppedHeight; } - mFloatingView.update(currentBounds, mIconAlpha.value, percent, 0f, + floatingView.update(currentBounds, mIconAlpha.value, percent, 0f, cornerRadius * scale, true /* isOpening */); } else { matrix.setTranslate(target.position.x, target.position.y); diff --git a/res/layout/floating_icon_view.xml b/res/layout/floating_icon_view.xml new file mode 100644 index 0000000000..240c486b19 --- /dev/null +++ b/res/layout/floating_icon_view.xml @@ -0,0 +1,19 @@ + + + diff --git a/res/values/config.xml b/res/values/config.xml index 83aea8b1f0..984729b20f 100644 --- a/res/values/config.xml +++ b/res/values/config.xml @@ -86,7 +86,6 @@ - diff --git a/src/com/android/launcher3/BaseActivity.java b/src/com/android/launcher3/BaseActivity.java index 7f7224241b..424ffde1ff 100644 --- a/src/com/android/launcher3/BaseActivity.java +++ b/src/com/android/launcher3/BaseActivity.java @@ -36,6 +36,7 @@ import com.android.launcher3.logging.UserEventDispatcher.UserEventDelegate; import com.android.launcher3.uioverrides.UiFactory; import com.android.launcher3.userevent.nano.LauncherLogProto; import com.android.launcher3.util.SystemUiController; +import com.android.launcher3.util.ViewCache; import com.android.launcher3.views.ActivityContext; import java.io.FileDescriptor; @@ -102,6 +103,12 @@ public abstract class BaseActivity extends Activity // animation @InvisibilityFlags private int mForceInvisible; + private final ViewCache mViewCache = new ViewCache(); + + public ViewCache getViewCache() { + return mViewCache; + } + @Override public DeviceProfile getDeviceProfile() { return mDeviceProfile; diff --git a/src/com/android/launcher3/dragndrop/DragView.java b/src/com/android/launcher3/dragndrop/DragView.java index 7af12c57d4..9d46cf2abf 100644 --- a/src/com/android/launcher3/dragndrop/DragView.java +++ b/src/com/android/launcher3/dragndrop/DragView.java @@ -44,7 +44,6 @@ import android.view.View; import com.android.launcher3.FastBitmapDrawable; import com.android.launcher3.ItemInfo; import com.android.launcher3.Launcher; -import com.android.launcher3.LauncherModel; import com.android.launcher3.LauncherSettings; import com.android.launcher3.LauncherState; import com.android.launcher3.LauncherStateManager; @@ -55,6 +54,7 @@ import com.android.launcher3.anim.Interpolators; import com.android.launcher3.icons.LauncherIcons; import com.android.launcher3.util.Themes; import com.android.launcher3.util.Thunk; +import com.android.launcher3.util.UiThreadHelper; import java.util.Arrays; @@ -210,8 +210,7 @@ public class DragView extends View implements LauncherStateManager.StateListener return; } // Load the adaptive icon on a background thread and add the view in ui thread. - final Looper workerLooper = LauncherModel.getWorkerLooper(); - new Handler(workerLooper).postAtFrontOfQueue(new Runnable() { + new Handler(UiThreadHelper.getBackgroundLooper()).postAtFrontOfQueue(new Runnable() { @Override public void run() { Object[] outObj = new Object[1]; diff --git a/src/com/android/launcher3/folder/FolderIcon.java b/src/com/android/launcher3/folder/FolderIcon.java index 0a9bc722d1..250169cdb2 100644 --- a/src/com/android/launcher3/folder/FolderIcon.java +++ b/src/com/android/launcher3/folder/FolderIcon.java @@ -102,7 +102,6 @@ public class FolderIcon extends FrameLayout implements FolderListener { private List mCurrentPreviewItems = new ArrayList<>(); boolean mAnimating = false; - private Rect mTempBounds = new Rect(); private float mSlop; diff --git a/src/com/android/launcher3/util/ViewCache.java b/src/com/android/launcher3/util/ViewCache.java new file mode 100644 index 0000000000..08b8744167 --- /dev/null +++ b/src/com/android/launcher3/util/ViewCache.java @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2019 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; + +import android.content.Context; +import android.util.SparseArray; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +/** + * Utility class to cache views at an activity level + */ +public class ViewCache { + + protected final SparseArray mCache = new SparseArray(); + + public void setCacheSize(int layoutId, int size) { + mCache.put(layoutId, new CacheEntry(size)); + } + + public T getView(int layoutId, Context context, ViewGroup parent) { + CacheEntry entry = mCache.get(layoutId); + if (entry == null) { + entry = new CacheEntry(1); + mCache.put(layoutId, entry); + } + + if (entry.mCurrentSize > 0) { + entry.mCurrentSize --; + T result = (T) entry.mViews[entry.mCurrentSize]; + entry.mViews[entry.mCurrentSize] = null; + return result; + } + + return (T) LayoutInflater.from(context).inflate(layoutId, parent, false); + } + + public void recycleView(int layoutId, View view) { + CacheEntry entry = mCache.get(layoutId); + if (entry != null && entry.mCurrentSize < entry.mMaxSize) { + entry.mViews[entry.mCurrentSize] = view; + entry.mCurrentSize++; + } + } + + private static class CacheEntry { + + final int mMaxSize; + final View[] mViews; + + int mCurrentSize; + + public CacheEntry(int maxSize) { + mMaxSize = maxSize; + mViews = new View[maxSize]; + mCurrentSize = 0; + } + } +} diff --git a/src/com/android/launcher3/views/FloatingIconView.java b/src/com/android/launcher3/views/FloatingIconView.java index 3d5877a597..f63bcddf0d 100644 --- a/src/com/android/launcher3/views/FloatingIconView.java +++ b/src/com/android/launcher3/views/FloatingIconView.java @@ -27,6 +27,7 @@ import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.animation.ValueAnimator; import android.annotation.TargetApi; +import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Outline; @@ -40,6 +41,7 @@ import android.os.Build; import android.os.CancellationSignal; import android.os.Handler; import android.os.Looper; +import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; import android.view.ViewOutlineProvider; @@ -61,6 +63,7 @@ import com.android.launcher3.graphics.ShiftedBitmapDrawable; import com.android.launcher3.icons.LauncherIcons; import com.android.launcher3.popup.SystemShortcut; import com.android.launcher3.shortcuts.DeepShortcutView; +import com.android.launcher3.util.UiThreadHelper; import androidx.annotation.Nullable; import androidx.annotation.WorkerThread; @@ -148,12 +151,20 @@ public class FloatingIconView extends View implements private final SpringAnimation mFgSpringX; private float mFgTransX; - private FloatingIconView(Launcher launcher) { - super(launcher); - mLauncher = launcher; + public FloatingIconView(Context context) { + this(context, null); + } + + public FloatingIconView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public FloatingIconView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + mLauncher = Launcher.getLauncher(context); mBlurSizeOutline = getResources().getDimensionPixelSize( R.dimen.blur_size_medium_outline); - mListenerView = new ListenerView(launcher, null); + mListenerView = new ListenerView(context, attrs); mFgSpringX = new SpringAnimation(this, mFgTransXProperty) .setSpring(new SpringForce() @@ -350,6 +361,7 @@ public class FloatingIconView extends View implements } @WorkerThread + @SuppressWarnings("WrongThread") private void getIcon(View v, ItemInfo info, boolean isOpening, Runnable onIconLoadedRunnable, CancellationSignal loadIconSignal) { final LayoutParams lp = (LayoutParams) getLayoutParams(); @@ -396,7 +408,7 @@ public class FloatingIconView extends View implements && finalDrawable instanceof AdaptiveIconDrawable; int iconOffset = getOffsetForIconBounds(finalDrawable); - new Handler(Looper.getMainLooper()).post(() -> { + mLauncher.getMainExecutor().execute(() -> { if (isAdaptiveIcon) { mIsAdaptiveIcon = true; boolean isFolderIcon = finalDrawable instanceof FolderAdaptiveIcon; @@ -505,6 +517,7 @@ public class FloatingIconView extends View implements } @WorkerThread + @SuppressWarnings("WrongThread") private int getOffsetForIconBounds(Drawable drawable) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O || !(drawable instanceof AdaptiveIconDrawable)) { @@ -515,7 +528,7 @@ public class FloatingIconView extends View implements Rect bounds = new Rect(0, 0, lp.width + mBlurSizeOutline, lp.height + mBlurSizeOutline); bounds.inset(mBlurSizeOutline / 2, mBlurSizeOutline / 2); - try (LauncherIcons li = LauncherIcons.obtain(getContext())) { + try (LauncherIcons li = LauncherIcons.obtain(mLauncher)) { Utilities.scaleRectAboutCenter(bounds, li.getNormalizer().getScale(drawable, null)); } @@ -604,11 +617,14 @@ public class FloatingIconView extends View implements * @param isOpening True if this view replaces the icon for app open animation. */ public static FloatingIconView getFloatingIconView(Launcher launcher, View originalView, - boolean hideOriginal, RectF positionOut, boolean isOpening, FloatingIconView recycle) { - if (recycle != null) { - recycle.recycle(); - } - FloatingIconView view = recycle != null ? recycle : new FloatingIconView(launcher); + boolean hideOriginal, RectF positionOut, boolean isOpening) { + final DragLayer dragLayer = launcher.getDragLayer(); + ViewGroup parent = (ViewGroup) dragLayer.getParent(); + + FloatingIconView view = launcher.getViewCache().getView(R.layout.floating_icon_view, + launcher, parent); + view.recycle(); + view.mIsVerticalBarLayout = launcher.getDeviceProfile().isVerticalBarLayout(); view.mOriginalIcon = originalView; @@ -626,16 +642,15 @@ public class FloatingIconView extends View implements originalView.setVisibility(INVISIBLE); }; CancellationSignal loadIconSignal = view.mLoadIconSignal; - new Handler(LauncherModel.getWorkerLooper()).postAtFrontOfQueue(() -> { + new Handler(UiThreadHelper.getBackgroundLooper()).postAtFrontOfQueue(() -> { view.getIcon(originalView, (ItemInfo) originalView.getTag(), isOpening, onIconLoaded, loadIconSignal); }); } // We need to add it to the overlay, but keep it invisible until animation starts.. - final DragLayer dragLayer = launcher.getDragLayer(); view.setVisibility(INVISIBLE); - ((ViewGroup) dragLayer.getParent()).addView(view); + parent.addView(view); dragLayer.addView(view.mListenerView); view.mListenerView.setListener(view::onListenerViewClosed); @@ -714,6 +729,7 @@ public class FloatingIconView extends View implements ((ViewGroup) dragLayer.getParent()).removeView(this); dragLayer.removeView(mListenerView); recycle(); + mLauncher.getViewCache().recycleView(R.layout.floating_icon_view, this); } private void recycle() {