From b8b9cfaf0d7565db83df94b1b026e2e746c628d8 Mon Sep 17 00:00:00 2001 From: Tony Wickham Date: Tue, 1 Oct 2019 10:03:14 -0700 Subject: Don't allow scrolling RecentsView outside navbar during quickswitch Once the inputProxy (OverviewInputConsumer) was enabled, it was never disabled. And while it was enabled, touches above the nav bar would go through to launcher, allowing you to scroll RecentsView (for example) during quick switch transitions. This breaks some assumptions, since it doesn't go through our normal shared swipe state logic that cancels the animation, updates the new end target (e.g. NEW_TASK vs LAST_TASK), etc. Thus, if you tried returning to LAST_TASK via this route, we would end up starting it as a new activity instead of resuming the existing one, causing a flicker (I guess because that TaskView is hidden). Test: - Swipe up from task A to home (to enable input proxy) - Open A - Swipe to B, and during transition scroll back to A from the center of the screen Before, this caused a flicker, now the last scroll is ignored. TODO: we should increase the nav region during quick switch to make it easier to continue scrolling Bug: 136829198 Bug: 138620399 Change-Id: I5ffb53743b728e1909066c5dd18cc9308aff2c7e (cherry picked from commit c9654eb09158a9878d7ff8fc9e588ec2d4903318) (cherry picked from commit 2784315f7d62ceea51651e57eb0348f23fb57c59) (cherry picked from commit 80090d579fc10f4dcb985259b6b70efcc27bd062) --- .../android/quickstep/RecentsAnimationWrapper.java | 27 ++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsAnimationWrapper.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsAnimationWrapper.java index e51ba631b..c4d3fa03a 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsAnimationWrapper.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsAnimationWrapper.java @@ -19,6 +19,8 @@ import static android.view.MotionEvent.ACTION_CANCEL; import static android.view.MotionEvent.ACTION_DOWN; import static android.view.MotionEvent.ACTION_UP; +import android.os.SystemClock; +import android.util.Log; import android.view.InputEvent; import android.view.KeyEvent; import android.view.MotionEvent; @@ -38,6 +40,8 @@ import java.util.function.Supplier; */ public class RecentsAnimationWrapper { + private static final String TAG = "RecentsAnimationWrapper"; + // A list of callbacks to run when we receive the recents animation target. There are different // than the state callbacks as these run on the current worker thread. private final ArrayList mCallbacks = new ArrayList<>(); @@ -125,6 +129,7 @@ public class RecentsAnimationWrapper { boolean sendUserLeaveHint) { SwipeAnimationTargetSet controller = targetSet; targetSet = null; + disableInputProxy(); if (controller != null) { controller.finishController(toRecents, onFinishComplete, sendUserLeaveHint); } @@ -153,6 +158,16 @@ public class RecentsAnimationWrapper { mInputConsumerController.setInputListener(this::onInputConsumerEvent); } + private void disableInputProxy() { + if (mInputConsumer != null && mTouchInProgress) { + long now = SystemClock.uptimeMillis(); + MotionEvent dummyCancel = MotionEvent.obtain(now, now, ACTION_CANCEL, 0, 0, 0); + mInputConsumer.onMotionEvent(dummyCancel); + dummyCancel.recycle(); + } + mInputConsumerController.setInputListener(null); + } + private boolean onInputConsumerEvent(InputEvent ev) { if (ev instanceof MotionEvent) { onInputConsumerMotionEvent((MotionEvent) ev); @@ -168,6 +183,18 @@ public class RecentsAnimationWrapper { private boolean onInputConsumerMotionEvent(MotionEvent ev) { int action = ev.getAction(); + + // Just to be safe, verify that ACTION_DOWN comes before any other action, + // and ignore any ACTION_DOWN after the first one (though that should not happen). + if (!mTouchInProgress && action != ACTION_DOWN) { + Log.w(TAG, "Received non-down motion before down motion: " + action); + return false; + } + if (mTouchInProgress && action == ACTION_DOWN) { + Log.w(TAG, "Received down motion while touch was already in progress"); + return false; + } + if (action == ACTION_DOWN) { mTouchInProgress = true; if (mInputConsumer == null) { -- cgit v1.2.3 From 7409190c86352c24e6ac6a023f0e610e02bc93ce Mon Sep 17 00:00:00 2001 From: Tony Wickham Date: Fri, 4 Oct 2019 12:55:22 -0700 Subject: Fix quickswitch flickers/ignored swipes - Don't set current page to running task when applying load plan, if we are already settling on a new task to launch. - When starting a new task, finish to the running app if that's the task being started (should not happen with above change) - When disabling free scroll mode, don't snap to a page if we're already on it. This was setting mNextPage so the first check was falsing. Bug: 142068081 Change-Id: I5b392d9726a81c51718d2f94eee6cd4f78b61f69 Merged-In: I5b392d9726a81c51718d2f94eee6cd4f78b61f69 (cherry picked from commit af33f2c9d4063c2ad95a92777cbd5e66d81d3fab) (cherry picked from commit 4d86c804baf6afb9fad0592ab062a4dba6998a03) --- .../com/android/quickstep/WindowTransformSwipeHandler.java | 10 +++++++++- .../src/com/android/quickstep/views/RecentsView.java | 11 +++++++---- src/com/android/launcher3/PagedView.java | 4 +++- 3 files changed, 19 insertions(+), 6 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 a3bd348e2..e1085e608 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java @@ -923,7 +923,15 @@ public class WindowTransformSwipeHandler windowAnim.addListener(new AnimationSuccessListener() { @Override public void onAnimationSuccess(Animator animator) { - setStateOnUiThread(target.endState); + if (target == NEW_TASK && mRecentsView != null + && mRecentsView.getNextPage() == mRecentsView.getRunningTaskIndex()) { + // We are about to launch the current running task, so use LAST_TASK state + // instead of NEW_TASK. This could happen, for example, if our scroll is + // aborted after we determined the target to be NEW_TASK. + setStateOnUiThread(LAST_TASK.endState); + } else { + setStateOnUiThread(target.endState); + } } }); windowAnim.start(); 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 d98ef425e..ef54d3f89 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 @@ -17,7 +17,6 @@ package com.android.quickstep.views; import static androidx.dynamicanimation.animation.DynamicAnimation.MIN_VISIBLE_CHANGE_PIXELS; - import static com.android.launcher3.BaseActivity.STATE_HANDLER_INVISIBILITY_FLAGS; import static com.android.launcher3.InvariantDeviceProfile.CHANGE_FLAG_ICON_PARAMS; import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY; @@ -572,9 +571,13 @@ public abstract class RecentsView extends PagedView impl final TaskView taskView = (TaskView) getChildAt(pageIndex); taskView.bind(task); } - TaskView runningTaskView = getRunningTaskView(); - if (runningTaskView != null) { - setCurrentPage(indexOfChild(runningTaskView)); + + if (mNextPage == INVALID_PAGE) { + // Set the current page to the running task, but not if settling on new task. + TaskView runningTaskView = getRunningTaskView(); + if (runningTaskView != null) { + setCurrentPage(indexOfChild(runningTaskView)); + } } if (mIgnoreResetTaskId != -1 && getTaskView(mIgnoreResetTaskId) != ignoreRestTaskView) { diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java index 70b55a44d..79d6ca793 100644 --- a/src/com/android/launcher3/PagedView.java +++ b/src/com/android/launcher3/PagedView.java @@ -1088,7 +1088,9 @@ public abstract class PagedView extends ViewGrou if (mFreeScroll) { setCurrentPage(getNextPage()); } else if (wasFreeScroll) { - snapToPage(getNextPage()); + if (getScrollForPage(getNextPage()) != getScrollX()) { + snapToPage(getNextPage()); + } } } -- cgit v1.2.3