Merge "Move app => overview anim out of OverviewCommandHelper" into ub-launcher3-master

This commit is contained in:
TreeHugger Robot
2019-02-01 21:30:38 +00:00
committed by Android (Google) Code Review
2 changed files with 206 additions and 128 deletions
@@ -0,0 +1,180 @@
/*
* Copyright (C) 2019 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 static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
import static com.android.launcher3.anim.Interpolators.TOUCH_RESPONSE_INTERPOLATOR;
import static com.android.quickstep.TouchConsumer.INTERACTION_NORMAL;
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING;
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_OPENING;
import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.ValueAnimator;
import android.graphics.Rect;
import android.util.Log;
import android.view.View;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.quickstep.util.ClipAnimationHelper;
import com.android.quickstep.util.RemoteAnimationProvider;
import com.android.quickstep.util.RemoteAnimationTargetSet;
import com.android.quickstep.util.TransformedRect;
import com.android.quickstep.views.RecentsView;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat;
import com.android.systemui.shared.system.TransactionCompat;
/**
* Provider for the atomic remote window animation from the app to the overview.
*
* @param <T> activity that contains the overview
*/
final class AppToOverviewAnimationProvider<T extends BaseDraggingActivity> implements
RemoteAnimationProvider {
private static final long RECENTS_LAUNCH_DURATION = 250;
private static final String TAG = "AppToOverviewAnimationProvider";
private final ActivityControlHelper<T> mHelper;
// The id of the currently running task that is transitioning to overview.
private final int mTargetTaskId;
private T mActivity;
private RecentsView mRecentsView;
AppToOverviewAnimationProvider(ActivityControlHelper<T> helper, int targetTaskId) {
mHelper = helper;
mTargetTaskId = targetTaskId;
}
/**
* Callback for when the activity is ready/initialized.
*
* @param activity the activity that is ready
* @param wasVisible true if it was visible before
*/
boolean onActivityReady(T activity, Boolean wasVisible) {
activity.<RecentsView>getOverviewPanel().setCurrentTask(mTargetTaskId);
AbstractFloatingView.closeAllOpenViews(activity, wasVisible);
ActivityControlHelper.AnimationFactory factory =
mHelper.prepareRecentsUI(activity, wasVisible,
false /* animate activity */, (controller) -> {
controller.dispatchOnStart();
ValueAnimator anim = controller.getAnimationPlayer()
.setDuration(RECENTS_LAUNCH_DURATION);
anim.setInterpolator(FAST_OUT_SLOW_IN);
anim.start();
});
factory.onRemoteAnimationReceived(null);
factory.createActivityController(RECENTS_LAUNCH_DURATION, INTERACTION_NORMAL);
mActivity = activity;
mRecentsView = mActivity.getOverviewPanel();
return false;
}
/**
* Create remote window animation from the currently running app to the overview panel.
*
* @param targetCompats the target apps
* @return animation from app to overview
*/
@Override
public AnimatorSet createWindowAnimation(RemoteAnimationTargetCompat[] targetCompats) {
if (mRecentsView != null) {
mRecentsView.setRunningTaskIconScaledDown(true);
}
AnimatorSet anim = new AnimatorSet();
anim.addListener(new AnimationSuccessListener() {
@Override
public void onAnimationSuccess(Animator animator) {
if (mRecentsView != null) {
mRecentsView.animateUpRunningTaskIconScale();
}
}
});
if (mActivity == null) {
Log.e(TAG, "Animation created, before activity");
anim.play(ValueAnimator.ofInt(0, 1).setDuration(RECENTS_LAUNCH_DURATION));
return anim;
}
RemoteAnimationTargetSet targetSet =
new RemoteAnimationTargetSet(targetCompats, MODE_CLOSING);
// Use the top closing app to determine the insets for the animation
RemoteAnimationTargetCompat runningTaskTarget = targetSet.findTask(mTargetTaskId);
if (runningTaskTarget == null) {
Log.e(TAG, "No closing app");
anim.play(ValueAnimator.ofInt(0, 1).setDuration(RECENTS_LAUNCH_DURATION));
return anim;
}
final ClipAnimationHelper clipHelper = new ClipAnimationHelper(mActivity);
// At this point, the activity is already started and laid-out. Get the home-bounds
// relative to the screen using the rootView of the activity.
int loc[] = new int[2];
View rootView = mActivity.getRootView();
rootView.getLocationOnScreen(loc);
Rect homeBounds = new Rect(loc[0], loc[1],
loc[0] + rootView.getWidth(), loc[1] + rootView.getHeight());
clipHelper.updateSource(homeBounds, runningTaskTarget);
TransformedRect targetRect = new TransformedRect();
mHelper.getSwipeUpDestinationAndLength(mActivity.getDeviceProfile(), mActivity,
INTERACTION_NORMAL, targetRect);
clipHelper.updateTargetRect(targetRect);
clipHelper.prepareAnimation(false /* isOpening */);
ClipAnimationHelper.TransformParams params = new ClipAnimationHelper.TransformParams()
.setSyncTransactionApplier(new SyncRtSurfaceTransactionApplierCompat(rootView));
ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1);
valueAnimator.setDuration(RECENTS_LAUNCH_DURATION);
valueAnimator.setInterpolator(TOUCH_RESPONSE_INTERPOLATOR);
valueAnimator.addUpdateListener((v) -> {
params.setProgress((float) v.getAnimatedValue());
clipHelper.applyTransform(targetSet, params);
});
if (targetSet.isAnimatingHome()) {
// If we are animating home, fade in the opening targets
RemoteAnimationTargetSet openingSet =
new RemoteAnimationTargetSet(targetCompats, MODE_OPENING);
TransactionCompat transaction = new TransactionCompat();
valueAnimator.addUpdateListener((v) -> {
for (RemoteAnimationTargetCompat app : openingSet.apps) {
transaction.setAlpha(app.leash, (float) v.getAnimatedValue());
}
transaction.apply();
});
}
anim.play(valueAnimator);
return anim;
}
/**
* Get duration of animation from app to overview.
*
* @return duration of animation
*/
long getRecentsLaunchDuration() {
return RECENTS_LAUNCH_DURATION;
}
}
@@ -15,44 +15,25 @@
*/
package com.android.quickstep;
import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
import static com.android.launcher3.anim.Interpolators.TOUCH_RESPONSE_INTERPOLATOR;
import static com.android.quickstep.TouchConsumer.INTERACTION_NORMAL;
import static com.android.systemui.shared.system.ActivityManagerWrapper
.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING;
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_OPENING;
import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.ValueAnimator;
import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Rect;
import android.os.Build;
import android.os.SystemClock;
import android.util.Log;
import android.view.View;
import android.view.ViewConfiguration;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.MainThreadExecutor;
import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.logging.UserEventDispatcher;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.quickstep.ActivityControlHelper.ActivityInitListener;
import com.android.quickstep.ActivityControlHelper.AnimationFactory;
import com.android.quickstep.util.ClipAnimationHelper;
import com.android.quickstep.util.RemoteAnimationTargetSet;
import com.android.quickstep.util.TransformedRect;
import com.android.quickstep.views.RecentsView;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.LatencyTrackerCompat;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat;
import com.android.systemui.shared.system.TransactionCompat;
/**
* Helper class to handle various atomic commands for switching between Overview.
@@ -60,10 +41,6 @@ import com.android.systemui.shared.system.TransactionCompat;
@TargetApi(Build.VERSION_CODES.P)
public class OverviewCommandHelper {
private static final long RECENTS_LAUNCH_DURATION = 250;
private static final String TAG = "OverviewCommandHelper";
private final Context mContext;
private final ActivityManagerWrapper mAM;
private final RecentsModel mRecentsModel;
@@ -111,18 +88,17 @@ public class OverviewCommandHelper {
protected final ActivityControlHelper<T> mHelper;
private final long mCreateTime;
private final int mRunningTaskId;
private final AppToOverviewAnimationProvider<T> mAnimationProvider;
private ActivityInitListener mListener;
private T mActivity;
private RecentsView mRecentsView;
private final long mToggleClickedTime = SystemClock.uptimeMillis();
private boolean mUserEventLogged;
private ActivityInitListener mListener;
public RecentsActivityCommand() {
mHelper = mOverviewComponentObserver.getActivityControlHelper();
mCreateTime = SystemClock.elapsedRealtime();
mRunningTaskId = RecentsModel.getRunningTaskId();
mAnimationProvider =
new AppToOverviewAnimationProvider<>(mHelper, RecentsModel.getRunningTaskId());
// Preload the plan
mRecentsModel.getTasks(null);
@@ -133,16 +109,21 @@ public class OverviewCommandHelper {
long elapsedTime = mCreateTime - mLastToggleTime;
mLastToggleTime = mCreateTime;
if (!handleCommand(elapsedTime)) {
// Start overview
if (!mHelper.switchToRecentsIfVisible(true)) {
mListener = mHelper.createActivityInitListener(this::onActivityReady);
mListener.registerAndStartActivity(
mOverviewComponentObserver.getOverviewIntent(),
this::createWindowAnimation, mContext, mMainThreadExecutor.getHandler(),
RECENTS_LAUNCH_DURATION);
}
if (handleCommand(elapsedTime)) {
// Command already handled.
return;
}
if (mHelper.switchToRecentsIfVisible(true)) {
// If successfully switched, then return
return;
}
// Otherwise, start overview.
mListener = mHelper.createActivityInitListener(this::onActivityReady);
mListener.registerAndStartActivity(mOverviewComponentObserver.getOverviewIntent(),
this::createWindowAnimation, mContext, mMainThreadExecutor.getHandler(),
mAnimationProvider.getRecentsLaunchDuration());
}
protected boolean handleCommand(long elapsedTime) {
@@ -163,26 +144,14 @@ public class OverviewCommandHelper {
}
private boolean onActivityReady(T activity, Boolean wasVisible) {
activity.<RecentsView>getOverviewPanel().setCurrentTask(mRunningTaskId);
AbstractFloatingView.closeAllOpenViews(activity, wasVisible);
AnimationFactory factory = mHelper.prepareRecentsUI(activity, wasVisible,
false /* animate activity */, (controller) -> {
controller.dispatchOnStart();
ValueAnimator anim = controller.getAnimationPlayer()
.setDuration(RECENTS_LAUNCH_DURATION);
anim.setInterpolator(FAST_OUT_SLOW_IN);
anim.start();
});
factory.onRemoteAnimationReceived(null);
factory.createActivityController(RECENTS_LAUNCH_DURATION, INTERACTION_NORMAL);
mActivity = activity;
mRecentsView = mActivity.getOverviewPanel();
if (!mUserEventLogged) {
activity.getUserEventDispatcher().logActionCommand(Action.Command.RECENTS_BUTTON,
mHelper.getContainerType(), ContainerType.TASKSWITCHER);
activity.getUserEventDispatcher().logActionCommand(
LauncherLogProto.Action.Command.RECENTS_BUTTON,
mHelper.getContainerType(),
LauncherLogProto.ContainerType.TASKSWITCHER);
mUserEventLogged = true;
}
return false;
return mAnimationProvider.onActivityReady(activity, wasVisible);
}
private AnimatorSet createWindowAnimation(RemoteAnimationTargetCompat[] targetCompats) {
@@ -191,80 +160,9 @@ public class OverviewCommandHelper {
(int) (SystemClock.uptimeMillis() - mToggleClickedTime));
}
if (mListener != null) {
mListener.unregister();
}
if (mRecentsView != null) {
mRecentsView.setRunningTaskIconScaledDown(true);
}
AnimatorSet anim = new AnimatorSet();
anim.addListener(new AnimationSuccessListener() {
@Override
public void onAnimationSuccess(Animator animator) {
if (mRecentsView != null) {
mRecentsView.animateUpRunningTaskIconScale();
}
}
});
if (mActivity == null) {
Log.e(TAG, "Animation created, before activity");
anim.play(ValueAnimator.ofInt(0, 1).setDuration(100));
return anim;
}
mListener.unregister();
RemoteAnimationTargetSet targetSet =
new RemoteAnimationTargetSet(targetCompats, MODE_CLOSING);
// Use the top closing app to determine the insets for the animation
RemoteAnimationTargetCompat runningTaskTarget = targetSet.findTask(mRunningTaskId);
if (runningTaskTarget == null) {
Log.e(TAG, "No closing app");
anim.play(ValueAnimator.ofInt(0, 1).setDuration(100));
return anim;
}
final ClipAnimationHelper clipHelper = new ClipAnimationHelper(mActivity);
// At this point, the activity is already started and laid-out. Get the home-bounds
// relative to the screen using the rootView of the activity.
int loc[] = new int[2];
View rootView = mActivity.getRootView();
rootView.getLocationOnScreen(loc);
Rect homeBounds = new Rect(loc[0], loc[1],
loc[0] + rootView.getWidth(), loc[1] + rootView.getHeight());
clipHelper.updateSource(homeBounds, runningTaskTarget);
TransformedRect targetRect = new TransformedRect();
mHelper.getSwipeUpDestinationAndLength(mActivity.getDeviceProfile(), mActivity,
INTERACTION_NORMAL, targetRect);
clipHelper.updateTargetRect(targetRect);
clipHelper.prepareAnimation(false /* isOpening */);
ClipAnimationHelper.TransformParams params = new ClipAnimationHelper.TransformParams()
.setSyncTransactionApplier(new SyncRtSurfaceTransactionApplierCompat(rootView));
ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1);
valueAnimator.setDuration(RECENTS_LAUNCH_DURATION);
valueAnimator.setInterpolator(TOUCH_RESPONSE_INTERPOLATOR);
valueAnimator.addUpdateListener((v) -> {
params.setProgress((float) v.getAnimatedValue());
clipHelper.applyTransform(targetSet, params);
});
if (targetSet.isAnimatingHome()) {
// If we are animating home, fade in the opening targets
RemoteAnimationTargetSet openingSet =
new RemoteAnimationTargetSet(targetCompats, MODE_OPENING);
TransactionCompat transaction = new TransactionCompat();
valueAnimator.addUpdateListener((v) -> {
for (RemoteAnimationTargetCompat app : openingSet.apps) {
transaction.setAlpha(app.leash, (float) v.getAnimatedValue());
}
transaction.apply();
});
}
anim.play(valueAnimator);
return anim;
return mAnimationProvider.createWindowAnimation(targetCompats);
}
}
}