From ef77fd0f40ac8b7564dfd7ce5ebea7f31e194315 Mon Sep 17 00:00:00 2001 From: Winson Chung Date: Wed, 21 Mar 2018 16:28:59 -0700 Subject: [PATCH 1/2] Workaround for ensuring dummy task view has valid task - Always assign the first task the running task id so that we can still identify it if applyLoadPlan() is not yet called back from loading tasks. Bug: 76100710 Change-Id: I22e2948a67f532b60415a248d6121febba29b3f6 --- .../android/quickstep/views/RecentsView.java | 35 ++++++++++++------- 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java index 41ac6b1abf..bc4cd90baf 100644 --- a/quickstep/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/src/com/android/quickstep/views/RecentsView.java @@ -26,7 +26,10 @@ import android.animation.ObjectAnimator; import android.animation.TimeInterpolator; import android.animation.ValueAnimator; import android.annotation.TargetApi; +import android.app.ActivityManager; +import android.content.ComponentName; import android.content.Context; +import android.content.Intent; import android.content.SharedPreferences; import android.content.SharedPreferences.OnSharedPreferenceChangeListener; import android.graphics.Canvas; @@ -123,6 +126,7 @@ public abstract class RecentsView // Only valid until the launcher state changes to NORMAL private int mRunningTaskId = -1; + private Task mTmpRunningTask; private boolean mFirstTaskIconScaledDown = false; @@ -470,6 +474,10 @@ public abstract class RecentsView Task task = taskView.getTask(); boolean visible = lower <= i && i <= upper; if (visible) { + if (task == mTmpRunningTask) { + // Skip loading if this is the task that we are animating into + continue; + } if (!mHasVisibleTaskData.get(task.key.id)) { loader.loadTaskData(task); loader.getHighResThumbnailLoader().onTaskVisible(task); @@ -528,24 +536,27 @@ public abstract class RecentsView * Also scrolls the view to this task */ public void showTask(int runningTaskId) { - boolean needsReload = false; if (getChildCount() == 0) { - needsReload = true; - // Add an empty view for now + // Add an empty view for now until the task plan is loaded and applied final TaskView taskView = (TaskView) LayoutInflater.from(getContext()) .inflate(R.layout.task, this, false); - addView(taskView, 0); + addView(taskView); + + // The temporary running task is only used for the duration between the start of the + // gesture and the task list is loaded and applied + mTmpRunningTask = new Task(new Task.TaskKey(runningTaskId, 0, new Intent(), 0, 0), null, + null, "", "", 0, 0, false, true, false, false, + new ActivityManager.TaskDescription(), 0, new ComponentName("", ""), false); + taskView.bind(mTmpRunningTask); } + mRunningTaskId = runningTaskId; setCurrentPage(0); - if (!needsReload) { - needsReload = !mModel.isLoadPlanValid(mLoadPlanId); - } - if (needsReload) { - mLoadPlanId = mModel.loadTasks(runningTaskId, this::applyLoadPlan); - } else { - loadVisibleTaskData(); - } + + // Load the tasks (if the loading is already + mLoadPlanId = mModel.loadTasks(runningTaskId, this::applyLoadPlan); + + // Hide the task that we are animating into getPageAt(mCurrentPage).setAlpha(0); } From 19adf653bde4bcee29df474badd4b6f0745867b8 Mon Sep 17 00:00:00 2001 From: Winson Chung Date: Wed, 28 Mar 2018 10:19:44 -0700 Subject: [PATCH 2/2] Use onQuickStep call from SysUI Change-Id: I838ef4de2d86abde1848efd757a523c088016756 --- .../android/quickstep/MotionEventQueue.java | 10 ++++ .../quickstep/OtherActivityTouchConsumer.java | 51 +++++++++++-------- .../com/android/quickstep/TouchConsumer.java | 2 + .../quickstep/TouchInteractionService.java | 2 + 4 files changed, 43 insertions(+), 22 deletions(-) diff --git a/quickstep/src/com/android/quickstep/MotionEventQueue.java b/quickstep/src/com/android/quickstep/MotionEventQueue.java index 8e6e4c70b8..538e23c3af 100644 --- a/quickstep/src/com/android/quickstep/MotionEventQueue.java +++ b/quickstep/src/com/android/quickstep/MotionEventQueue.java @@ -53,6 +53,8 @@ public class MotionEventQueue { ACTION_VIRTUAL | (5 << ACTION_POINTER_INDEX_SHIFT); private static final int ACTION_SHOW_OVERVIEW_FROM_ALT_TAB = ACTION_VIRTUAL | (6 << ACTION_POINTER_INDEX_SHIFT); + private static final int ACTION_QUICK_STEP = + ACTION_VIRTUAL | (7 << ACTION_POINTER_INDEX_SHIFT); private final EventArray mEmptyArray = new EventArray(); private final Object mExecutionLock = new Object(); @@ -160,6 +162,9 @@ public class MotionEventQueue { mConsumer.onShowOverviewFromAltTab(); mConsumer.updateTouchTracking(INTERACTION_QUICK_SCRUB); break; + case ACTION_QUICK_STEP: + mConsumer.onQuickStep(event.getX(), event.getY(), event.getEventTime()); + break; default: Log.e(TAG, "Invalid virtual event: " + event.getAction()); } @@ -204,6 +209,11 @@ public class MotionEventQueue { queueVirtualAction(ACTION_QUICK_SCRUB_END, 0); } + public void onQuickStep(MotionEvent event) { + event.setAction(ACTION_QUICK_STEP); + queueNoPreProcess(event); + } + public void reset() { queueVirtualAction(ACTION_RESET, 0); } diff --git a/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java b/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java index 4877abbe19..bcc986d5e6 100644 --- a/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java +++ b/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java @@ -79,7 +79,7 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC private final PointF mDownPos = new PointF(); private final PointF mLastPos = new PointF(); private int mActivePointerId = INVALID_POINTER_ID; - private boolean mTouchThresholdCrossed; + private boolean mGestureStarted; private int mTouchSlop; private float mStartDisplacement; private WindowTransformSwipeHandler mInteractionHandler; @@ -122,7 +122,7 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC mDownPos.set(ev.getX(), ev.getY()); mLastPos.set(mDownPos); mTouchSlop = ViewConfiguration.get(this).getScaledPagingTouchSlop(); - mTouchThresholdCrossed = false; + mGestureStarted = false; // Start the window animation on down to give more time for launcher to draw if the // user didn't start the gesture over the back button @@ -155,26 +155,10 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC } mLastPos.set(ev.getX(pointerIndex), ev.getY(pointerIndex)); - float displacement = ev.getY(pointerIndex) - mDownPos.y; - if (isNavBarOnRight()) { - displacement = ev.getX(pointerIndex) - mDownPos.x; - } else if (isNavBarOnLeft()) { - displacement = mDownPos.x - ev.getX(pointerIndex); - } - if (!mTouchThresholdCrossed) { - mTouchThresholdCrossed = Math.abs(displacement) >= mTouchSlop; - if (mTouchThresholdCrossed) { - mStartDisplacement = Math.signum(displacement) * mTouchSlop; - - if (mIsDeferredDownTarget) { - // If we deferred starting the window animation on touch down, then - // start tracking now - startTouchTrackingForWindowAnimation(ev.getEventTime()); - } - notifyGestureStarted(); - } - } else if (mInteractionHandler != null) { + if (mGestureStarted && mInteractionHandler != null) { // Move + float displacement = getDisplacement(ev.getX(pointerIndex), + ev.getY(pointerIndex)); mInteractionHandler.updateDisplacement(displacement - mStartDisplacement); } break; @@ -195,6 +179,7 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC return; } // Notify the handler that the gesture has actually started + mGestureStarted = true; mInteractionHandler.onGestureStarted(); } @@ -276,7 +261,7 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC * the animation can still be running. */ private void finishTouchTracking() { - if (mTouchThresholdCrossed && mInteractionHandler != null) { + if (mGestureStarted && mInteractionHandler != null) { mVelocityTracker.computeCurrentVelocity(1000, ViewConfiguration.get(this).getScaledMaximumFlingVelocity()); @@ -336,6 +321,28 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC } } + @Override + public void onQuickStep(float eventX, float eventY, long eventTime) { + float displacement = getDisplacement(eventX, eventY); + mStartDisplacement = Math.signum(displacement) * mTouchSlop; + if (mIsDeferredDownTarget) { + // If we deferred starting the window animation on touch down, then + // start tracking now + startTouchTrackingForWindowAnimation(eventTime); + } + notifyGestureStarted(); + } + + private float getDisplacement(float eventX, float eventY) { + float displacement = eventY - mDownPos.y; + if (isNavBarOnRight()) { + displacement = eventX - mDownPos.x; + } else if (isNavBarOnLeft()) { + displacement = mDownPos.x - eventX; + } + return displacement; + } + public void switchToMainChoreographer() { mEventQueue.setInterimChoreographer(null); } diff --git a/quickstep/src/com/android/quickstep/TouchConsumer.java b/quickstep/src/com/android/quickstep/TouchConsumer.java index 4e351595ff..1290ec3375 100644 --- a/quickstep/src/com/android/quickstep/TouchConsumer.java +++ b/quickstep/src/com/android/quickstep/TouchConsumer.java @@ -46,6 +46,8 @@ public interface TouchConsumer extends Consumer { default void onQuickScrubProgress(float progress) { } + default void onQuickStep(float eventX, float eventY, long eventTime) { } + /** * Called on the binder thread to allow the consumer to process the motion event before it is * posted on a handler thread. diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java index cc49dc743e..2d58a6b2a3 100644 --- a/quickstep/src/com/android/quickstep/TouchInteractionService.java +++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java @@ -153,6 +153,8 @@ public class TouchInteractionService extends Service { @Override public void onQuickStep(MotionEvent motionEvent) { + mEventQueue.onQuickStep(motionEvent); + TraceHelper.endSection("SysUiBinder", "onQuickStep"); } };