[automerger] Various quickscrub fixes am: 9bb8ffb5e3 am: c7bf48338c

Change-Id: I2ed6d0318a36148bf177108d3d2c21506644d33f
This commit is contained in:
Android Build Merger (Role) 2018-05-29 19:17:28 +00:00
commit 1d9a44748a
10 changed files with 179 additions and 62 deletions

View File

@ -46,6 +46,7 @@ import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherInitListener;
import com.android.launcher3.LauncherState;
import com.android.launcher3.R;
import com.android.launcher3.allapps.AllAppsTransitionController;
import com.android.launcher3.allapps.DiscoveryBounce;
import com.android.launcher3.anim.AnimatorPlaybackController;
@ -82,7 +83,8 @@ public interface ActivityControlHelper<T extends BaseDraggingActivity> {
void onQuickInteractionStart(T activity, @Nullable RunningTaskInfo taskInfo,
boolean activityVisible);
float getTranslationYForQuickScrub(T activity);
float getTranslationYForQuickScrub(TransformedRect targetRect, DeviceProfile dp,
Context context);
void executeOnWindowAvailable(T activity, Runnable action);
@ -151,10 +153,15 @@ public interface ActivityControlHelper<T extends BaseDraggingActivity> {
}
@Override
public float getTranslationYForQuickScrub(Launcher activity) {
LauncherRecentsView recentsView = activity.getOverviewPanel();
return recentsView.computeTranslationYForFactor(
FastOverviewState.OVERVIEW_TRANSLATION_FACTOR);
public float getTranslationYForQuickScrub(TransformedRect targetRect, DeviceProfile dp,
Context context) {
// The padding calculations are exactly same as that of RecentsView.setInsets
int topMargin = context.getResources()
.getDimensionPixelSize(R.dimen.task_thumbnail_top_margin);
int paddingTop = targetRect.rect.top - topMargin - dp.getInsets().top;
int paddingBottom = dp.availableHeightPx + dp.getInsets().top - targetRect.rect.bottom;
return FastOverviewState.OVERVIEW_TRANSLATION_FACTOR * (paddingBottom - paddingTop);
}
@Override
@ -380,7 +387,8 @@ public interface ActivityControlHelper<T extends BaseDraggingActivity> {
}
@Override
public float getTranslationYForQuickScrub(RecentsActivity activity) {
public float getTranslationYForQuickScrub(TransformedRect targetRect, DeviceProfile dp,
Context context) {
return 0;
}

View File

@ -63,6 +63,16 @@ public class DeferredTouchConsumer implements TouchConsumer {
mTarget.onQuickScrubProgress(progress);
}
@Override
public void onQuickStep(MotionEvent ev) {
mTarget.onQuickStep(ev);
}
@Override
public void onCommand(int command) {
mTarget.onCommand(command);
}
@Override
public void preProcessMotionEvent(MotionEvent ev) {
mVelocityTracker.addMovement(ev);
@ -92,6 +102,11 @@ public class DeferredTouchConsumer implements TouchConsumer {
return target == null ? true : target.deferNextEventToMainThread();
}
@Override
public void onShowOverviewFromAltTab() {
mTarget.onShowOverviewFromAltTab();
}
public interface DeferredTouchProvider {
TouchConsumer createTouchConsumer(VelocityTracker tracker);

View File

@ -55,6 +55,8 @@ public class MotionEventQueue {
ACTION_VIRTUAL | (6 << ACTION_POINTER_INDEX_SHIFT);
private static final int ACTION_QUICK_STEP =
ACTION_VIRTUAL | (7 << ACTION_POINTER_INDEX_SHIFT);
private static final int ACTION_COMMAND =
ACTION_VIRTUAL | (8 << ACTION_POINTER_INDEX_SHIFT);
private final EventArray mEmptyArray = new EventArray();
private final Object mExecutionLock = new Object();
@ -165,6 +167,9 @@ public class MotionEventQueue {
case ACTION_QUICK_STEP:
mConsumer.onQuickStep(event);
break;
case ACTION_COMMAND:
mConsumer.onCommand(event.getSource());
break;
default:
Log.e(TAG, "Invalid virtual event: " + event.getAction());
}
@ -222,6 +227,12 @@ public class MotionEventQueue {
queueVirtualAction(ACTION_DEFER_INIT, 0);
}
public void onCommand(int command) {
MotionEvent ev = MotionEvent.obtain(0, 0, ACTION_COMMAND, 0, 0, 0);
ev.setSource(command);
queueNoPreProcess(ev);
}
public TouchConsumer getConsumer() {
return mConsumer;
}

View File

@ -37,6 +37,7 @@ import android.os.Build;
import android.os.Bundle;
import android.os.Looper;
import android.os.SystemClock;
import android.util.SparseArray;
import android.view.Choreographer;
import android.view.Display;
import android.view.MotionEvent;
@ -69,6 +70,7 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC
private static final long LAUNCHER_DRAW_TIMEOUT_MS = 150;
private final SparseArray<RecentsAnimationState> mAnimationStates = new SparseArray<>();
private final RunningTaskInfo mRunningTask;
private final RecentsModel mRecentsModel;
private final Intent mHomeIntent;
@ -212,8 +214,9 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC
private void startTouchTrackingForWindowAnimation(long touchTimeMs) {
// Create the shared handler
RecentsAnimationState animationState = new RecentsAnimationState();
final WindowTransformSwipeHandler handler = new WindowTransformSwipeHandler(
mRunningTask, this, touchTimeMs, mActivityControlHelper);
animationState.id, mRunningTask, this, touchTimeMs, mActivityControlHelper);
// Preload the plan
mRecentsModel.loadTasks(mRunningTask.id, null);
@ -237,31 +240,7 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC
public void onHandleAssistData(Bundle bundle) {
mRecentsModel.preloadAssistData(mRunningTask.id, bundle);
}
},
new RecentsAnimationListener() {
public void onAnimationStart(
RecentsAnimationControllerCompat controller,
RemoteAnimationTargetCompat[] apps, Rect homeContentInsets,
Rect minimizedHomeBounds) {
if (mInteractionHandler == handler) {
TraceHelper.partitionSection("RecentsController", "Received");
handler.onRecentsAnimationStart(controller,
new RemoteAnimationTargetSet(apps, MODE_CLOSING),
homeContentInsets, minimizedHomeBounds);
} else {
TraceHelper.endSection("RecentsController", "Finishing no handler");
controller.finish(false /* toHome */);
}
}
public void onAnimationCanceled() {
TraceHelper.endSection("RecentsController",
"Cancelled: " + mInteractionHandler);
if (mInteractionHandler == handler) {
handler.onRecentsAnimationCanceled();
}
}
}, null, null);
}, animationState, null, null);
if (Looper.myLooper() != Looper.getMainLooper()) {
startActivity.run();
@ -277,6 +256,14 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC
}
}
@Override
public void onCommand(int command) {
RecentsAnimationState state = mAnimationStates.get(command);
if (state != null) {
state.execute();
}
}
/**
* Called when the gesture has ended. Does not correlate to the completion of the interaction as
* the animation can still be running.
@ -398,4 +385,55 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC
// TODO: Consider also check if the eventQueue is using mainThread of not.
return mInteractionHandler != null;
}
private class RecentsAnimationState implements RecentsAnimationListener {
private final int id;
private RecentsAnimationControllerCompat mController;
private RemoteAnimationTargetSet mTargets;
private Rect mHomeContentInsets;
private Rect mMinimizedHomeBounds;
private boolean mCancelled;
public RecentsAnimationState() {
id = mAnimationStates.size();
mAnimationStates.put(id, this);
}
@Override
public void onAnimationStart(
RecentsAnimationControllerCompat controller,
RemoteAnimationTargetCompat[] apps, Rect homeContentInsets,
Rect minimizedHomeBounds) {
mController = controller;
mTargets = new RemoteAnimationTargetSet(apps, MODE_CLOSING);
mHomeContentInsets = homeContentInsets;
mMinimizedHomeBounds = minimizedHomeBounds;
mEventQueue.onCommand(id);
}
@Override
public void onAnimationCanceled() {
mCancelled = true;
mEventQueue.onCommand(id);
}
public void execute() {
if (mInteractionHandler == null || mInteractionHandler.id != id) {
if (!mCancelled && mController != null) {
TraceHelper.endSection("RecentsController", "Finishing no handler");
mController.finish(false /* toHome */);
}
} else if (mCancelled) {
TraceHelper.endSection("RecentsController",
"Cancelled: " + mInteractionHandler);
mInteractionHandler.onRecentsAnimationCanceled();
} else {
TraceHelper.partitionSection("RecentsController", "Received");
mInteractionHandler.onRecentsAnimationStart(mController, mTargets,
mHomeContentInsets, mMinimizedHomeBounds);
}
}
}
}

View File

@ -20,6 +20,8 @@ import com.android.launcher3.util.TraceHelper;
import com.android.launcher3.util.UiThreadHelper;
import com.android.quickstep.util.RemoteAnimationTargetSet;
import com.android.systemui.shared.system.RecentsAnimationControllerCompat;
import java.util.ArrayList;
import java.util.concurrent.ExecutorService;
/**
@ -27,6 +29,10 @@ import java.util.concurrent.ExecutorService;
*/
public class 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<Runnable> mCallbacks = new ArrayList<>();
public RemoteAnimationTargetSet targetSet;
private RecentsAnimationControllerCompat mController;
@ -46,6 +52,21 @@ public class RecentsAnimationWrapper {
if (mInputConsumerEnabled) {
enableInputConsumer();
}
if (!mCallbacks.isEmpty()) {
for (Runnable action : new ArrayList<>(mCallbacks)) {
action.run();
}
mCallbacks.clear();
}
}
public synchronized void runOnInit(Runnable action) {
if (targetSet == null) {
mCallbacks.add(action);
} else {
action.run();
}
}
/**

View File

@ -48,6 +48,8 @@ public interface TouchConsumer extends Consumer<MotionEvent> {
default void onQuickStep(MotionEvent ev) { }
default void onCommand(int command) { }
/**
* Called on the binder thread to allow the consumer to process the motion event before it is
* posted on a handler thread.

View File

@ -29,6 +29,7 @@ import android.animation.ObjectAnimator;
import android.annotation.TargetApi;
import android.app.ActivityManager.RunningTaskInfo;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Point;
import android.graphics.Rect;
@ -36,6 +37,7 @@ import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.os.SystemClock;
import android.os.UserHandle;
import android.support.annotation.AnyThread;
import android.support.annotation.UiThread;
import android.support.annotation.WorkerThread;
@ -51,6 +53,7 @@ import com.android.launcher3.DeviceProfile;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.logging.UserEventDispatcher;
@ -65,11 +68,12 @@ import com.android.quickstep.ActivityControlHelper.AnimationFactory;
import com.android.quickstep.ActivityControlHelper.LayoutListener;
import com.android.quickstep.TouchConsumer.InteractionType;
import com.android.quickstep.util.ClipAnimationHelper;
import com.android.quickstep.util.TransformedRect;
import com.android.quickstep.util.RemoteAnimationTargetSet;
import com.android.quickstep.util.TransformedRect;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
import com.android.systemui.shared.recents.model.ThumbnailData;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.InputConsumerController;
import com.android.systemui.shared.system.LatencyTrackerCompat;
import com.android.systemui.shared.system.RecentsAnimationControllerCompat;
@ -167,6 +171,12 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> {
private final Handler mMainThreadHandler = new Handler(Looper.getMainLooper());
// An increasing identifier per single instance of OtherActivityTouchConsumer. Generally one
// instance of OtherActivityTouchConsumer will only have one swipe handle, but sometimes we can
// end up with multiple handlers if we get recents command in the middle of a swipe gesture.
// This is used to match the corresponding activity manager callbacks in
// OtherActivityTouchConsumer
public final int id;
private final Context mContext;
private final ActivityControlHelper<T> mActivityControlHelper;
private final ActivityInitListener mActivityInitListener;
@ -199,6 +209,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> {
InputConsumerController.getRecentsAnimationInputConsumer();
private final RecentsAnimationWrapper mRecentsAnimationWrapper = new RecentsAnimationWrapper();
private final long mTouchTimeMs;
private long mLauncherFrameDrawnTime;
@ -207,8 +218,9 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> {
private float mLongSwipeDisplacement = 0;
private LongSwipeHelper mLongSwipeController;
WindowTransformSwipeHandler(RunningTaskInfo runningTaskInfo, Context context, long touchTimeMs,
ActivityControlHelper<T> controller) {
WindowTransformSwipeHandler(int id, RunningTaskInfo runningTaskInfo, Context context,
long touchTimeMs, ActivityControlHelper<T> controller) {
this.id = id;
mContext = context;
mRunningTaskInfo = runningTaskInfo;
mRunningTaskId = runningTaskInfo.id;
@ -453,6 +465,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> {
"Can't change interaction type to " + interactionType);
}
mInteractionType = interactionType;
mRecentsAnimationWrapper.runOnInit(this::shiftAnimationDestinationForQuickscrub);
setStateOnUiThread(STATE_QUICK_SCRUB_START | STATE_GESTURE_COMPLETED);
@ -460,6 +473,34 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> {
animateToProgress(1f, QUICK_SCRUB_FROM_APP_START_DURATION, LINEAR);
}
private void shiftAnimationDestinationForQuickscrub() {
TransformedRect tempRect = new TransformedRect();
mActivityControlHelper
.getSwipeUpDestinationAndLength(mDp, mContext, mInteractionType, tempRect);
mClipAnimationHelper.updateTargetRect(tempRect);
float offsetY =
mActivityControlHelper.getTranslationYForQuickScrub(tempRect, mDp, mContext);
float scale, offsetX;
Resources res = mContext.getResources();
if (ActivityManagerWrapper.getInstance().getRecentTasks(2, UserHandle.myUserId()).size()
< 2) {
// There are not enough tasks, we don't need to shift
offsetX = 0;
scale = 1;
} else {
offsetX = res.getDimensionPixelSize(R.dimen.recents_page_spacing)
+ tempRect.rect.width();
float distanceToReachEdge = mDp.widthPx / 2 + tempRect.rect.width() / 2 +
res.getDimensionPixelSize(R.dimen.recents_page_spacing);
float interpolation = Math.min(1, offsetX / distanceToReachEdge);
scale = TaskView.getCurveScaleForInterpolation(interpolation);
}
mClipAnimationHelper.offsetTarget(scale, Utilities.isRtl(res) ? -offsetX : offsetX, offsetY,
QuickScrubController.QUICK_SCRUB_START_INTERPOLATOR);
}
@WorkerThread
public void updateDisplacement(float displacement) {
// We are moving in the negative x/y direction
@ -658,7 +699,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> {
: STATE_SCALED_CONTROLLER_APP);
}
});
anim.start();
mRecentsAnimationWrapper.runOnInit(anim::start);
}
@UiThread
@ -786,30 +827,6 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> {
// Inform the last progress in case we skipped before.
mQuickScrubController.onQuickScrubProgress(mCurrentQuickScrubProgress);
// Make sure the window follows the first task if it moves, e.g. during quick scrub.
TaskView firstTask = mRecentsView.getPageAt(0);
// The first task may be null if we are swiping up from a task that does not
// appear in the list (i.e. the assistant)
if (firstTask != null) {
int scrollForFirstTask = mRecentsView.getScrollForPage(0);
int scrollForSecondTask = mRecentsView.getChildCount() > 1
? mRecentsView.getScrollForPage(1) : scrollForFirstTask;
float offsetFromFirstTask = scrollForFirstTask - scrollForSecondTask;
TransformedRect tempRect = new TransformedRect();
mActivityControlHelper
.getSwipeUpDestinationAndLength(mDp, mContext, mInteractionType, tempRect);
float distanceToReachEdge = mDp.widthPx / 2 + tempRect.rect.width() / 2 +
mContext.getResources().getDimensionPixelSize(R.dimen.recents_page_spacing);
float interpolation = Math.min(1,
Math.abs(offsetFromFirstTask) / distanceToReachEdge);
mClipAnimationHelper.offsetTarget(
firstTask.getCurveScaleForInterpolation(interpolation), offsetFromFirstTask,
mActivityControlHelper.getTranslationYForQuickScrub(mActivity),
QuickScrubController.QUICK_SCRUB_START_INTERPOLATOR);
}
}
private void onFinishedTransitionToQuickScrub() {

View File

@ -507,6 +507,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
DeviceProfile dp = mActivity.getDeviceProfile();
getTaskSize(dp, mTempRect);
// Keep this logic in sync with ActivityControlHelper.getTranslationYForQuickScrub.
mTempRect.top -= mTaskTopMargin;
setPadding(mTempRect.left - mInsets.left, mTempRect.top - mInsets.top,
dp.availableWidthPx + mInsets.left - mTempRect.right,

View File

@ -250,12 +250,12 @@ public class TaskView extends FrameLayout implements TaskCallbacks, PageCallback
setPivotY(mSnapshotView.getTop() + mSnapshotView.getHeight() * 0.5f);
}
public float getCurveScaleForInterpolation(float linearInterpolation) {
public static float getCurveScaleForInterpolation(float linearInterpolation) {
float curveInterpolation = CURVE_INTERPOLATOR.getInterpolation(linearInterpolation);
return getCurveScaleForCurveInterpolation(curveInterpolation);
}
private float getCurveScaleForCurveInterpolation(float curveInterpolation) {
private static float getCurveScaleForCurveInterpolation(float curveInterpolation) {
return 1 - curveInterpolation * EDGE_SCALE_DOWN_FACTOR;
}

View File

@ -1450,6 +1450,10 @@ public abstract class PagedView<T extends View & PageIndicator> extends ViewGrou
protected boolean snapToPage(int whichPage, int delta, int duration, boolean immediate,
TimeInterpolator interpolator) {
if (mFirstLayout) {
setCurrentPage(whichPage);
return false;
}
if (FeatureFlags.IS_DOGFOOD_BUILD) {
duration *= Settings.System.getFloat(getContext().getContentResolver(),