Implement transition for docking task in recents #6
- Use a future to provide the app thumbnail so the app can restart
in parallel when recents draws the bitmap (extremely expensive).
- Don't call startRecents from AM when recents is already running - this
messes up the transition information.
- Make sure to put the task into resizing mode if it needs to be restored
from the disk.
- Some minor fixes for the transition animation spec.
- Add NO_MOVE_ANIMATION to recents flags to prevent wallpaper
flickering.
Bug: 27607141
Change-Id: I7d0c75b88775ab467927b8cf94303ddb60222e7f
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index 9536cb7..62fa013 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -72,7 +72,6 @@
import android.view.animation.ScaleAnimation;
import android.view.animation.TranslateAnimation;
-import com.android.internal.R;
import com.android.internal.util.DumpUtils.Dump;
import com.android.server.AttributeCache;
import com.android.server.wm.WindowManagerService.H;
@@ -147,6 +146,9 @@
static final Interpolator TOUCH_RESPONSE_INTERPOLATOR =
new PathInterpolator(0.3f, 0f, 0.1f, 1f);
+ private static final Interpolator THUMBNAIL_DOCK_INTERPOLATOR =
+ new PathInterpolator(0.85f, 0f, 1f, 1f);
+
/**
* Maximum duration for the clip reveal animation. This is used when there is a lot of movement
* involved, to make it more understandable.
@@ -827,7 +829,9 @@
a.setDuration(duration);
}
a.setFillAfter(true);
- a.setInterpolator(interpolator);
+ if (interpolator != null) {
+ a.setInterpolator(interpolator);
+ }
a.initialize(appWidth, appHeight, appWidth, appHeight);
return a;
}
@@ -900,8 +904,11 @@
scale.setInterpolator(interpolator);
scale.setDuration(duration);
Animation alpha = new AlphaAnimation(1f, 0f);
- alpha.setInterpolator(mThumbnailFadeOutInterpolator);
- alpha.setDuration(duration);
+ alpha.setInterpolator(mNextAppTransition == TRANSIT_DOCK_TASK_FROM_RECENTS
+ ? THUMBNAIL_DOCK_INTERPOLATOR : mThumbnailFadeOutInterpolator);
+ alpha.setDuration(mNextAppTransition == TRANSIT_DOCK_TASK_FROM_RECENTS
+ ? duration / 2
+ : duration);
Animation translate = createCurvedMotion(fromX, toX, fromY, toY);
translate.setInterpolator(interpolator);
translate.setDuration(duration);
@@ -912,8 +919,8 @@
// Containing frame is in screen space, but we need the clip rect in the
// app space.
mTmpToClipRect.offsetTo(0, 0);
- mTmpToClipRect.right = (int) (mTmpToClipRect.right * scaleW);
- mTmpToClipRect.bottom = (int) (mTmpToClipRect.bottom * scaleW);
+ mTmpToClipRect.right = (int) (mTmpToClipRect.right / scaleW);
+ mTmpToClipRect.bottom = (int) (mTmpToClipRect.bottom / scaleW);
if (contentInsets != null) {
mTmpToClipRect.inset((int) (-contentInsets.left * scaleW),
@@ -954,13 +961,13 @@
}
return prepareThumbnailAnimationWithDuration(a, appWidth, appRect.height(), 0,
- TOUCH_RESPONSE_INTERPOLATOR);
+ null);
}
private Animation createCurvedMotion(float fromX, float toX, float fromY, float toY) {
// Almost no x-change - use linear animation
- if (Math.abs(toX - fromX) < 1f) {
+ if (Math.abs(toX - fromX) < 1f || mNextAppTransition != TRANSIT_DOCK_TASK_FROM_RECENTS) {
return new TranslateAnimation(fromX, toX, fromY, toY);
} else {
final Path path = createCurvedPath(fromX, toX, fromY, toY);
@@ -977,7 +984,7 @@
private long getAspectScaleDuration() {
if (mNextAppTransition == TRANSIT_DOCK_TASK_FROM_RECENTS) {
- return (long) (THUMBNAIL_APP_TRANSITION_DURATION * 1f);
+ return (long) (THUMBNAIL_APP_TRANSITION_DURATION * 1.35f);
} else {
return THUMBNAIL_APP_TRANSITION_DURATION;
}
@@ -1009,10 +1016,6 @@
final int thumbStartX = mTmpRect.left - containingFrame.left;
final int thumbStartY = mTmpRect.top - containingFrame.top;
- // Used for the ENTER_SCALE_UP and EXIT_SCALE_DOWN transitions
- float scale = 1f;
- int scaledTopDecor = 0;
-
switch (thumbTransitState) {
case THUMBNAIL_TRANSITION_ENTER_SCALE_UP:
case THUMBNAIL_TRANSITION_EXIT_SCALE_DOWN: {
@@ -1041,25 +1044,34 @@
if (orientation == Configuration.ORIENTATION_PORTRAIT) {
// We scale the width and clip to the top/left square
+ // We scale the width and clip to the top/left square
+ float scale = thumbWidth /
+ (appWidth - contentInsets.left - contentInsets.right);
+ int unscaledThumbHeight = (int) (thumbHeight / scale);
+ mTmpFromClipRect.bottom = mTmpFromClipRect.top + unscaledThumbHeight;
+
+ mNextAppTransitionInsets.set(contentInsets);
+
Animation scaleAnim = new ScaleAnimation(
scaleUp ? scale : 1, scaleUp ? 1 : scale,
scaleUp ? scale : 1, scaleUp ? 1 : scale,
- containingFrame.width() / 2,
- containingFrame.height() / 2 + contentInsets.top);
+ containingFrame.width() / 2f,
+ containingFrame.height() / 2f + contentInsets.top);
final float targetX = (mTmpRect.left - containingFrame.left);
- final float x = containingFrame.width() / 2
- - containingFrame.width() / 2 * scale;
+ final float x = containingFrame.width() / 2f
+ - containingFrame.width() / 2f * scale;
final float targetY = (mTmpRect.top - containingFrame.top);
- final float y = containingFrame.height() / 2
- - containingFrame.height() / 2 * scale;
+ final float y = containingFrame.height() / 2f
+ - containingFrame.height() / 2f * scale;
final float startX = targetX - x;
final float startY = targetY - y;
Animation clipAnim = scaleUp
? new ClipRectAnimation(mTmpFromClipRect, mTmpToClipRect)
: new ClipRectAnimation(mTmpToClipRect, mTmpFromClipRect);
Animation translateAnim = scaleUp
- ? createCurvedMotion(startX, 0, startY - scaledTopDecor, 0)
- : createCurvedMotion(0, startX, 0, startY - scaledTopDecor);
+ ? createCurvedMotion(startX, 0, startY - contentInsets.top, 0)
+ : createCurvedMotion(0, startX, 0, startY - contentInsets.top);
+
set.addAnimation(clipAnim);
set.addAnimation(scaleAnim);
set.addAnimation(translateAnim);
@@ -1081,7 +1093,6 @@
set.addAnimation(clipAnim);
set.addAnimation(translateAnim);
}
- set.setZAdjustment(Animation.ZORDER_TOP);
a = set;
a.setZAdjustment(Animation.ZORDER_TOP);
}
@@ -1527,6 +1538,7 @@
int getAppStackClipMode() {
return mNextAppTransition == TRANSIT_ACTIVITY_RELAUNCH
+ || mNextAppTransition == TRANSIT_DOCK_TASK_FROM_RECENTS
? STACK_CLIP_NONE
: STACK_CLIP_AFTER_ANIM;
}