Waiting for a small timeout for launcher draw, before performing the swipe gesture.
This allow for a better synchronized motion, in case launcher draw was fast enough
Change-Id: Ie59aa1e8a2ffa94f3640b4ea08a0c23eeabafb54
diff --git a/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java b/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java
index df012df..d6fe866 100644
--- a/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java
+++ b/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java
@@ -36,6 +36,7 @@
import android.graphics.PointF;
import android.graphics.Rect;
import android.os.Bundle;
+import android.os.Looper;
import android.util.Log;
import android.view.Display;
import android.view.MotionEvent;
@@ -56,12 +57,17 @@
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
import com.android.systemui.shared.system.WindowManagerWrapper;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
/**
* Touch consumer for handling events originating from an activity other than Launcher
*/
public class OtherActivityTouchConsumer extends ContextWrapper implements TouchConsumer {
private static final String TAG = "ActivityTouchConsumer";
+ private static final long LAUNCHER_DRAW_TIMEOUT_MS = 150;
+
private final RunningTaskInfo mRunningTask;
private final RecentsModel mRecentsModel;
private final Intent mHomeIntent;
@@ -111,7 +117,6 @@
startTouchTrackingForWindowAnimation();
}
- mVelocityTracker.addMovement(ev);
Display display = getSystemService(WindowManager.class).getDefaultDisplay();
mDisplayRotation = display.getRotation();
WindowManagerWrapper.getInstance().getStableInsets(mStableInsets);
@@ -127,7 +132,6 @@
ev.getY(newPointerIdx) - (mLastPos.y - mDownPos.y));
mLastPos.set(ev.getX(newPointerIdx), ev.getY(newPointerIdx));
mActivePointerId = ev.getPointerId(newPointerIdx);
- mVelocityTracker.clear();
}
break;
}
@@ -136,7 +140,6 @@
if (pointerIndex == INVALID_POINTER_ID) {
break;
}
- mVelocityTracker.addMovement(ev);
mLastPos.set(ev.getX(pointerIndex), ev.getY(pointerIndex));
float displacement = ev.getY(pointerIndex) - mDownPos.y;
@@ -250,44 +253,60 @@
// Create the shared handler
final WindowTransformSwipeHandler handler =
new WindowTransformSwipeHandler(mRunningTask, this);
- BackgroundExecutor.get().submit(() -> {
- ActivityManagerWrapper.getInstance().startRecentsActivity(mHomeIntent,
- new AssistDataReceiver() {
- @Override
- public void onHandleAssistData(Bundle bundle) {
- // Pass to AIAI
- }
- },
- new RecentsAnimationListener() {
- public void onAnimationStart(
- RecentsAnimationControllerCompat controller,
- RemoteAnimationTargetCompat[] apps) {
- if (mInteractionHandler == handler) {
- handler.setRecentsAnimation(controller, apps);
-
- } else {
- controller.finish(false /* toHome */);
- }
- }
-
- public void onAnimationCanceled() {
- if (mInteractionHandler == handler) {
- handler.setRecentsAnimation(null, null);
- }
- }
- }, null, null);
- });
// Preload the plan
mRecentsModel.loadTasks(mRunningTask.id, null);
mInteractionHandler = handler;
handler.setGestureEndCallback(this::onFinish);
+
+ CountDownLatch drawWaitLock = new CountDownLatch(1);
handler.setLauncherOnDrawCallback(() -> {
+ drawWaitLock.countDown();
if (handler == mInteractionHandler) {
switchToMainConsumer();
}
});
- mMainThreadExecutor.execute(handler::initWhenReady);
+ handler.initWhenReady(mMainThreadExecutor);
+
+ Runnable startActivity = () -> ActivityManagerWrapper.getInstance()
+ .startRecentsActivity(mHomeIntent,
+ new AssistDataReceiver() {
+ @Override
+ public void onHandleAssistData(Bundle bundle) {
+ // Pass to AIAI
+ }
+ },
+ new RecentsAnimationListener() {
+ public void onAnimationStart(
+ RecentsAnimationControllerCompat controller,
+ RemoteAnimationTargetCompat[] apps) {
+ if (mInteractionHandler == handler) {
+ handler.setRecentsAnimation(controller, apps);
+
+ } else {
+ controller.finish(false /* toHome */);
+ }
+ }
+
+ public void onAnimationCanceled() {
+ if (mInteractionHandler == handler) {
+ handler.setRecentsAnimation(null, null);
+ }
+ }
+ }, null, null);
+
+ if (Looper.myLooper() != Looper.getMainLooper()) {
+ startActivity.run();
+ try {
+ drawWaitLock.await(LAUNCHER_DRAW_TIMEOUT_MS, TimeUnit.MILLISECONDS);
+ } catch (Exception e) {
+ // We have waited long enough for launcher to draw
+ }
+ } else {
+ // We should almost always get touch-town on background thread. This is an edge case
+ // when the background Choreographer has not yet initialized.
+ BackgroundExecutor.get().submit(startActivity);
+ }
}
/**
@@ -360,4 +379,14 @@
public void onTouchTrackingComplete() { }
public void switchToMainConsumer() { }
+
+ @Override
+ public void preProcessMotionEvent(MotionEvent ev) {
+ if (mVelocityTracker != null) {
+ mVelocityTracker.addMovement(ev);
+ if (ev.getActionMasked() == ACTION_POINTER_UP) {
+ mVelocityTracker.clear();
+ }
+ }
+ }
}
diff --git a/quickstep/src/com/android/quickstep/TouchConsumer.java b/quickstep/src/com/android/quickstep/TouchConsumer.java
index d4d3a3f..77480af 100644
--- a/quickstep/src/com/android/quickstep/TouchConsumer.java
+++ b/quickstep/src/com/android/quickstep/TouchConsumer.java
@@ -55,4 +55,10 @@
default void onQuickScrubEnd() { }
default void onQuickScrubProgress(float progress) { }
+
+ /**
+ * Called on the binder thread to allow the consumer to process the motion event before it is
+ * posted on a handler thread.
+ */
+ default void preProcessMotionEvent(MotionEvent ev) { }
}
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index ab496ad..e80f97d 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -178,6 +178,7 @@
mEventQueue.setInterimChoreographer(mCurrentConsumer.shouldUseBackgroundConsumer()
? mBackgroundThreadChoreographer : null);
}
+ mCurrentConsumer.preProcessMotionEvent(ev);
mEventQueue.queue(ev);
}
diff --git a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
index 3364c36..5f5d15b 100644
--- a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
+++ b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
@@ -119,6 +119,7 @@
private boolean mWasLauncherAlreadyVisible;
private float mCurrentDisplacement;
+ private boolean mGestureStarted;
private @InteractionType int mInteractionType = INTERACTION_NORMAL;
private boolean mStartedQuickScrubFromHome;
@@ -216,6 +217,7 @@
long accuracy = 2 * Math.max(dp.widthPx, dp.heightPx);
mLauncherTransitionController = launcher.getStateManager()
.createAnimationToNewWorkspace(OVERVIEW, accuracy);
+ mLauncherTransitionController.dispatchOnStart();
mLauncherTransitionController.setPlayFraction(mCurrentShift.value);
state = STATE_ACTIVITY_MULTIPLIER_COMPLETE | STATE_LAUNCHER_DRAWN
@@ -273,10 +275,15 @@
private void launcherFrameDrawn() {
View rootView = mLauncher.getRootView();
if (rootView.getAlpha() < 1) {
- final MultiStateCallback callback = mStateCallback;
- rootView.animate().alpha(1)
- .setDuration(getFadeInDuration())
- .withEndAction(() -> callback.setState(STATE_ACTIVITY_MULTIPLIER_COMPLETE));
+ if (mGestureStarted) {
+ final MultiStateCallback callback = mStateCallback;
+ rootView.animate().alpha(1)
+ .setDuration(getFadeInDuration())
+ .withEndAction(() -> callback.setState(STATE_ACTIVITY_MULTIPLIER_COMPLETE));
+ } else {
+ rootView.setAlpha(1);
+ mStateCallback.setState(STATE_ACTIVITY_MULTIPLIER_COMPLETE);
+ }
}
mLauncherLayoutListener.setHandler(this);
onLauncherLayoutChanged();
@@ -416,7 +423,9 @@
setStateOnUiThread(STATE_APP_CONTROLLER_RECEIVED);
}
- public void onGestureStarted() { }
+ public void onGestureStarted() {
+ mGestureStarted = true;
+ }
@WorkerThread
public void onGestureEnded(float endVelocity) {
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 639fb6c..fcf36ca 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -1256,7 +1256,7 @@
&& AbstractFloatingView.getTopOpenView(this) == null;
boolean isActionMain = Intent.ACTION_MAIN.equals(intent.getAction());
boolean internalStateHandled = InternalStateHandler
- .handleNewIntent(this, intent, alreadyOnHome);
+ .handleNewIntent(this, intent, isStarted());
if (isActionMain) {
if (!internalStateHandled) {
diff --git a/src/com/android/launcher3/states/InternalStateHandler.java b/src/com/android/launcher3/states/InternalStateHandler.java
index 4c3ef4b..7298383 100644
--- a/src/com/android/launcher3/states/InternalStateHandler.java
+++ b/src/com/android/launcher3/states/InternalStateHandler.java
@@ -23,6 +23,7 @@
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherModel.Callbacks;
+import com.android.launcher3.MainThreadExecutor;
import com.android.launcher3.util.Preconditions;
import java.lang.ref.WeakReference;
@@ -52,9 +53,12 @@
return intent;
}
- public final void initWhenReady() {
- Preconditions.assertUIThread();
+ public final void initWhenReady(MainThreadExecutor executor) {
sPendingHandler = new WeakReference<>(this);
+ executor.execute(this::initIfReadOnUIThread);
+ }
+
+ private void initIfReadOnUIThread() {
LauncherAppState app = LauncherAppState.getInstanceNoCreate();
if (app == null) {
return;
@@ -76,15 +80,15 @@
}
public static boolean handleCreate(Launcher launcher, Intent intent) {
- return handleIntent(launcher, intent, false);
+ return handleIntent(launcher, intent, false, false);
}
public static boolean handleNewIntent(Launcher launcher, Intent intent, boolean alreadyOnHome) {
- return handleIntent(launcher, intent, alreadyOnHome);
+ return handleIntent(launcher, intent, alreadyOnHome, true);
}
private static boolean handleIntent(
- Launcher launcher, Intent intent, boolean alreadyOnHome) {
+ Launcher launcher, Intent intent, boolean alreadyOnHome, boolean explicitIntent) {
boolean result = false;
if (intent != null && intent.getExtras() != null) {
IBinder stateBinder = intent.getExtras().getBinder(EXTRA_STATE_HANDLER);
@@ -96,7 +100,7 @@
result = true;
}
}
- if (!result) {
+ if (!result && !explicitIntent) {
InternalStateHandler pendingHandler = sPendingHandler.get();
if (pendingHandler != null) {
if (!pendingHandler.init(launcher, alreadyOnHome)) {