diff options
author | Sunny Goyal <sunnygoyal@google.com> | 2018-03-12 13:40:58 -0700 |
---|---|---|
committer | Sunny Goyal <sunnygoyal@google.com> | 2018-03-12 15:25:17 -0700 |
commit | 6586062f711a5194d22d870b66ba7e5a8467576f (patch) | |
tree | 624b2195f13f1f18e0941724186ce7eaab8bee04 /quickstep/src/com/android | |
parent | dcdeffdfd5446886759e128d4b59ffa1cb3c2dc1 (diff) | |
download | android_packages_apps_Trebuchet-6586062f711a5194d22d870b66ba7e5a8467576f.tar.gz android_packages_apps_Trebuchet-6586062f711a5194d22d870b66ba7e5a8467576f.tar.bz2 android_packages_apps_Trebuchet-6586062f711a5194d22d870b66ba7e5a8467576f.zip |
Ensuring that we finish the last transition before starting a new one.
> Finishing the active animation instead of cancelling it. This ansures
that the animation callbacks are called properly and RecentsAnimaiton is finished
> If a transition is already running, using main thread for next transtion so that
this new transition is not started before the last transition is finished.
> If the transition is expected to finish at Launcher, directly use the Launcher
consumer. RunningTaskInfo is not updated until the screen shot is complete.
Bug: 74481901
Change-Id: I2b1128f1f2eff0e6bd94b3adb9cef6ae0578bd0c
Diffstat (limited to 'quickstep/src/com/android')
9 files changed, 186 insertions, 29 deletions
diff --git a/quickstep/src/com/android/quickstep/AnimatedFloat.java b/quickstep/src/com/android/quickstep/AnimatedFloat.java index 214b3f3b9..84dfa457e 100644 --- a/quickstep/src/com/android/quickstep/AnimatedFloat.java +++ b/quickstep/src/com/android/quickstep/AnimatedFloat.java @@ -77,6 +77,12 @@ public class AnimatedFloat { } } + public void finishAnimation() { + if (mValueAnimator != null && mValueAnimator.isRunning()) { + mValueAnimator.end(); + } + } + public ObjectAnimator getCurrentAnimation() { return mValueAnimator; } diff --git a/quickstep/src/com/android/quickstep/BaseSwipeInteractionHandler.java b/quickstep/src/com/android/quickstep/BaseSwipeInteractionHandler.java index b3ebd772c..5871a6d59 100644 --- a/quickstep/src/com/android/quickstep/BaseSwipeInteractionHandler.java +++ b/quickstep/src/com/android/quickstep/BaseSwipeInteractionHandler.java @@ -23,6 +23,7 @@ import com.android.quickstep.TouchConsumer.InteractionType; public abstract class BaseSwipeInteractionHandler extends InternalStateHandler { protected Runnable mGestureEndCallback; + protected boolean mIsGoingToHome; public void setGestureEndCallback(Runnable gestureEndCallback) { mGestureEndCallback = gestureEndCallback; diff --git a/quickstep/src/com/android/quickstep/DeferredTouchConsumer.java b/quickstep/src/com/android/quickstep/DeferredTouchConsumer.java new file mode 100644 index 000000000..b92678a2e --- /dev/null +++ b/quickstep/src/com/android/quickstep/DeferredTouchConsumer.java @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2018 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.quickstep; + +import android.annotation.TargetApi; +import android.os.Build; +import android.view.Choreographer; +import android.view.MotionEvent; +import android.view.VelocityTracker; + +/** + * A TouchConsumer which defers all events on the UIThread until the consumer is created. + */ +@TargetApi(Build.VERSION_CODES.P) +public class DeferredTouchConsumer implements TouchConsumer { + + private final VelocityTracker mVelocityTracker; + private final DeferredTouchProvider mTouchProvider; + + private MotionEventQueue mMyQueue; + private TouchConsumer mTarget; + + public DeferredTouchConsumer(DeferredTouchProvider touchProvider) { + mVelocityTracker = VelocityTracker.obtain(); + mTouchProvider = touchProvider; + } + + @Override + public void accept(MotionEvent event) { + mTarget.accept(event); + } + + @Override + public void reset() { + mTarget.reset(); + } + + @Override + public void updateTouchTracking(int interactionType) { + mTarget.updateTouchTracking(interactionType); + } + + @Override + public void onQuickScrubEnd() { + mTarget.onQuickScrubEnd(); + } + + @Override + public void onQuickScrubProgress(float progress) { + mTarget.onQuickScrubProgress(progress); + } + + @Override + public void preProcessMotionEvent(MotionEvent ev) { + mVelocityTracker.addMovement(ev); + } + + @Override + public Choreographer getIntrimChoreographer(MotionEventQueue queue) { + mMyQueue = queue; + return null; + } + + @Override + public void deferInit() { + mTarget = mTouchProvider.createTouchConsumer(mVelocityTracker); + mTarget.getIntrimChoreographer(mMyQueue); + } + + @Override + public boolean forceToLauncherConsumer() { + return mTarget.forceToLauncherConsumer(); + } + + @Override + public boolean deferNextEventToMainThread() { + // If our target is still null, defer the next target as well + TouchConsumer target = mTarget; + return target == null ? true : target.deferNextEventToMainThread(); + } + + public interface DeferredTouchProvider { + + TouchConsumer createTouchConsumer(VelocityTracker tracker); + } +} diff --git a/quickstep/src/com/android/quickstep/MotionEventQueue.java b/quickstep/src/com/android/quickstep/MotionEventQueue.java index 6e92d83c5..94b6faa39 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 | (4 << ACTION_POINTER_INDEX_SHIFT); private static final int ACTION_RESET = ACTION_VIRTUAL | (5 << ACTION_POINTER_INDEX_SHIFT); + private static final int ACTION_DEFER_INIT = + ACTION_VIRTUAL | (6 << ACTION_POINTER_INDEX_SHIFT); private final EventArray mEmptyArray = new EventArray(); private final Object mExecutionLock = new Object(); @@ -76,10 +78,10 @@ public class MotionEventQueue { public MotionEventQueue(Choreographer choreographer, TouchConsumer consumer) { mMainChoreographer = choreographer; mConsumer = consumer; - mCurrentChoreographer = mMainChoreographer; mCurrentRunnable = mMainFrameCallback; - setInterimChoreographerLocked(consumer.getIntrimChoreographer(this)); + + setInterimChoreographer(consumer.getIntrimChoreographer(this)); } public void setInterimChoreographer(Choreographer choreographer) { @@ -156,6 +158,9 @@ public class MotionEventQueue { case ACTION_RESET: mConsumer.reset(); break; + case ACTION_DEFER_INIT: + mConsumer.deferInit(); + break; default: Log.e(TAG, "Invalid virtual event: " + event.getAction()); } @@ -204,6 +209,14 @@ public class MotionEventQueue { queueVirtualAction(ACTION_RESET, 0); } + public void deferInit() { + queueVirtualAction(ACTION_DEFER_INIT, 0); + } + + public TouchConsumer getConsumer() { + return mConsumer; + } + private static class EventArray extends ArrayList<MotionEvent> { public int lastEventAction = ACTION_CANCEL; diff --git a/quickstep/src/com/android/quickstep/NavBarSwipeInteractionHandler.java b/quickstep/src/com/android/quickstep/NavBarSwipeInteractionHandler.java index ff7d434e7..fca844c6b 100644 --- a/quickstep/src/com/android/quickstep/NavBarSwipeInteractionHandler.java +++ b/quickstep/src/com/android/quickstep/NavBarSwipeInteractionHandler.java @@ -319,13 +319,14 @@ public class NavBarSwipeInteractionHandler extends BaseSwipeInteractionHandler i /** Animates to the given progress, where 0 is the current app and 1 is overview. */ private void animateToProgress(float progress, long duration) { + mIsGoingToHome = Float.compare(progress, 1) == 0; ObjectAnimator anim = mCurrentShift.animateToValue(progress).setDuration(duration); anim.setInterpolator(Interpolators.SCROLL); anim.addListener(new AnimationSuccessListener() { @Override public void onAnimationSuccess(Animator animator) { - mStateCallback.setState((Float.compare(mCurrentShift.value, 0) == 0) - ? STATE_SCALED_SNAPSHOT_APP : STATE_SCALED_SNAPSHOT_RECENTS); + mStateCallback.setState(mIsGoingToHome + ? STATE_SCALED_SNAPSHOT_RECENTS : STATE_SCALED_SNAPSHOT_APP); } }); anim.start(); diff --git a/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java b/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java index 9b2e82264..c96f6d73a 100644 --- a/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java +++ b/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java @@ -25,9 +25,9 @@ import static android.view.MotionEvent.INVALID_POINTER_ID; import static com.android.quickstep.RemoteRunnable.executeSafely; import static com.android.quickstep.TouchInteractionService.DEBUG_SHOW_OVERVIEW_BUTTON; import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_BACK; -import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_NONE; import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_OVERVIEW; +import android.annotation.TargetApi; import android.app.ActivityManager.RunningTaskInfo; import android.app.ActivityOptions; import android.content.Context; @@ -39,6 +39,7 @@ import android.graphics.Color; import android.graphics.Point; import android.graphics.PointF; import android.graphics.Rect; +import android.os.Build; import android.os.Bundle; import android.os.Looper; import android.util.Log; @@ -70,6 +71,7 @@ import java.util.concurrent.TimeUnit; /** * Touch consumer for handling events originating from an activity other than Launcher */ +@TargetApi(Build.VERSION_CODES.P) public class OtherActivityTouchConsumer extends ContextWrapper implements TouchConsumer { private static final String TAG = "ActivityTouchConsumer"; @@ -97,16 +99,17 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC private VelocityTracker mVelocityTracker; private MotionEventQueue mEventQueue; + private boolean mIsGoingToHome; public OtherActivityTouchConsumer(Context base, RunningTaskInfo runningTaskInfo, RecentsModel recentsModel, Intent homeIntent, ISystemUiProxy systemUiProxy, MainThreadExecutor mainThreadExecutor, Choreographer backgroundThreadChoreographer, - @HitTarget int downHitTarget) { + @HitTarget int downHitTarget, VelocityTracker velocityTracker) { super(base); mRunningTask = runningTaskInfo; mRecentsModel = recentsModel; mHomeIntent = homeIntent; - mVelocityTracker = VelocityTracker.obtain(); + mVelocityTracker = velocityTracker; mISystemUiProxy = systemUiProxy; mMainThreadExecutor = mainThreadExecutor; mBackgroundThreadChoreographer = backgroundThreadChoreographer; @@ -374,6 +377,7 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC if (mInteractionHandler != null) { final BaseSwipeInteractionHandler handler = mInteractionHandler; mInteractionHandler = null; + mIsGoingToHome = handler.mIsGoingToHome; mMainThreadExecutor.execute(handler::reset); } } @@ -428,4 +432,15 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC } } } + + @Override + public boolean forceToLauncherConsumer() { + return mIsGoingToHome; + } + + @Override + public boolean deferNextEventToMainThread() { + // TODO: Consider also check if the eventQueue is using mainThread of not. + return mInteractionHandler != null; + } } diff --git a/quickstep/src/com/android/quickstep/TouchConsumer.java b/quickstep/src/com/android/quickstep/TouchConsumer.java index f35f6a6f4..768fbda73 100644 --- a/quickstep/src/com/android/quickstep/TouchConsumer.java +++ b/quickstep/src/com/android/quickstep/TouchConsumer.java @@ -21,8 +21,6 @@ import android.support.annotation.IntDef; import android.view.Choreographer; import android.view.MotionEvent; -import com.android.systemui.shared.system.NavigationBarCompat.HitTarget; - import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.function.Consumer; @@ -64,4 +62,14 @@ public interface TouchConsumer extends Consumer<MotionEvent> { default Choreographer getIntrimChoreographer(MotionEventQueue queue) { return null; } + + default void deferInit() { } + + default boolean deferNextEventToMainThread() { + return false; + } + + default boolean forceToLauncherConsumer() { + return false; + } } diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java index 12c21701c..5d0bec9c1 100644 --- a/quickstep/src/com/android/quickstep/TouchInteractionService.java +++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java @@ -39,6 +39,7 @@ import android.util.Log; import android.util.SparseArray; import android.view.Choreographer; import android.view.MotionEvent; +import android.view.VelocityTracker; import android.view.View; import android.view.ViewConfiguration; @@ -161,7 +162,6 @@ public class TouchInteractionService extends Service { private Choreographer mMainThreadChoreographer; private Choreographer mBackgroundThreadChoreographer; - private MotionEventQueue mNoOpEventQueue; @Override public void onCreate() { @@ -171,8 +171,7 @@ public class TouchInteractionService extends Service { mMainThreadExecutor = new MainThreadExecutor(); mOverviewCommandHelper = new OverviewCommandHelper(this); mMainThreadChoreographer = Choreographer.getInstance(); - mNoOpEventQueue = new MotionEventQueue(mMainThreadChoreographer, mNoOpTouchConsumer); - mEventQueue = mNoOpEventQueue; + mEventQueue = new MotionEventQueue(mMainThreadChoreographer, mNoOpTouchConsumer); sConnected = true; @@ -194,31 +193,45 @@ public class TouchInteractionService extends Service { } private void onBinderPreMotionEvent(@HitTarget int downHitTarget) { - RunningTaskInfo runningTaskInfo = mAM.getRunningTask(); - mEventQueue.reset(); + TouchConsumer oldConsumer = mEventQueue.getConsumer(); + if (oldConsumer.deferNextEventToMainThread()) { + mEventQueue = new MotionEventQueue(mMainThreadChoreographer, + new DeferredTouchConsumer((v) -> getCurrentTouchConsumer(downHitTarget, + oldConsumer.forceToLauncherConsumer(), v))); + mEventQueue.deferInit(); + } else { + mEventQueue = new MotionEventQueue( + mMainThreadChoreographer, getCurrentTouchConsumer(downHitTarget, false, null)); + } + } - if (runningTaskInfo == null) { - mEventQueue = mNoOpEventQueue; - } else if (runningTaskInfo.topActivity.equals(mOverviewCommandHelper.launcher)) { - mEventQueue = getLauncherEventQueue(); + private TouchConsumer getCurrentTouchConsumer( + @HitTarget int downHitTarget, boolean forceToLauncher, VelocityTracker tracker) { + RunningTaskInfo runningTaskInfo = mAM.getRunningTask(); + + if (runningTaskInfo == null && !forceToLauncher) { + return mNoOpTouchConsumer; + } else if (forceToLauncher || + runningTaskInfo.topActivity.equals(mOverviewCommandHelper.launcher)) { + return getLauncherConsumer(); } else { - mEventQueue = new MotionEventQueue(mMainThreadChoreographer, - new OtherActivityTouchConsumer(this, runningTaskInfo, mRecentsModel, + if (tracker == null) { + tracker = VelocityTracker.obtain(); + } + return new OtherActivityTouchConsumer(this, runningTaskInfo, mRecentsModel, mOverviewCommandHelper.homeIntent, mISystemUiProxy, mMainThreadExecutor, - mBackgroundThreadChoreographer, downHitTarget)); + mBackgroundThreadChoreographer, downHitTarget, tracker); } } - private MotionEventQueue getLauncherEventQueue() { + private TouchConsumer getLauncherConsumer() { Launcher launcher = (Launcher) LauncherAppState.getInstance(this).getModel().getCallback(); if (launcher == null) { - return mNoOpEventQueue; + return mNoOpTouchConsumer; } - View target = launcher.getDragLayer(); - return new MotionEventQueue(mMainThreadChoreographer, - new LauncherTouchConsumer(launcher, target)); + return new LauncherTouchConsumer(launcher, target); } private static class LauncherTouchConsumer implements TouchConsumer { diff --git a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java index bab8ef17a..7c242fa52 100644 --- a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java +++ b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java @@ -720,13 +720,14 @@ public class WindowTransformSwipeHandler extends BaseSwipeInteractionHandler { /** Animates to the given progress, where 0 is the current app and 1 is overview. */ private void animateToProgress(float progress, long duration) { + mIsGoingToHome = Float.compare(progress, 1) == 0; ObjectAnimator anim = mCurrentShift.animateToValue(progress).setDuration(duration); anim.setInterpolator(Interpolators.SCROLL); anim.addListener(new AnimationSuccessListener() { @Override public void onAnimationSuccess(Animator animator) { - setStateOnUiThread((Float.compare(mCurrentShift.value, 0) == 0) - ? STATE_SCALED_CONTROLLER_APP : STATE_SCALED_CONTROLLER_RECENTS); + setStateOnUiThread(mIsGoingToHome ? + STATE_SCALED_CONTROLLER_RECENTS : STATE_SCALED_CONTROLLER_APP); } }); anim.start(); @@ -747,7 +748,7 @@ public class WindowTransformSwipeHandler extends BaseSwipeInteractionHandler { } private void invalidateHandler() { - mCurrentShift.cancelAnimation(); + mCurrentShift.finishAnimation(); if (mGestureEndCallback != null) { mGestureEndCallback.run(); |