From bfaa9760dd06d13618a17b3ca362db0639fc8008 Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Thu, 25 Apr 2019 18:04:41 -0700 Subject: [PATCH 01/58] Updating the touch proxy logic: In draglayer, we always dispatch touch events to child views. If the touch originated from gesture area, when we dont route it through touch controllers. The proxy events are only send to touch controller. If any controller consumes the event, then we cancel the view touch (pilferPointers) This allows the controllers to work outside the dragView area, and prevents normal view interaction when there is a window on top (like keyboard) while keeping our activity focused Bug: 131088901 Bug: 130618737 Change-Id: If033dde3a0f9cb6a6e449c9586c1fa050af5bdcb --- .../quickstep/OverviewInputConsumer.java | 121 +++++--------- .../quickstep/TouchInteractionService.java | 4 +- .../WindowTransformSwipeHandler.java | 2 +- .../quickstep/fallback/RecentsRootView.java | 29 +--- .../android/launcher3/LauncherRootView.java | 27 +--- .../popup/PopupContainerWithArrow.java | 4 +- .../launcher3/views/BaseDragLayer.java | 150 +++++++++++++----- 7 files changed, 153 insertions(+), 184 deletions(-) diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/OverviewInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/OverviewInputConsumer.java index b803071cfc..32e0e48a4d 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/OverviewInputConsumer.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/OverviewInputConsumer.java @@ -15,24 +15,20 @@ */ package com.android.quickstep; -import static android.view.MotionEvent.ACTION_CANCEL; -import static android.view.MotionEvent.ACTION_DOWN; -import static android.view.MotionEvent.ACTION_MOVE; -import static android.view.MotionEvent.ACTION_UP; import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE; import static com.android.quickstep.TouchInteractionService.TOUCH_INTERACTION_LOG; import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS; -import android.graphics.PointF; import android.view.KeyEvent; import android.view.MotionEvent; -import android.view.ViewConfiguration; import com.android.launcher3.BaseDraggingActivity; import com.android.launcher3.Utilities; import com.android.launcher3.views.BaseDragLayer; -import com.android.quickstep.util.CachedEventDispatcher; import com.android.systemui.shared.system.ActivityManagerWrapper; +import com.android.systemui.shared.system.InputMonitorCompat; + +import androidx.annotation.Nullable; /** * Input consumer for handling touch on the recents/Launcher activity. @@ -40,24 +36,27 @@ import com.android.systemui.shared.system.ActivityManagerWrapper; public class OverviewInputConsumer implements InputConsumer { - private final CachedEventDispatcher mCachedEventDispatcher = new CachedEventDispatcher(); private final T mActivity; private final BaseDragLayer mTarget; + private final InputMonitorCompat mInputMonitor; + private final int[] mLocationOnScreen = new int[2]; - private final PointF mDownPos = new PointF(); - private final int mTouchSlopSquared; + private final boolean mProxyTouch; private final boolean mStartingInActivityBounds; + private boolean mTargetHandledTouch; - private boolean mTrackingStarted = false; - private boolean mInvalidated = false; - - OverviewInputConsumer(T activity, boolean startingInActivityBounds) { + OverviewInputConsumer(T activity, @Nullable InputMonitorCompat inputMonitor, + boolean startingInActivityBounds) { mActivity = activity; - mTarget = activity.getDragLayer(); - int touchSlop = ViewConfiguration.get(mActivity).getScaledTouchSlop(); - mTouchSlopSquared = touchSlop * touchSlop; + mInputMonitor = inputMonitor; mStartingInActivityBounds = startingInActivityBounds; + + mTarget = activity.getDragLayer(); + if (!startingInActivityBounds) { + mTarget.getLocationOnScreen(mLocationOnScreen); + } + mProxyTouch = mTarget.prepareProxyEventStarting(); } @Override @@ -67,45 +66,29 @@ public class OverviewInputConsumer @Override public void onMotionEvent(MotionEvent ev) { - if (mInvalidated) { + if (!mProxyTouch) { return; } - mCachedEventDispatcher.dispatchEvent(ev); - int action = ev.getActionMasked(); - if (action == ACTION_DOWN) { - if (mStartingInActivityBounds) { - startTouchTracking(ev, false /* updateLocationOffset */, - false /* closeActiveWindows */); - return; - } - mTrackingStarted = false; - mDownPos.set(ev.getX(), ev.getY()); - } else if (!mTrackingStarted) { - switch (action) { - case ACTION_CANCEL: - case ACTION_UP: - startTouchTracking(ev, true /* updateLocationOffset */, - false /* closeActiveWindows */); - break; - case ACTION_MOVE: { - float x = ev.getX() - mDownPos.x; - float y = ev.getY() - mDownPos.y; - double hypotSquared = x * x + y * y; - if (hypotSquared >= mTouchSlopSquared) { - // Start tracking only when touch slop is crossed. - startTouchTracking(ev, true /* updateLocationOffset */, - true /* closeActiveWindows */); - } - } - } + + int flags = ev.getEdgeFlags(); + if (!mStartingInActivityBounds) { + ev.setEdgeFlags(flags | Utilities.EDGE_NAV_BAR); } + ev.offsetLocation(-mLocationOnScreen[0], -mLocationOnScreen[1]); + boolean handled = mTarget.proxyTouchEvent(ev); + ev.offsetLocation(mLocationOnScreen[0], mLocationOnScreen[1]); + ev.setEdgeFlags(flags); - if (action == ACTION_UP || action == ACTION_CANCEL) { - mInvalidated = true; - - // Set an empty consumer to that all the cached events are cleared - if (!mCachedEventDispatcher.hasConsumer()) { - mCachedEventDispatcher.setConsumer(motionEvent -> { }); + if (!mTargetHandledTouch && handled) { + mTargetHandledTouch = true; + if (!mStartingInActivityBounds) { + OverviewCallbacks.get(mActivity).closeAllWindows(); + ActivityManagerWrapper.getInstance() + .closeSystemWindows(CLOSE_SYSTEM_WINDOWS_REASON_RECENTS); + TOUCH_INTERACTION_LOG.addLog("startQuickstep"); + } + if (mInputMonitor != null) { + mInputMonitor.pilferPointers(); } } } @@ -117,42 +100,12 @@ public class OverviewInputConsumer } } - private void startTouchTracking(MotionEvent ev, boolean updateLocationOffset, - boolean closeActiveWindows) { - if (updateLocationOffset) { - mTarget.getLocationOnScreen(mLocationOnScreen); - } - - if (closeActiveWindows) { - OverviewCallbacks.get(mActivity).closeAllWindows(); - ActivityManagerWrapper.getInstance() - .closeSystemWindows(CLOSE_SYSTEM_WINDOWS_REASON_RECENTS); - TOUCH_INTERACTION_LOG.addLog("startQuickstep"); - } - - mTrackingStarted = true; - mCachedEventDispatcher.setConsumer(this::sendEvent); - - } - - private void sendEvent(MotionEvent ev) { - if (mInvalidated) { - return; - } - int flags = ev.getEdgeFlags(); - ev.setEdgeFlags(flags | Utilities.EDGE_NAV_BAR); - ev.offsetLocation(-mLocationOnScreen[0], -mLocationOnScreen[1]); - mInvalidated = !mTarget.dispatchTouchEvent(this, ev); - ev.offsetLocation(mLocationOnScreen[0], mLocationOnScreen[1]); - ev.setEdgeFlags(flags); - } - public static InputConsumer newInstance(ActivityControlHelper activityHelper, - boolean startingInActivityBounds) { + @Nullable InputMonitorCompat inputMonitor, boolean startingInActivityBounds) { BaseDraggingActivity activity = activityHelper.getCreatedActivity(); if (activity == null) { return InputConsumer.NO_OP; } - return new OverviewInputConsumer(activity, startingInActivityBounds); + return new OverviewInputConsumer(activity, inputMonitor, startingInActivityBounds); } } \ No newline at end of file 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 fc3f332d5d..b62bac66dd 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java @@ -468,10 +468,10 @@ public class TouchInteractionService extends Service implements mInputMonitorCompat, activityControl); } else if (mSwipeSharedState.goingToLauncher || activityControl.isResumed()) { - return OverviewInputConsumer.newInstance(activityControl, false); + return OverviewInputConsumer.newInstance(activityControl, mInputMonitorCompat, false); } else if (ENABLE_QUICKSTEP_LIVE_TILE.get() && activityControl.isInLiveTileMode()) { - return OverviewInputConsumer.newInstance(activityControl, false); + return OverviewInputConsumer.newInstance(activityControl, mInputMonitorCompat, false); } else { return createOtherActivityInputConsumer(event, runningTaskInfo); } 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 7ffd8d7354..fd63ddce5a 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java @@ -738,7 +738,7 @@ public class WindowTransformSwipeHandler setTargetAlphaProvider(WindowTransformSwipeHandler::getHiddenTargetAlpha); } - return OverviewInputConsumer.newInstance(mActivityControlHelper, true); + return OverviewInputConsumer.newInstance(mActivityControlHelper, null, true); } @UiThread diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/RecentsRootView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/RecentsRootView.java index 777e59252f..09d323ee69 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/RecentsRootView.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/RecentsRootView.java @@ -17,18 +17,13 @@ package com.android.quickstep.fallback; import android.annotation.TargetApi; import android.content.Context; -import android.graphics.Insets; import android.graphics.Point; import android.graphics.Rect; -import android.graphics.RectF; import android.util.AttributeSet; -import android.view.MotionEvent; -import android.view.ViewDebug; import android.view.WindowInsets; import com.android.launcher3.BaseActivity; import com.android.launcher3.R; -import com.android.launcher3.Utilities; import com.android.launcher3.util.Themes; import com.android.launcher3.util.TouchController; import com.android.launcher3.views.BaseDragLayer; @@ -39,9 +34,6 @@ public class RecentsRootView extends BaseDragLayer { private static final int MIN_SIZE = 10; private final RecentsActivity mActivity; - @ViewDebug.ExportedProperty(category = "launcher") - private final RectF mTouchExcludeRegion = new RectF(); - private final Point mLastKnownSize = new Point(MIN_SIZE, MIN_SIZE); public RecentsRootView(Context context, AttributeSet attrs) { @@ -100,26 +92,7 @@ public class RecentsRootView extends BaseDragLayer { @Override public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) { - if (Utilities.ATLEAST_Q) { - Insets gestureInsets = insets.getMandatorySystemGestureInsets(); - mTouchExcludeRegion.set(gestureInsets.left, gestureInsets.top, - gestureInsets.right, gestureInsets.bottom); - } + updateTouchExcludeRegion(insets); return super.dispatchApplyWindowInsets(insets); } - - @Override - public boolean dispatchTouchEvent(MotionEvent ev) { - if (ev.getAction() == MotionEvent.ACTION_DOWN) { - float x = ev.getX(); - float y = ev.getY(); - if (y < mTouchExcludeRegion.top - || x < mTouchExcludeRegion.left - || x > (getWidth() - mTouchExcludeRegion.right) - || y > (getHeight() - mTouchExcludeRegion.bottom)) { - return false; - } - } - return super.dispatchTouchEvent(ev); - } } \ No newline at end of file diff --git a/src/com/android/launcher3/LauncherRootView.java b/src/com/android/launcher3/LauncherRootView.java index e6c2d0c9c5..90e673b3e9 100644 --- a/src/com/android/launcher3/LauncherRootView.java +++ b/src/com/android/launcher3/LauncherRootView.java @@ -8,13 +8,10 @@ import android.app.ActivityManager; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; -import android.graphics.Insets; import android.graphics.Paint; import android.graphics.Rect; -import android.graphics.RectF; import android.os.Build; import android.util.AttributeSet; -import android.view.MotionEvent; import android.view.View; import android.view.ViewDebug; import android.view.WindowInsets; @@ -31,9 +28,6 @@ public class LauncherRootView extends InsettableFrameLayout { @ViewDebug.ExportedProperty(category = "launcher") private final Rect mConsumedInsets = new Rect(); - @ViewDebug.ExportedProperty(category = "launcher") - private final RectF mTouchExcludeRegion = new RectF(); - @ViewDebug.ExportedProperty(category = "launcher") private static final List SYSTEM_GESTURE_EXCLUSION_RECT = Collections.singletonList(new Rect()); @@ -164,29 +158,10 @@ public class LauncherRootView extends InsettableFrameLayout { @Override public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) { - if (Utilities.ATLEAST_Q) { - Insets gestureInsets = insets.getMandatorySystemGestureInsets(); - mTouchExcludeRegion.set(gestureInsets.left, gestureInsets.top, - gestureInsets.right, gestureInsets.bottom); - } + mLauncher.getDragLayer().updateTouchExcludeRegion(insets); return super.dispatchApplyWindowInsets(insets); } - @Override - public boolean dispatchTouchEvent(MotionEvent ev) { - if (ev.getAction() == MotionEvent.ACTION_DOWN) { - float x = ev.getX(); - float y = ev.getY(); - if (y < mTouchExcludeRegion.top - || x < mTouchExcludeRegion.left - || x > (getWidth() - mTouchExcludeRegion.right) - || y > (getHeight() - mTouchExcludeRegion.bottom)) { - return false; - } - } - return super.dispatchTouchEvent(ev); - } - @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); diff --git a/src/com/android/launcher3/popup/PopupContainerWithArrow.java b/src/com/android/launcher3/popup/PopupContainerWithArrow.java index 593dbd46c8..c7d93fec9c 100644 --- a/src/com/android/launcher3/popup/PopupContainerWithArrow.java +++ b/src/com/android/launcher3/popup/PopupContainerWithArrow.java @@ -22,7 +22,6 @@ import static com.android.launcher3.popup.PopupPopulator.MAX_SHORTCUTS_IF_NOTIFI import static com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType; import static com.android.launcher3.userevent.nano.LauncherLogProto.ItemType; import static com.android.launcher3.userevent.nano.LauncherLogProto.Target; -import static com.android.launcher3.Utilities.EDGE_NAV_BAR; import android.animation.AnimatorSet; import android.animation.LayoutTransition; @@ -173,8 +172,7 @@ public class PopupContainerWithArrow extends ArrowPopup implements DragSource, public boolean onControllerInterceptTouchEvent(MotionEvent ev) { if (ev.getAction() == MotionEvent.ACTION_DOWN) { BaseDragLayer dl = getPopupContainer(); - final boolean cameFromNavBar = (ev.getEdgeFlags() & EDGE_NAV_BAR) != 0; - if (!cameFromNavBar && !dl.isEventOverView(this, ev)) { + if (!dl.isEventOverView(this, ev)) { mLauncher.getUserEventDispatcher().logActionTapOutside( LoggerUtils.newContainerTarget(ContainerType.DEEPSHORTCUTS)); close(true); diff --git a/src/com/android/launcher3/views/BaseDragLayer.java b/src/com/android/launcher3/views/BaseDragLayer.java index 66cd536a54..8a15220360 100644 --- a/src/com/android/launcher3/views/BaseDragLayer.java +++ b/src/com/android/launcher3/views/BaseDragLayer.java @@ -22,13 +22,19 @@ import static android.view.MotionEvent.ACTION_UP; import static com.android.launcher3.Utilities.SINGLE_FRAME_MS; +import android.annotation.TargetApi; import android.content.Context; +import android.graphics.Insets; import android.graphics.Rect; +import android.graphics.RectF; +import android.os.Build; import android.util.AttributeSet; import android.util.Property; import android.view.MotionEvent; import android.view.View; +import android.view.ViewDebug; import android.view.ViewGroup; +import android.view.WindowInsets; import android.view.accessibility.AccessibilityEvent; import android.widget.FrameLayout; @@ -74,18 +80,32 @@ public abstract class BaseDragLayer } }; + // Touch is being dispatched through the normal view dispatch system + private static final int TOUCH_DISPATCHING_VIEW = 1 << 0; + // Touch is being dispatched through the normal view dispatch system, and started at the + // system gesture region + private static final int TOUCH_DISPATCHING_GESTURE = 1 << 1; + // Touch is being dispatched through a proxy from InputMonitor + private static final int TOUCH_DISPATCHING_PROXY = 1 << 2; + protected final int[] mTmpXY = new int[2]; protected final Rect mHitRect = new Rect(); + @ViewDebug.ExportedProperty(category = "launcher") + private final RectF mSystemGestureRegion = new RectF(); + private int mTouchDispatchState = 0; + protected final T mActivity; private final MultiValueAlpha mMultiValueAlpha; + // All the touch controllers for the view protected TouchController[] mControllers; + // Touch controller which is currently active for the normal view dispatch protected TouchController mActiveController; - private TouchCompleteListener mTouchCompleteListener; + // Touch controller which is being used for the proxy events + protected TouchController mProxyTouchController; - // Object controlling the current touch interaction - private Object mCurrentTouchOwner; + private TouchCompleteListener mTouchCompleteListener; public BaseDragLayer(Context context, AttributeSet attrs, int alphaChannelCount) { super(context, attrs); @@ -113,30 +133,36 @@ public abstract class BaseDragLayer return findActiveController(ev); } + private TouchController findControllerToHandleTouch(MotionEvent ev) { + AbstractFloatingView topView = AbstractFloatingView.getTopOpenView(mActivity); + if (topView != null && topView.onControllerInterceptTouchEvent(ev)) { + return topView; + } + + for (TouchController controller : mControllers) { + if (controller.onControllerInterceptTouchEvent(ev)) { + return controller; + } + } + return null; + } + protected boolean findActiveController(MotionEvent ev) { if (com.android.launcher3.TestProtocol.sDebugTracing) { android.util.Log.d(com.android.launcher3.TestProtocol.NO_DRAG_TAG, "mActiveController = null"); } mActiveController = null; + if ((mTouchDispatchState & (TOUCH_DISPATCHING_GESTURE | TOUCH_DISPATCHING_PROXY)) == 0) { + // Only look for controllers if we are not dispatching from gesture area and proxy is + // not active + mActiveController = findControllerToHandleTouch(ev); - AbstractFloatingView topView = AbstractFloatingView.getTopOpenView(mActivity); - if (topView != null && topView.onControllerInterceptTouchEvent(ev)) { - if (com.android.launcher3.TestProtocol.sDebugTracing) { - android.util.Log.d(com.android.launcher3.TestProtocol.NO_DRAG_TAG, - "setting controller1: " + topView.getClass().getSimpleName()); - } - mActiveController = topView; - return true; - } - - for (TouchController controller : mControllers) { - if (controller.onControllerInterceptTouchEvent(ev)) { + if (mActiveController != null) { if (com.android.launcher3.TestProtocol.sDebugTracing) { android.util.Log.d(com.android.launcher3.TestProtocol.NO_DRAG_TAG, - "setting controller1: " + controller.getClass().getSimpleName()); + "setting controller1: " + mActiveController.getClass().getSimpleName()); } - mActiveController = controller; return true; } } @@ -223,39 +249,74 @@ public abstract class BaseDragLayer @Override public boolean dispatchTouchEvent(MotionEvent ev) { - return dispatchTouchEvent(this, ev); - } + switch (ev.getAction()) { + case ACTION_DOWN: { + float x = ev.getX(); + float y = ev.getY(); + mTouchDispatchState |= TOUCH_DISPATCHING_VIEW; - public boolean dispatchTouchEvent(Object caller, MotionEvent ev) { - return verifyTouchDispatch(caller, ev) && super.dispatchTouchEvent(ev); + if ((y < mSystemGestureRegion.top + || x < mSystemGestureRegion.left + || x > (getWidth() - mSystemGestureRegion.right) + || y > (getHeight() - mSystemGestureRegion.bottom))) { + mTouchDispatchState |= TOUCH_DISPATCHING_GESTURE; + } else { + mTouchDispatchState &= ~TOUCH_DISPATCHING_GESTURE; + } + break; + } + case ACTION_CANCEL: + case ACTION_UP: + mTouchDispatchState &= ~TOUCH_DISPATCHING_GESTURE; + mTouchDispatchState &= ~TOUCH_DISPATCHING_VIEW; + break; + } + super.dispatchTouchEvent(ev); + + // We want to get all events so that mTouchDispatchSource is maintained properly + return true; } /** - * Returns true if the {@param caller} is allowed to dispatch {@param ev} on this view, - * false otherwise. + * Called before we are about to receive proxy events. + * + * @return false if we can't handle proxy at this time */ - private boolean verifyTouchDispatch(Object caller, MotionEvent ev) { - int action = ev.getAction(); - if (action == ACTION_DOWN) { - if (mCurrentTouchOwner != null) { - // Another touch in progress. - ev.setAction(ACTION_CANCEL); - super.dispatchTouchEvent(ev); - ev.setAction(action); - } - mCurrentTouchOwner = caller; - return true; - } - if (mCurrentTouchOwner != caller) { - // Someone else is controlling the touch + public boolean prepareProxyEventStarting() { + mProxyTouchController = null; + if ((mTouchDispatchState & TOUCH_DISPATCHING_VIEW) != 0 && mActiveController != null) { + // We are already dispatching using view system and have an active controller, we can't + // handle another controller. + + // This flag was already cleared in proxy ACTION_UP or ACTION_CANCEL. Added here just + // to be safe + mTouchDispatchState &= ~TOUCH_DISPATCHING_PROXY; return false; } - if (action == ACTION_UP || action == ACTION_CANCEL) { - mCurrentTouchOwner = null; - } + + mTouchDispatchState |= TOUCH_DISPATCHING_PROXY; return true; } + /** + * Proxies the touch events to the gesture handlers + */ + public boolean proxyTouchEvent(MotionEvent ev) { + boolean handled; + if (mProxyTouchController != null) { + handled = mProxyTouchController.onControllerTouchEvent(ev); + } else { + mProxyTouchController = findControllerToHandleTouch(ev); + handled = mProxyTouchController != null; + } + int action = ev.getAction(); + if (action == ACTION_UP || action == ACTION_CANCEL) { + mProxyTouchController = null; + mTouchDispatchState &= ~TOUCH_DISPATCHING_PROXY; + } + return handled; + } + /** * Determine the rect of the descendant in this DragLayer's coordinates * @@ -423,4 +484,13 @@ public abstract class BaseDragLayer } } } + + @TargetApi(Build.VERSION_CODES.Q) + public void updateTouchExcludeRegion(WindowInsets insets) { + if (Utilities.ATLEAST_Q) { + Insets gestureInsets = insets.getMandatorySystemGestureInsets(); + mSystemGestureRegion.set(gestureInsets.left, gestureInsets.top, + gestureInsets.right, gestureInsets.bottom); + } + } } From 042f2e33fbfc0917f0db334b900bd246eb24c8c9 Mon Sep 17 00:00:00 2001 From: vadimt Date: Fri, 26 Apr 2019 11:44:52 -0700 Subject: [PATCH 02/58] Temporarily disabling 3-button testing mode Bug: 131419978 Change-Id: I9a817140ee5e0fb8d40da67759399f85b0625da0 --- .../src/com/android/quickstep/NavigationModeSwitchRule.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java b/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java index e552f56ba6..572f9a9735 100644 --- a/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java +++ b/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java @@ -92,9 +92,12 @@ public class NavigationModeSwitchRule implements TestRule { if (mode == TWO_BUTTON || mode == ALL) { evaluateWithTwoButtons(); } + /* + b/131419978 if (mode == THREE_BUTTON || mode == ALL) { evaluateWithThreeButtons(); } + */ } finally { setActiveOverlay(prevOverlayPkg, originalMode); } From 9565c2a071d51477f58ee8a1e39dcc73d86ed96a Mon Sep 17 00:00:00 2001 From: vadimt Date: Fri, 26 Apr 2019 12:46:56 -0700 Subject: [PATCH 03/58] Running tests only in 1 nav mode Pixel1: 3-button Pixel2: 2-button Pixel3: 0-button This is a temporary workaround for the listed bugs. Bug: 130558787 Bug: 131419978 Change-Id: Ic57422c7ca8e9985fc0613239c803149e66d907f --- .../quickstep/NavigationModeSwitchRule.java | 6 +- .../launcher3/ui/AbstractLauncherUiTest.java | 67 +++++++++++++++++++ 2 files changed, 69 insertions(+), 4 deletions(-) diff --git a/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java b/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java index 572f9a9735..93e403cc84 100644 --- a/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java +++ b/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java @@ -71,7 +71,8 @@ public class NavigationModeSwitchRule implements TestRule { @Override public Statement apply(Statement base, Description description) { - if (TestHelpers.isInLauncherProcess() && + // b/130558787; b/131419978 + if (false && TestHelpers.isInLauncherProcess() && description.getAnnotation(NavigationModeSwitch.class) != null) { Mode mode = description.getAnnotation(NavigationModeSwitch.class).mode(); return new Statement() { @@ -92,12 +93,9 @@ public class NavigationModeSwitchRule implements TestRule { if (mode == TWO_BUTTON || mode == ALL) { evaluateWithTwoButtons(); } - /* - b/131419978 if (mode == THREE_BUTTON || mode == ALL) { evaluateWithThreeButtons(); } - */ } finally { setActiveOverlay(prevOverlayPkg, originalMode); } diff --git a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java index a37218b179..15402870f4 100644 --- a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java +++ b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java @@ -17,6 +17,10 @@ package com.android.launcher3.ui; import static androidx.test.InstrumentationRegistry.getInstrumentation; +import static com.android.systemui.shared.system.QuickStepContract.NAV_BAR_MODE_2BUTTON_OVERLAY; +import static com.android.systemui.shared.system.QuickStepContract.NAV_BAR_MODE_3BUTTON_OVERLAY; +import static com.android.systemui.shared.system.QuickStepContract.NAV_BAR_MODE_GESTURAL_OVERLAY; + import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -29,6 +33,7 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.pm.LauncherActivityInfo; import android.content.pm.PackageManager; +import android.os.Build; import android.os.Process; import android.os.RemoteException; import android.util.Log; @@ -57,6 +62,7 @@ import com.android.launcher3.util.rule.LauncherActivityRule; import com.android.launcher3.util.rule.ShellCommandRule; import org.junit.After; +import org.junit.Assert; import org.junit.Before; import org.junit.Rule; import org.junit.rules.TestRule; @@ -67,6 +73,7 @@ import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import java.lang.reflect.Method; import java.util.concurrent.Callable; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -102,6 +109,66 @@ public abstract class AbstractLauncherUiTest { } if (TestHelpers.isInLauncherProcess()) Utilities.enableRunningInTestHarnessForTests(); mLauncher = new LauncherInstrumentation(instrumentation); + + // b/130558787; b/131419978 + try { + Class systemProps = Class.forName("android.os.SystemProperties"); + Method getInt = systemProps.getMethod("getInt", String.class, int.class); + int apiLevel = (int) getInt.invoke(null, "ro.product.first_api_level", 0); + + if (apiLevel >= Build.VERSION_CODES.P) { + setActiveOverlay(NAV_BAR_MODE_GESTURAL_OVERLAY, + LauncherInstrumentation.NavigationModel.ZERO_BUTTON); + } + if (apiLevel >= Build.VERSION_CODES.O && apiLevel < Build.VERSION_CODES.P) { + setActiveOverlay(NAV_BAR_MODE_2BUTTON_OVERLAY, + LauncherInstrumentation.NavigationModel.TWO_BUTTON); + } + if (apiLevel < Build.VERSION_CODES.O) { + setActiveOverlay(NAV_BAR_MODE_3BUTTON_OVERLAY, + LauncherInstrumentation.NavigationModel.THREE_BUTTON); + } + } catch (Throwable e) { + e.printStackTrace(); + } + } + + public void setActiveOverlay(String overlayPackage, + LauncherInstrumentation.NavigationModel expectedMode) { + setOverlayPackageEnabled(NAV_BAR_MODE_3BUTTON_OVERLAY, + overlayPackage == NAV_BAR_MODE_3BUTTON_OVERLAY); + setOverlayPackageEnabled(NAV_BAR_MODE_2BUTTON_OVERLAY, + overlayPackage == NAV_BAR_MODE_2BUTTON_OVERLAY); + setOverlayPackageEnabled(NAV_BAR_MODE_GESTURAL_OVERLAY, + overlayPackage == NAV_BAR_MODE_GESTURAL_OVERLAY); + + for (int i = 0; i != 100; ++i) { + if (mLauncher.getNavigationModel() == expectedMode) { + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + return; + } + try { + Thread.sleep(100); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + Assert.fail("Couldn't switch to " + overlayPackage); + } + + private void setOverlayPackageEnabled(String overlayPackage, boolean enable) { + Log.d(TAG, "setOverlayPackageEnabled: " + overlayPackage + " " + enable); + final String action = enable ? "enable" : "disable"; + try { + UiDevice.getInstance(getInstrumentation()).executeShellCommand( + "cmd overlay " + action + " " + overlayPackage); + } catch (IOException e) { + e.printStackTrace(); + } } @Rule From 1d2059031007e78054a244bbbbf6d618162c2baa Mon Sep 17 00:00:00 2001 From: vadimt Date: Fri, 26 Apr 2019 14:10:01 -0700 Subject: [PATCH 04/58] Disabling AppPredictionsUITests Also I recommend not using TAPL here, but follow this: https://docs.google.com/presentation/d/1jyS_AIqevT22mk3SpfFS6paW98QLoJ_Fu7DgpXIgZ2g/edit#slide=id.g3f7630d0d8_0_9 https://docs.google.com/presentation/d/1jyS_AIqevT22mk3SpfFS6paW98QLoJ_Fu7DgpXIgZ2g/edit#slide=id.g435cf3d76d_1_113 Bug: 131188880 Change-Id: Ib01197acbe3ea68e27f121b1c6d8304bbff9696f --- .../src/com/android/quickstep/AppPredictionsUITests.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/quickstep/tests/src/com/android/quickstep/AppPredictionsUITests.java b/quickstep/tests/src/com/android/quickstep/AppPredictionsUITests.java index 43f6039404..72de80bfab 100644 --- a/quickstep/tests/src/com/android/quickstep/AppPredictionsUITests.java +++ b/quickstep/tests/src/com/android/quickstep/AppPredictionsUITests.java @@ -37,6 +37,7 @@ import com.android.launcher3.model.AppLaunchTracker; import org.junit.After; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; @@ -49,7 +50,6 @@ import androidx.test.runner.AndroidJUnit4; @LargeTest @RunWith(AndroidJUnit4.class) public class AppPredictionsUITests extends AbstractQuickStepTest { - private static final int DEFAULT_APP_LAUNCH_TIMES = 3; private static final String TAG = "AppPredictionsUITests"; private LauncherActivityInfo mSampleApp1; @@ -86,6 +86,7 @@ public class AppPredictionsUITests extends AbstractQuickStepTest { * Test that prediction UI is updated as soon as we get predictions from the system */ @Test + @Ignore // b/131188880 public void testPredictionExistsInAllApps() { mActivityMonitor.startLauncher(); mLauncher.pressHome().switchToAllApps(); @@ -106,6 +107,7 @@ public class AppPredictionsUITests extends AbstractQuickStepTest { * Test tat prediction update is deferred if it is already visible */ @Test + @Ignore // b/131188880 public void testPredictionsDeferredUntilHome() { mActivityMonitor.startLauncher(); sendPredictionUpdate(mSampleApp1, mSampleApp2); From 91b01f6c7fe6955a926f0cf6cf11068a4354cf21 Mon Sep 17 00:00:00 2001 From: vadimt Date: Fri, 26 Apr 2019 14:38:21 -0700 Subject: [PATCH 05/58] Not starting Chrome for testing as it's unstable Bug: 131420412 Change-Id: Ief57e8a9ba37feddfc7c2bddc66209e99c796052 --- .../com/android/launcher3/ui/TaplTestsLauncher3.java | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java index c55bc72ca8..2a69757623 100644 --- a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java +++ b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java @@ -239,12 +239,6 @@ public class TaplTestsLauncher3 extends AbstractLauncherUiTest { // Test starting a workspace app. final AppIcon app = workspace.tryGetWorkspaceAppIcon("Chrome"); assertNotNull("No Chrome app in workspace", app); - assertNotNull("AppIcon.launch returned null", - app.launch(resolveSystemApp(Intent.CATEGORY_APP_BROWSER))); - executeOnLauncher(launcher -> assertTrue( - "Launcher activity is the top activity; expecting another activity to be the top " - + "one", - isInBackground(launcher))); } public static void runIconLaunchFromAllAppsTest(AbstractLauncherUiTest test, AllApps allApps) { @@ -340,6 +334,10 @@ public class TaplTestsLauncher3 extends AbstractLauncherUiTest { dragToWorkspace(). getWorkspaceAppIcon(APP_NAME). launch(getAppPackageName()); + executeOnLauncher(launcher -> assertTrue( + "Launcher activity is the top activity; expecting another activity to be the " + + "top one", + isInBackground(launcher))); } finally { TestProtocol.sDebugTracing = false; } From 8153b69da8639a2159168e27dd3650d2b1f7627f Mon Sep 17 00:00:00 2001 From: Winson Chung Date: Fri, 26 Apr 2019 16:41:37 -0700 Subject: [PATCH 06/58] Reset the task's curve scale prior to calculating the recents view scale Bug: 131436393 Test: Swipe to next task, before it can settle, touch and start quick switching again Change-Id: I568ec059be4c5c2f8c663980da0931c01d784f1f --- .../android/quickstep/LauncherActivityControllerHelper.java | 3 +++ .../src/com/android/quickstep/views/TaskView.java | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) 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 a033402ffe..3d2659d544 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java @@ -308,7 +308,10 @@ public final class LauncherActivityControllerHelper implements ActivityControlHe SCALE_PROPERTY.set(recentsView, targetRvScale); recentsView.setTranslationY(0); ClipAnimationHelper clipHelper = new ClipAnimationHelper(launcher); + float tmpCurveScale = v.getCurveScale(); + v.setCurveScale(1f); clipHelper.fromTaskThumbnailView(v.getThumbnail(), (RecentsView) v.getParent(), null); + v.setCurveScale(tmpCurveScale); SCALE_PROPERTY.set(recentsView, prevRvScale); recentsView.setTranslationY(prevRvTransY); diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java index 848c2140fd..298c56268a 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java @@ -492,7 +492,7 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { return 1 - curveInterpolation * EDGE_SCALE_DOWN_FACTOR; } - private void setCurveScale(float curveScale) { + public void setCurveScale(float curveScale) { mCurveScale = curveScale; onScaleChanged(); } From b3a934d98485c05489154ef7ffd06bd3d7a583e0 Mon Sep 17 00:00:00 2001 From: vadimt Date: Fri, 26 Apr 2019 17:28:25 -0700 Subject: [PATCH 07/58] Quick for for broken OOP tests Change-Id: I1009381a58ca28b3ef922f1c6bb872f811f88716 --- .../launcher3/ui/AbstractLauncherUiTest.java | 36 ++++++++++--------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java index 15402870f4..86a5769564 100644 --- a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java +++ b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java @@ -111,25 +111,27 @@ public abstract class AbstractLauncherUiTest { mLauncher = new LauncherInstrumentation(instrumentation); // b/130558787; b/131419978 - try { - Class systemProps = Class.forName("android.os.SystemProperties"); - Method getInt = systemProps.getMethod("getInt", String.class, int.class); - int apiLevel = (int) getInt.invoke(null, "ro.product.first_api_level", 0); + if (TestHelpers.isInLauncherProcess()) { + try { + Class systemProps = Class.forName("android.os.SystemProperties"); + Method getInt = systemProps.getMethod("getInt", String.class, int.class); + int apiLevel = (int) getInt.invoke(null, "ro.product.first_api_level", 0); - if (apiLevel >= Build.VERSION_CODES.P) { - setActiveOverlay(NAV_BAR_MODE_GESTURAL_OVERLAY, - LauncherInstrumentation.NavigationModel.ZERO_BUTTON); + if (apiLevel >= Build.VERSION_CODES.P) { + setActiveOverlay(NAV_BAR_MODE_GESTURAL_OVERLAY, + LauncherInstrumentation.NavigationModel.ZERO_BUTTON); + } + if (apiLevel >= Build.VERSION_CODES.O && apiLevel < Build.VERSION_CODES.P) { + setActiveOverlay(NAV_BAR_MODE_2BUTTON_OVERLAY, + LauncherInstrumentation.NavigationModel.TWO_BUTTON); + } + if (apiLevel < Build.VERSION_CODES.O) { + setActiveOverlay(NAV_BAR_MODE_3BUTTON_OVERLAY, + LauncherInstrumentation.NavigationModel.THREE_BUTTON); + } + } catch (Throwable e) { + e.printStackTrace(); } - if (apiLevel >= Build.VERSION_CODES.O && apiLevel < Build.VERSION_CODES.P) { - setActiveOverlay(NAV_BAR_MODE_2BUTTON_OVERLAY, - LauncherInstrumentation.NavigationModel.TWO_BUTTON); - } - if (apiLevel < Build.VERSION_CODES.O) { - setActiveOverlay(NAV_BAR_MODE_3BUTTON_OVERLAY, - LauncherInstrumentation.NavigationModel.THREE_BUTTON); - } - } catch (Throwable e) { - e.printStackTrace(); } } From 3be3f03e9082d06e68ac378fe3a27a3760cdbf6a Mon Sep 17 00:00:00 2001 From: vadimt Date: Fri, 26 Apr 2019 18:29:07 -0700 Subject: [PATCH 08/58] Attempt to fix broken tests by having different nav models Change-Id: I1adae9f5897269bda9019b1cce0479b6d4af1c72 Pixel1: 3 button Pixel2: 0 button Pixel3: 2 button --- .../com/android/launcher3/ui/AbstractLauncherUiTest.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java index 86a5769564..3e84440b0c 100644 --- a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java +++ b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java @@ -118,13 +118,13 @@ public abstract class AbstractLauncherUiTest { int apiLevel = (int) getInt.invoke(null, "ro.product.first_api_level", 0); if (apiLevel >= Build.VERSION_CODES.P) { - setActiveOverlay(NAV_BAR_MODE_GESTURAL_OVERLAY, - LauncherInstrumentation.NavigationModel.ZERO_BUTTON); - } - if (apiLevel >= Build.VERSION_CODES.O && apiLevel < Build.VERSION_CODES.P) { setActiveOverlay(NAV_BAR_MODE_2BUTTON_OVERLAY, LauncherInstrumentation.NavigationModel.TWO_BUTTON); } + if (apiLevel >= Build.VERSION_CODES.O && apiLevel < Build.VERSION_CODES.P) { + setActiveOverlay(NAV_BAR_MODE_GESTURAL_OVERLAY, + LauncherInstrumentation.NavigationModel.ZERO_BUTTON); + } if (apiLevel < Build.VERSION_CODES.O) { setActiveOverlay(NAV_BAR_MODE_3BUTTON_OVERLAY, LauncherInstrumentation.NavigationModel.THREE_BUTTON); From 31d569e324315d27fef24b86cc81d8b0da3c6b19 Mon Sep 17 00:00:00 2001 From: Tim Joines Date: Mon, 29 Apr 2019 10:32:49 -0700 Subject: [PATCH 09/58] Launcher3GoIconRecents should override Launcher3Go The default recommended launcher should be Launcher3GoIconRecents for low_ram devices. Bug: 131434765 Test: manual, check out dir --- Android.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Android.mk b/Android.mk index 6568a263e8..7956d2810a 100644 --- a/Android.mk +++ b/Android.mk @@ -298,7 +298,7 @@ LOCAL_PROGUARD_ENABLED := full LOCAL_PACKAGE_NAME := Launcher3GoIconRecents LOCAL_PRIVILEGED_MODULE := true LOCAL_PRODUCT_MODULE := true -LOCAL_OVERRIDES_PACKAGES := Home Launcher2 Launcher3 Launcher3QuickStep Launcher3QuickStepGo +LOCAL_OVERRIDES_PACKAGES := Home Launcher2 Launcher3 Launcher3Go Launcher3QuickStep Launcher3QuickStepGo LOCAL_REQUIRED_MODULES := privapp_whitelist_com.android.launcher3 LOCAL_FULL_LIBS_MANIFEST_FILES := \ From 0382dd76e8b04180a716d4cebc4b98caf80a948b Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Wed, 10 Apr 2019 15:47:08 -0700 Subject: [PATCH 10/58] Releasing SurfaceControl when they are no longer needed Bug: 123874711 Change-Id: I9c06723a3e5d4a23b8a6c60352806bb12daba598 --- .../android/quickstep/SwipeSharedState.java | 11 ++++++++-- .../com/android/quickstep/TaskViewUtils.java | 22 ++++++++++++++----- .../WindowTransformSwipeHandler.java | 14 ++++++------ .../util/SwipeAnimationTargetSet.java | 5 ----- .../QuickstepAppTransitionManagerImpl.java | 4 ++-- .../util/RemoteAnimationTargetSet.java | 21 ++++++++++++++++++ 6 files changed, 56 insertions(+), 21 deletions(-) diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeSharedState.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeSharedState.java index 7c6638a440..f393387a7f 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeSharedState.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeSharedState.java @@ -51,9 +51,16 @@ public class SwipeSharedState implements SwipeAnimationListener { mLastAnimationRunning = true; } + private void clearAnimationTarget() { + if (mLastAnimationTarget != null) { + mLastAnimationTarget.release(); + mLastAnimationTarget = null; + } + } + @Override public final void onRecentsAnimationCanceled() { - mLastAnimationTarget = null; + clearAnimationTarget(); mLastAnimationCancelled = true; mLastAnimationRunning = false; @@ -64,7 +71,7 @@ public class SwipeSharedState implements SwipeAnimationListener { mRecentsAnimationListener.removeListener(this); } mRecentsAnimationListener = null; - mLastAnimationTarget = null; + clearAnimationTarget(); mLastAnimationCancelled = false; mLastAnimationRunning = false; } diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskViewUtils.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskViewUtils.java index 4526d670d5..5b9400201f 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskViewUtils.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskViewUtils.java @@ -19,6 +19,8 @@ import static com.android.launcher3.anim.Interpolators.LINEAR; import static com.android.launcher3.anim.Interpolators.TOUCH_RESPONSE_INTERPOLATOR; import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_OPENING; +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; import android.content.ComponentName; import android.graphics.RectF; @@ -109,8 +111,14 @@ public final class TaskViewUtils { */ public static ValueAnimator getRecentsWindowAnimator(TaskView v, boolean skipViewChanges, RemoteAnimationTargetCompat[] targets, final ClipAnimationHelper inOutHelper) { + SyncRtSurfaceTransactionApplierCompat applier = + new SyncRtSurfaceTransactionApplierCompat(v); ClipAnimationHelper.TransformParams params = new ClipAnimationHelper.TransformParams() - .setSyncTransactionApplier(new SyncRtSurfaceTransactionApplierCompat(v)); + .setSyncTransactionApplier(applier); + + final RemoteAnimationTargetSet targetSet = + new RemoteAnimationTargetSet(targets, MODE_OPENING); + targetSet.addDependentTransactionApplier(applier); final ValueAnimator appAnimator = ValueAnimator.ofFloat(0, 1); appAnimator.setInterpolator(TOUCH_RESPONSE_INTERPOLATOR); @@ -120,17 +128,15 @@ public final class TaskViewUtils { final FloatProp mViewAlpha = new FloatProp(1f, 0f, 75, 75, LINEAR); final FloatProp mTaskAlpha = new FloatProp(0f, 1f, 0, 75, LINEAR); - final RemoteAnimationTargetSet mTargetSet; final RectF mThumbnailRect; { - mTargetSet = new RemoteAnimationTargetSet(targets, MODE_OPENING); inOutHelper.setTaskAlphaCallback((t, alpha) -> mTaskAlpha.value); inOutHelper.prepareAnimation(true /* isOpening */); inOutHelper.fromTaskThumbnailView(v.getThumbnail(), (RecentsView) v.getParent(), - mTargetSet.apps.length == 0 ? null : mTargetSet.apps[0]); + targetSet.apps.length == 0 ? null : targetSet.apps[0]); mThumbnailRect = new RectF(inOutHelper.getTargetRect()); mThumbnailRect.offset(-v.getTranslationX(), -v.getTranslationY()); @@ -140,7 +146,7 @@ public final class TaskViewUtils { @Override public void onUpdate(float percent) { params.setProgress(1 - percent); - RectF taskBounds = inOutHelper.applyTransform(mTargetSet, params); + RectF taskBounds = inOutHelper.applyTransform(targetSet, params); if (!skipViewChanges) { float scale = taskBounds.width() / mThumbnailRect.width(); v.setScaleX(scale); @@ -151,6 +157,12 @@ public final class TaskViewUtils { } } }); + appAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + targetSet.release(); + } + }); return appAnimator; } } 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 4df1b151a8..50a60fddba 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java @@ -250,7 +250,6 @@ public class WindowTransformSwipeHandler private T mActivity; private RecentsView mRecentsView; - private SyncRtSurfaceTransactionApplierCompat mSyncTransactionApplier; private AnimationFactory mAnimationFactory = (t) -> { }; private LiveTileOverlay mLiveTileOverlay = new LiveTileOverlay(); @@ -405,8 +404,11 @@ public class WindowTransformSwipeHandler } mRecentsView = activity.getOverviewPanel(); - SyncRtSurfaceTransactionApplierCompat.create(mRecentsView, - applier -> mSyncTransactionApplier = applier ); + SyncRtSurfaceTransactionApplierCompat.create(mRecentsView, applier -> { + mTransformParams.setSyncTransactionApplier(applier); + mRecentsAnimationWrapper.runOnInit(() -> + mRecentsAnimationWrapper.targetSet.addDependentTransactionApplier(applier)); + }); mRecentsView.setEnableFreeScroll(false); mRecentsView.setOnScrollChangeListener((v, scrollX, scrollY, oldScrollX, oldScrollY) -> { @@ -648,8 +650,7 @@ public class WindowTransformSwipeHandler } float offsetScale = getTaskCurveScaleForOffsetX(offsetX, mClipAnimationHelper.getTargetRect().width()); - mTransformParams.setProgress(shift).setOffsetX(offsetX).setOffsetScale(offsetScale) - .setSyncTransactionApplier(mSyncTransactionApplier); + mTransformParams.setProgress(shift).setOffsetX(offsetX).setOffsetScale(offsetScale); mClipAnimationHelper.applyTransform(mRecentsAnimationWrapper.targetSet, mTransformParams); mRecentsAnimationWrapper.setWindowThresholdCrossed( @@ -1047,8 +1048,7 @@ public class WindowTransformSwipeHandler float iconAlpha = Utilities.mapToRange(interpolatedProgress, 0, windowAlphaThreshold, 0f, 1f, Interpolators.LINEAR); - mTransformParams.setCurrentRectAndTargetAlpha(currentRect, 1f - iconAlpha) - .setSyncTransactionApplier(mSyncTransactionApplier); + mTransformParams.setCurrentRectAndTargetAlpha(currentRect, 1f - iconAlpha); mClipAnimationHelper.applyTransform(targetSet, mTransformParams, false /* launcherOnTop */); diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/SwipeAnimationTargetSet.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/SwipeAnimationTargetSet.java index 5a1a103204..83973fa7ec 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/SwipeAnimationTargetSet.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/SwipeAnimationTargetSet.java @@ -95,9 +95,4 @@ public class SwipeAnimationTargetSet extends RemoteAnimationTargetSet { void onRecentsAnimationCanceled(); } - - public interface SwipeAnimationFinishListener { - - void onSwipeAnimationFinished(SwipeAnimationTargetSet targetSet); - } } diff --git a/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java b/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java index cda9d4f348..886dcc3de6 100644 --- a/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java +++ b/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java @@ -416,10 +416,9 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans RemoteAnimationTargetSet openingTargets = new RemoteAnimationTargetSet(targets, MODE_OPENING); - RemoteAnimationTargetSet closingTargets = new RemoteAnimationTargetSet(targets, - MODE_CLOSING); SyncRtSurfaceTransactionApplierCompat surfaceApplier = new SyncRtSurfaceTransactionApplierCompat(mFloatingView); + openingTargets.addDependentTransactionApplier(surfaceApplier); // Scale the app icon to take up the entire screen. This simplifies the math when // animating the app window position / scale. @@ -470,6 +469,7 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans if (v instanceof BubbleTextView) { ((BubbleTextView) v).setStayPressed(false); } + openingTargets.release(); } }); diff --git a/quickstep/src/com/android/quickstep/util/RemoteAnimationTargetSet.java b/quickstep/src/com/android/quickstep/util/RemoteAnimationTargetSet.java index c3724853ae..0df4e947d3 100644 --- a/quickstep/src/com/android/quickstep/util/RemoteAnimationTargetSet.java +++ b/quickstep/src/com/android/quickstep/util/RemoteAnimationTargetSet.java @@ -16,14 +16,20 @@ package com.android.quickstep.util; import com.android.systemui.shared.system.RemoteAnimationTargetCompat; +import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat; +import java.util.ArrayDeque; import java.util.ArrayList; +import java.util.Queue; /** * Holds a collection of RemoteAnimationTargets, filtered by different properties. */ public class RemoteAnimationTargetSet { + private final Queue mDependentTransactionAppliers = + new ArrayDeque<>(1); + public final RemoteAnimationTargetCompat[] unfilteredApps; public final RemoteAnimationTargetCompat[] apps; public final int targetMode; @@ -60,4 +66,19 @@ public class RemoteAnimationTargetSet { } return false; } + + public void addDependentTransactionApplier(SyncRtSurfaceTransactionApplierCompat delay) { + mDependentTransactionAppliers.add(delay); + } + + public void release() { + SyncRtSurfaceTransactionApplierCompat applier = mDependentTransactionAppliers.poll(); + if (applier == null) { + for (RemoteAnimationTargetCompat target : unfilteredApps) { + target.release(); + } + } else { + applier.addAfterApplyCallback(this::release); + } + } } From eb815415da35c68ba05cc57c844b46c69be99b02 Mon Sep 17 00:00:00 2001 From: Kevin Date: Mon, 29 Apr 2019 11:25:16 -0700 Subject: [PATCH 11/58] Layout aligned to dp grid for portrait (1/3) This CL sets fixed dp values for the recents item views based off the UX spec. Vertical margins will be handled by an item decorator in the next CL to handle special cases. Bug: 131610834 Test: Builds Change-Id: Ieb7936bd24933552844a6bd1bdb9e3101b8cdca4 --- go/quickstep/res/layout/clear_all_button.xml | 8 +++----- go/quickstep/res/layout/task_item_view.xml | 6 ++---- go/quickstep/res/values/dimens.xml | 6 ++++++ .../src/com/android/quickstep/views/IconRecentsView.java | 1 + 4 files changed, 12 insertions(+), 9 deletions(-) diff --git a/go/quickstep/res/layout/clear_all_button.xml b/go/quickstep/res/layout/clear_all_button.xml index be76d53661..85ccb88ca8 100644 --- a/go/quickstep/res/layout/clear_all_button.xml +++ b/go/quickstep/res/layout/clear_all_button.xml @@ -18,14 +18,12 @@ xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/clear_all_item_view" android:layout_width="match_parent" - android:layout_height="match_parent"> + android:layout_height="@dimen/clear_all_item_view_height">