Merge "Fixing task open animation in split screen mode" into ub-launcher3-edmonton

This commit is contained in:
android-build-team Robot 2018-04-30 21:27:38 +00:00 committed by Android (Google) Code Review
commit 6dcf142f61
9 changed files with 117 additions and 210 deletions

View File

@ -64,6 +64,7 @@ import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.dragndrop.DragLayer;
import com.android.launcher3.graphics.DrawableFactory;
import com.android.launcher3.shortcuts.DeepShortcutView;
import com.android.quickstep.util.ClipAnimationHelper;
import com.android.quickstep.util.MultiValueUpdateListener;
import com.android.quickstep.util.RemoteAnimationProvider;
import com.android.quickstep.views.RecentsView;
@ -233,12 +234,16 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag
return false;
}
ClipAnimationHelper helper = new ClipAnimationHelper();
target.play(getRecentsWindowAnimator(taskView, skipLauncherChanges, targets, helper)
.setDuration(RECENTS_LAUNCH_DURATION));
Animator childStateAnimation = null;
// Found a visible recents task that matches the opening app, lets launch the app from there
Animator launcherAnim;
final AnimatorListenerAdapter windowAnimEndListener;
if (launcherClosing) {
launcherAnim = recentsView.createAdjacentPageAnimForTaskLaunch(taskView);
launcherAnim = recentsView.createAdjacentPageAnimForTaskLaunch(taskView, helper);
launcherAnim.setInterpolator(Interpolators.TOUCH_RESPONSE_INTERPOLATOR);
launcherAnim.setDuration(RECENTS_LAUNCH_DURATION);
@ -258,9 +263,6 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag
}
};
}
target.play(getRecentsWindowAnimator(taskView, skipLauncherChanges, targets)
.setDuration(RECENTS_LAUNCH_DURATION));
target.play(launcherAnim);
// Set the current animation first, before adding windowAnimEndListener. Setting current

View File

@ -51,6 +51,7 @@ import com.android.launcher3.util.Themes;
import com.android.launcher3.views.BaseDragLayer;
import com.android.quickstep.fallback.FallbackRecentsView;
import com.android.quickstep.fallback.RecentsRootView;
import com.android.quickstep.util.ClipAnimationHelper;
import com.android.quickstep.views.RecentsViewContainer;
import com.android.quickstep.views.TaskView;
import com.android.systemui.shared.system.ActivityOptionsCompat;
@ -193,13 +194,14 @@ public class RecentsActivity extends BaseDraggingActivity {
RemoteAnimationTargetCompat[] targets) {
AnimatorSet target = new AnimatorSet();
boolean activityClosing = taskIsATargetWithMode(targets, getTaskId(), MODE_CLOSING);
target.play(getRecentsWindowAnimator(taskView, !activityClosing, targets)
ClipAnimationHelper helper = new ClipAnimationHelper();
target.play(getRecentsWindowAnimator(taskView, !activityClosing, targets, helper)
.setDuration(RECENTS_LAUNCH_DURATION));
// Found a visible recents task that matches the opening app, lets launch the app from there
if (activityClosing) {
Animator adjacentAnimation = mFallbackRecentsView
.createAdjacentPageAnimForTaskLaunch(taskView);
.createAdjacentPageAnimForTaskLaunch(taskView, helper);
adjacentAnimation.setInterpolator(Interpolators.TOUCH_RESPONSE_INTERPOLATOR);
adjacentAnimation.setDuration(RECENTS_LAUNCH_DURATION);
adjacentAnimation.addListener(new AnimatorListenerAdapter() {

View File

@ -1,117 +0,0 @@
/*
* 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.graphics.Rect;
import com.android.launcher3.Utilities;
/**
* Helper class to interpolate the animation between a task view representation and an actual
* window.
*/
public class RecentsAnimationInterpolator {
public static class TaskWindowBounds {
public float taskScale = 1f;
public float taskX = 0f;
public float taskY = 0f;
public float winScale = 1f;
public float winX = 0f;
public float winY = 0f;
public Rect winCrop = new Rect();
@Override
public String toString() {
return "taskScale=" + taskScale + " taskX=" + taskX + " taskY=" + taskY
+ " winScale=" + winScale + " winX=" + winX + " winY=" + winY
+ " winCrop=" + winCrop;
}
}
private TaskWindowBounds mTmpTaskWindowBounds = new TaskWindowBounds();
private Rect mTmpInsets = new Rect();
private Rect mWindow;
private Rect mInsetWindow;
private Rect mInsets;
private Rect mTask;
private Rect mTaskInsets;
private Rect mThumbnail;
private float mInitialTaskScale;
private float mInitialTaskTranslationX;
private float mFinalTaskScale;
private Rect mScaledTask;
private Rect mTargetTask;
private Rect mSrcWindow;
public RecentsAnimationInterpolator(Rect window, Rect insets, Rect task, Rect taskInsets,
float taskScale, float taskTranslationX) {
mWindow = window;
mInsets = insets;
mTask = task;
mTaskInsets = taskInsets;
mInsetWindow = new Rect(window);
Utilities.insetRect(mInsetWindow, insets);
mThumbnail = new Rect(task);
Utilities.insetRect(mThumbnail, taskInsets);
mInitialTaskScale = taskScale;
mInitialTaskTranslationX = taskTranslationX;
mFinalTaskScale = (float) mInsetWindow.width() / mThumbnail.width();
mScaledTask = new Rect(task);
Utilities.scaleRectAboutCenter(mScaledTask, mFinalTaskScale);
Rect finalScaledTaskInsets = new Rect(taskInsets);
Utilities.scaleRect(finalScaledTaskInsets, mFinalTaskScale);
mTargetTask = new Rect(mInsetWindow);
mTargetTask.offsetTo(window.left + insets.left - finalScaledTaskInsets.left,
window.top + insets.top - finalScaledTaskInsets.top);
float initialWinScale = 1f / mFinalTaskScale;
Rect scaledWindow = new Rect(mInsetWindow);
Utilities.scaleRectAboutCenter(scaledWindow, initialWinScale);
Rect scaledInsets = new Rect(insets);
Utilities.scaleRect(scaledInsets, initialWinScale);
mSrcWindow = new Rect(scaledWindow);
mSrcWindow.offsetTo(mThumbnail.left - scaledInsets.left,
mThumbnail.top - scaledInsets.top);
}
public TaskWindowBounds interpolate(float t) {
mTmpTaskWindowBounds.taskScale = Utilities.mapRange(t,
mInitialTaskScale, mFinalTaskScale);
mTmpTaskWindowBounds.taskX = Utilities.mapRange(t,
mInitialTaskTranslationX, mTargetTask.left - mScaledTask.left);
mTmpTaskWindowBounds.taskY = Utilities.mapRange(t,
0, mTargetTask.top - mScaledTask.top);
float taskScale = Utilities.mapRange(t, 1, mFinalTaskScale);
mTmpTaskWindowBounds.winScale = taskScale / mFinalTaskScale;
mTmpTaskWindowBounds.winX = Utilities.mapRange(t,
mSrcWindow.left, 0);
mTmpTaskWindowBounds.winY = Utilities.mapRange(t,
mSrcWindow.top, 0);
mTmpInsets.set(mInsets);
Utilities.scaleRect(mTmpInsets, (1f - t));
mTmpTaskWindowBounds.winCrop.set(mWindow);
Utilities.insetRect(mTmpTaskWindowBounds.winCrop, mTmpInsets);
return mTmpTaskWindowBounds;
}
}

View File

@ -27,8 +27,7 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.RectF;
import android.os.UserHandle;
import android.util.Log;
import android.view.Surface;
@ -36,17 +35,17 @@ import android.view.View;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.ItemInfo;
import com.android.launcher3.Utilities;
import com.android.launcher3.compat.LauncherAppsCompat;
import com.android.launcher3.compat.UserManagerCompat;
import com.android.launcher3.util.ComponentKey;
import com.android.quickstep.RecentsAnimationInterpolator.TaskWindowBounds;
import com.android.quickstep.util.ClipAnimationHelper;
import com.android.quickstep.util.MultiValueUpdateListener;
import com.android.quickstep.util.RemoteAnimationProvider;
import com.android.quickstep.util.RemoteAnimationTargetSet;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
import com.android.systemui.shared.system.TransactionCompat;
/**
* Contains helpful methods for retrieving data from {@link Task}s.
@ -136,74 +135,64 @@ public class TaskUtils {
return taskView;
}
/**
* @return Animator that controls the window of the opening targets for the recents launch
* animation.
*/
public static ValueAnimator getRecentsWindowAnimator(TaskView v, boolean skipViewChanges,
RemoteAnimationTargetCompat[] targets) {
final RecentsAnimationInterpolator recentsInterpolator = v.getRecentsInterpolator();
Rect crop = new Rect();
Matrix matrix = new Matrix();
ValueAnimator appAnimator = ValueAnimator.ofFloat(0, 1);
RemoteAnimationTargetCompat[] targets, final ClipAnimationHelper inOutHelper) {
final ValueAnimator appAnimator = ValueAnimator.ofFloat(0, 1);
appAnimator.setInterpolator(TOUCH_RESPONSE_INTERPOLATOR);
appAnimator.addUpdateListener(new MultiValueUpdateListener() {
// Defer fading out the view until after the app window gets faded in
FloatProp mViewAlpha = new FloatProp(1f, 0f, 75, 75, LINEAR);
FloatProp mTaskAlpha = new FloatProp(0f, 1f, 0, 75, LINEAR);
final FloatProp mViewAlpha = new FloatProp(1f, 0f, 75, 75, LINEAR);
final FloatProp mTaskAlpha = new FloatProp(0f, 1f, 0, 75, LINEAR);
boolean isFirstFrame = true;
final RemoteAnimationTargetSet mTargetSet;
final RectF mThumbnailRect;
private Surface mSurface;
private long mFrameNumber;
{
mTargetSet = new RemoteAnimationTargetSet(targets, MODE_OPENING);
inOutHelper.setTaskTransformCallback((t, app) -> {
t.setAlpha(app.leash, mTaskAlpha.value);
if (!skipViewChanges) {
t.deferTransactionUntil(app.leash, mSurface, mFrameNumber);
}
});
inOutHelper.prepareAnimation(true /* isOpening */);
inOutHelper.fromTaskThumbnailView(v.getThumbnail(), (RecentsView) v.getParent(),
mTargetSet.apps.length == 0 ? null : mTargetSet.apps[0]);
mThumbnailRect = new RectF(inOutHelper.getTargetRect());
mThumbnailRect.offset(-v.getTranslationX(), -v.getTranslationY());
Utilities.scaleRectFAboutCenter(mThumbnailRect, 1 / v.getScaleX());
}
@Override
public void onUpdate(float percent) {
final Surface surface = getSurface(v);
final long frameNumber = surface != null ? getNextFrameNumber(surface) : -1;
if (frameNumber == -1) {
mSurface = getSurface(v);
mFrameNumber = mSurface != null ? getNextFrameNumber(mSurface) : -1;
if (mFrameNumber == -1) {
// Booo, not cool! Our surface got destroyed, so no reason to animate anything.
Log.w(TAG, "Failed to animate, surface got destroyed.");
return;
}
TaskWindowBounds tw = recentsInterpolator.interpolate(percent);
RectF taskBounds = inOutHelper.applyTransform(mTargetSet, 1 - percent);
if (!skipViewChanges) {
v.setScaleX(tw.taskScale);
v.setScaleY(tw.taskScale);
v.setTranslationX(tw.taskX);
v.setTranslationY(tw.taskY);
float scale = taskBounds.width() / mThumbnailRect.width();
v.setScaleX(scale);
v.setScaleY(scale);
v.setTranslationX(taskBounds.centerX() - mThumbnailRect.centerX());
v.setTranslationY(taskBounds.centerY() - mThumbnailRect.centerY());
v.setAlpha(mViewAlpha.value);
}
matrix.setScale(tw.winScale, tw.winScale);
matrix.postTranslate(tw.winX, tw.winY);
crop.set(tw.winCrop);
TransactionCompat t = new TransactionCompat();
if (isFirstFrame) {
RemoteAnimationProvider.prepareTargetsForFirstFrame(targets, t, MODE_OPENING);
isFirstFrame = false;
}
for (RemoteAnimationTargetCompat target : targets) {
if (target.mode == RemoteAnimationTargetCompat.MODE_OPENING) {
t.setAlpha(target.leash, mTaskAlpha.value);
// TODO: This isn't correct at the beginning of the animation, but better
// than nothing.
matrix.postTranslate(target.position.x, target.position.y);
t.setMatrix(target.leash, matrix);
t.setWindowCrop(target.leash, crop);
if (!skipViewChanges) {
t.deferTransactionUntil(target.leash, surface, frameNumber);
}
}
}
t.apply();
matrix.reset();
}
});
return appAnimator;

View File

@ -20,13 +20,16 @@ import static com.android.launcher3.anim.Interpolators.SCROLL;
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING;
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_OPENING;
import android.annotation.TargetApi;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Matrix.ScaleToFit;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.RectF;
import android.os.Build;
import android.os.RemoteException;
import android.support.annotation.Nullable;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.DeviceProfile;
@ -42,9 +45,12 @@ import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
import com.android.systemui.shared.system.TransactionCompat;
import com.android.systemui.shared.system.WindowManagerWrapper;
import java.util.function.BiConsumer;
/**
* Utility class to handle window clip animation
*/
@TargetApi(Build.VERSION_CODES.P)
public class ClipAnimationHelper {
// The bounds of the source app in device coordinates
@ -78,13 +84,21 @@ public class ClipAnimationHelper {
// Wether or not applyTransform has been called yet since prepareAnimation()
private boolean mIsFirstFrame = true;
public void updateSource(Rect homeStackBounds, RemoteAnimationTargetCompat target) {
mHomeStackBounds.set(homeStackBounds);
private BiConsumer<TransactionCompat, RemoteAnimationTargetCompat> mTaskTransformCallback =
(t, a) -> { };
private void updateSourceStack(RemoteAnimationTargetCompat target) {
mSourceInsets.set(target.contentInsets);
mSourceStackBounds.set(target.sourceContainerBounds);
// TODO: Should sourceContainerBounds already have this offset?
mSourceStackBounds.offsetTo(target.position.x, target.position.y);
}
public void updateSource(Rect homeStackBounds, RemoteAnimationTargetCompat target) {
mHomeStackBounds.set(homeStackBounds);
updateSourceStack(target);
}
public void updateTargetRect(Rect targetRect) {
@ -116,7 +130,7 @@ public class ClipAnimationHelper {
mBoostModeTargetLayers = isOpening ? MODE_OPENING : MODE_CLOSING;
}
public void applyTransform(RemoteAnimationTargetSet targetSet, float progress) {
public RectF applyTransform(RemoteAnimationTargetSet targetSet, float progress) {
RectF currentRect;
mTmpRectF.set(mTargetRect);
Utilities.scaleRectFAboutCenter(mTmpRectF, mTargetScale);
@ -153,8 +167,16 @@ public class ClipAnimationHelper {
|| app.activityType == RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME) {
transaction.setAlpha(app.leash, 1 - progress);
}
mTaskTransformCallback.accept(transaction, app);
}
transaction.apply();
return currentRect;
}
public void setTaskTransformCallback
(BiConsumer<TransactionCompat, RemoteAnimationTargetCompat> callback) {
mTaskTransformCallback = callback;
}
public void offsetTarget(float scale, float offsetX, float offsetY) {
@ -165,6 +187,11 @@ public class ClipAnimationHelper {
}
public void fromTaskThumbnailView(TaskThumbnailView ttv, RecentsView rv) {
fromTaskThumbnailView(ttv, rv, null);
}
public void fromTaskThumbnailView(TaskThumbnailView ttv, RecentsView rv,
@Nullable RemoteAnimationTargetCompat target) {
BaseDraggingActivity activity = BaseDraggingActivity.fromContext(ttv.getContext());
BaseDragLayer dl = activity.getDragLayer();
@ -173,7 +200,9 @@ public class ClipAnimationHelper {
mHomeStackBounds.set(0, 0, dl.getWidth(), dl.getHeight());
mHomeStackBounds.offset(pos[0], pos[1]);
if (rv.shouldUseMultiWindowTaskSizeStrategy()) {
if (target != null) {
updateSourceStack(target);
} else if (rv.shouldUseMultiWindowTaskSizeStrategy()) {
updateStackBoundsToMultiWindowTaskSize(activity);
} else {
mSourceStackBounds.set(mHomeStackBounds);
@ -226,7 +255,6 @@ public class ClipAnimationHelper {
insets.top + fullDp.availableHeightPx - taskHeight);
}
public void drawForProgress(TaskThumbnailView ttv, Canvas canvas, float progress) {
RectF currentRect = mRectFEvaluator.evaluate(progress, mSourceRect, mTargetRect);
canvas.translate(mSourceStackBounds.left - mHomeStackBounds.left,
@ -244,4 +272,12 @@ public class ClipAnimationHelper {
ttv.getMeasuredHeight() + mSourceWindowClipInsets.bottom * insetProgress,
ttv.getCornerRadius() * progress);
}
public RectF getTargetRect() {
return mTargetRect;
}
public RectF getSourceRect() {
return mSourceRect;
}
}

View File

@ -87,6 +87,10 @@ public class TaskViewDrawable extends Drawable {
canvas.restore();
}
public ClipAnimationHelper getClipAnimationHelper() {
return mClipAnimationHelper;
}
@Override
public void setAlpha(int i) { }

View File

@ -36,6 +36,7 @@ import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
import com.android.quickstep.OverviewInteractionState;
import com.android.quickstep.util.ClipAnimationHelper;
import com.android.quickstep.util.LayoutUtils;
/**
@ -116,8 +117,9 @@ public class LauncherRecentsView extends RecentsView<Launcher> {
* Animates adjacent tasks and translate hotseat off screen as well.
*/
@Override
public AnimatorSet createAdjacentPageAnimForTaskLaunch(TaskView tv) {
AnimatorSet anim = super.createAdjacentPageAnimForTaskLaunch(tv);
public AnimatorSet createAdjacentPageAnimForTaskLaunch(TaskView tv,
ClipAnimationHelper helper) {
AnimatorSet anim = super.createAdjacentPageAnimForTaskLaunch(tv, helper);
if (!OverviewInteractionState.getInstance(mActivity).isSwipeUpGestureEnabled()) {
// Hotseat doesn't move when opening recents with the button,

View File

@ -65,9 +65,9 @@ import com.android.launcher3.util.PendingAnimation;
import com.android.launcher3.util.Themes;
import com.android.quickstep.OverviewCallbacks;
import com.android.quickstep.QuickScrubController;
import com.android.quickstep.RecentsAnimationInterpolator.TaskWindowBounds;
import com.android.quickstep.RecentsModel;
import com.android.quickstep.TaskUtils;
import com.android.quickstep.util.ClipAnimationHelper;
import com.android.quickstep.util.TaskViewDrawable;
import com.android.systemui.shared.recents.model.RecentsTaskLoadPlan;
import com.android.systemui.shared.recents.model.RecentsTaskLoader;
@ -1095,17 +1095,18 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
* If launching one of the adjacent tasks, parallax the center task and other adjacent task
* to the right.
*/
public AnimatorSet createAdjacentPageAnimForTaskLaunch(TaskView tv) {
public AnimatorSet createAdjacentPageAnimForTaskLaunch(
TaskView tv, ClipAnimationHelper clipAnimationHelper) {
AnimatorSet anim = new AnimatorSet();
int taskIndex = indexOfChild(tv);
int centerTaskIndex = getCurrentPage();
boolean launchingCenterTask = taskIndex == centerTaskIndex;
TaskWindowBounds endInterpolation = tv.getRecentsInterpolator().interpolate(1);
float toScale = endInterpolation.taskScale;
float toTranslationY = endInterpolation.taskY;
float toScale = clipAnimationHelper.getSourceRect().width()
/ clipAnimationHelper.getTargetRect().width();
float toTranslationY = clipAnimationHelper.getSourceRect().centerY()
- clipAnimationHelper.getTargetRect().centerY();
if (launchingCenterTask) {
TaskView centerTask = getPageAt(centerTaskIndex);
if (taskIndex - 1 >= 0) {
@ -1152,11 +1153,10 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
if (FeatureFlags.IS_DOGFOOD_BUILD && mPendingAnimation != null) {
throw new IllegalStateException("Another pending animation is still running");
}
AnimatorSet anim = createAdjacentPageAnimForTaskLaunch(tv);
int count = getChildCount();
if (count == 0) {
return new PendingAnimation(anim);
return new PendingAnimation(new AnimatorSet());
}
tv.setVisibility(INVISIBLE);
@ -1167,6 +1167,8 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
ObjectAnimator.ofFloat(drawable, TaskViewDrawable.PROGRESS, 1, 0);
drawableAnim.setInterpolator(LINEAR);
AnimatorSet anim = createAdjacentPageAnimForTaskLaunch(tv,
drawable.getClipAnimationHelper());
anim.play(drawableAnim);
anim.setDuration(duration);

View File

@ -26,7 +26,6 @@ import android.app.ActivityOptions;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Outline;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.Handler;
import android.util.AttributeSet;
@ -39,11 +38,9 @@ import android.widget.ImageView;
import com.android.launcher3.BaseActivity;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
import com.android.quickstep.RecentsAnimationInterpolator;
import com.android.quickstep.TaskSystemShortcut;
import com.android.quickstep.TaskUtils;
import com.android.quickstep.views.RecentsView.PageCallbacks;
@ -231,6 +228,13 @@ public class TaskView extends FrameLayout implements TaskCallbacks, PageCallback
setScaleY(mCurveScale);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
setPivotX((right - left) * 0.5f);
setPivotY(mSnapshotView.getTop() + mSnapshotView.getHeight() * 0.5f);
}
public float getCurveScaleForInterpolation(float linearInterpolation) {
float curveInterpolation = CURVE_INTERPOLATOR.getInterpolation(linearInterpolation);
return getCurveScaleForCurveInterpolation(curveInterpolation);
@ -250,23 +254,6 @@ public class TaskView extends FrameLayout implements TaskCallbacks, PageCallback
return false;
}
public RecentsAnimationInterpolator getRecentsInterpolator() {
Rect taskViewBounds = new Rect();
BaseDraggingActivity activity = BaseDraggingActivity.fromContext(getContext());
DeviceProfile dp = activity.getDeviceProfile();
activity.getDragLayer().getDescendantRectRelativeToSelf(this, taskViewBounds);
// TODO: Use the actual target insets instead of the current thumbnail insets in case the
// device state has changed
return new RecentsAnimationInterpolator(
new Rect(0, 0, dp.widthPx, dp.heightPx),
getThumbnail().getInsets(),
taskViewBounds,
new Rect(0, getThumbnail().getTop(), 0, 0),
getScaleX(),
getTranslationX());
}
private static final class TaskOutlineProvider extends ViewOutlineProvider {
private final int mMarginTop;