Freeform to recents app transition.
Bug: 24913782
Change-Id: I54fcbe38c51e5d75fa5ad2cb38de89d371b47bed
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index dc34904..eb0ca23 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -64,7 +64,6 @@
import android.view.animation.PathInterpolator;
import android.view.animation.ScaleAnimation;
import android.view.animation.TranslateAnimation;
-import android.view.animation.TranslateYAnimation;
import com.android.internal.util.DumpUtils.Dump;
import com.android.server.AttributeCache;
@@ -175,7 +174,7 @@
private Rect mTmpFromClipRect = new Rect();
private Rect mTmpToClipRect = new Rect();
- private final Rect mTmpStartRect = new Rect();
+ private final Rect mTmpRect = new Rect();
private final static int APP_STATE_IDLE = 0;
private final static int APP_STATE_READY = 1;
@@ -459,16 +458,16 @@
private Animation createScaleUpAnimationLocked(int transit, boolean enter,
Rect containingFrame) {
Animation a;
- getDefaultNextAppTransitionStartRect(mTmpStartRect);
+ getDefaultNextAppTransitionStartRect(mTmpRect);
final int appWidth = containingFrame.width();
final int appHeight = containingFrame.height();
if (enter) {
// Entering app zooms out from the center of the initial rect.
- float scaleW = mTmpStartRect.width() / (float) appWidth;
- float scaleH = mTmpStartRect.height() / (float) appHeight;
+ float scaleW = mTmpRect.width() / (float) appWidth;
+ float scaleH = mTmpRect.height() / (float) appHeight;
Animation scale = new ScaleAnimation(scaleW, 1, scaleH, 1,
- computePivot(mTmpStartRect.left, scaleW),
- computePivot(mTmpStartRect.right, scaleH));
+ computePivot(mTmpRect.left, scaleW),
+ computePivot(mTmpRect.right, scaleH));
scale.setInterpolator(mDecelerateInterpolator);
Animation alpha = new AlphaAnimation(0, 1);
@@ -545,20 +544,20 @@
final int appWidth = appFrame.width();
final int appHeight = appFrame.height();
- // mTmpStartRect will contain an area around the launcher icon that was pressed. We will
+ // mTmpRect will contain an area around the launcher icon that was pressed. We will
// clip reveal from that area in the final area of the app.
- getDefaultNextAppTransitionStartRect(mTmpStartRect);
+ getDefaultNextAppTransitionStartRect(mTmpRect);
float t = 0f;
if (appHeight > 0) {
- t = (float) mTmpStartRect.left / appHeight;
+ t = (float) mTmpRect.left / appHeight;
}
int translationY = mClipRevealTranslationY + (int)(appHeight / 7f * t);
- int centerX = mTmpStartRect.centerX();
- int centerY = mTmpStartRect.centerY();
- int halfWidth = mTmpStartRect.width() / 2;
- int halfHeight = mTmpStartRect.height() / 2;
+ int centerX = mTmpRect.centerX();
+ int centerY = mTmpRect.centerY();
+ int halfWidth = mTmpRect.width() / 2;
+ int halfHeight = mTmpRect.height() / 2;
// Clip third of the from size of launch icon, expand to full width/height
Animation clipAnimLR = new ClipRectLRAnimation(
@@ -693,19 +692,19 @@
float scaleW = appWidth / thumbWidth;
float unscaledHeight = thumbHeight * scaleW;
- getNextAppTransitionStartRect(taskId, mTmpStartRect);
- float unscaledStartY = mTmpStartRect.top - (unscaledHeight - thumbHeight) / 2f;
+ getNextAppTransitionStartRect(taskId, mTmpRect);
+ float unscaledStartY = mTmpRect.top - (unscaledHeight - thumbHeight) / 2f;
if (mNextAppTransitionScaleUp) {
// Animation up from the thumbnail to the full screen
Animation scale = new ScaleAnimation(1f, scaleW, 1f, scaleW,
- mTmpStartRect.left + (thumbWidth / 2f), mTmpStartRect.top + (thumbHeight / 2f));
+ mTmpRect.left + (thumbWidth / 2f), mTmpRect.top + (thumbHeight / 2f));
scale.setInterpolator(mTouchResponseInterpolator);
scale.setDuration(THUMBNAIL_APP_TRANSITION_DURATION);
Animation alpha = new AlphaAnimation(1, 0);
alpha.setInterpolator(mThumbnailFadeOutInterpolator);
alpha.setDuration(THUMBNAIL_APP_TRANSITION_ALPHA_DURATION);
final float toX = appRect.left + appRect.width() / 2 -
- (mTmpStartRect.left + thumbWidth / 2);
+ (mTmpRect.left + thumbWidth / 2);
final float toY = appRect.top + mNextAppTransitionInsets.top + -unscaledStartY;
Animation translate = new TranslateAnimation(0, toX, 0, toY);
translate.setInterpolator(mTouchResponseInterpolator);
@@ -720,7 +719,7 @@
} else {
// Animation down from the full screen to the thumbnail
Animation scale = new ScaleAnimation(scaleW, 1f, scaleW, 1f,
- mTmpStartRect.left + (thumbWidth / 2f), mTmpStartRect.top + (thumbHeight / 2f));
+ mTmpRect.left + (thumbWidth / 2f), mTmpRect.top + (thumbHeight / 2f));
scale.setInterpolator(mTouchResponseInterpolator);
scale.setDuration(THUMBNAIL_APP_TRANSITION_DURATION);
Animation alpha = new AlphaAnimation(0f, 1f);
@@ -753,10 +752,10 @@
Animation a;
final int appWidth = containingFrame.width();
final int appHeight = containingFrame.height();
- getDefaultNextAppTransitionStartRect(mTmpStartRect);
- final int thumbWidthI = mTmpStartRect.width();
+ getDefaultNextAppTransitionStartRect(mTmpRect);
+ final int thumbWidthI = mTmpRect.width();
final float thumbWidth = thumbWidthI > 0 ? thumbWidthI : 1;
- final int thumbHeightI = mTmpStartRect.height();
+ final int thumbHeightI = mTmpRect.height();
final float thumbHeight = thumbHeightI > 0 ? thumbHeightI : 1;
// Used for the ENTER_SCALE_UP and EXIT_SCALE_DOWN transitions
@@ -766,7 +765,7 @@
switch (thumbTransitState) {
case THUMBNAIL_TRANSITION_ENTER_SCALE_UP: {
if (freeform) {
- a = createAspectScaledThumbnailEnterNonFullscreenAnimationLocked(
+ a = createAspectScaledThumbnailEnterFreeformAnimationLocked(
containingFrame, surfaceInsets, taskId);
} else {
mTmpFromClipRect.set(containingFrame);
@@ -797,8 +796,8 @@
mNextAppTransitionInsets.set(contentInsets);
Animation scaleAnim = new ScaleAnimation(scale, 1, scale, 1,
- computePivot(mTmpStartRect.left, scale),
- computePivot(mTmpStartRect.top, scale));
+ computePivot(mTmpRect.left, scale),
+ computePivot(mTmpRect.top, scale));
Animation clipAnim = new ClipRectAnimation(mTmpFromClipRect, mTmpToClipRect);
Animation translateAnim = new TranslateAnimation(0, 0, -scaledTopDecor, 0);
@@ -834,44 +833,49 @@
}
case THUMBNAIL_TRANSITION_EXIT_SCALE_DOWN: {
// App window scaling down from full screen
- mTmpFromClipRect.set(containingFrame);
- mTmpToClipRect.set(containingFrame);
- // exclude top screen decor (status bar) region from the destination clip.
- mTmpToClipRect.top = contentInsets.top;
- if (orientation == Configuration.ORIENTATION_PORTRAIT) {
- // In portrait, we scale the width and clip to the top/left square
- scale = thumbWidth / appWidth;
- scaledTopDecor = (int) (scale * contentInsets.top);
- int unscaledThumbHeight = (int) (thumbHeight / scale);
- mTmpToClipRect.bottom = mTmpToClipRect.top + unscaledThumbHeight;
+ if (freeform) {
+ a = createAspectScaledThumbnailExitFreeformAnimationLocked(
+ containingFrame, surfaceInsets, taskId);
} else {
- // In landscape, we scale the height and clip to the top/left square. We only
- // scale the part that is not covered by status bar and the nav bar.
- scale = thumbHeight / (appHeight - contentInsets.top - contentInsets.bottom);
- scaledTopDecor = (int) (scale * contentInsets.top);
- int unscaledThumbWidth = (int) (thumbWidth / scale);
- mTmpToClipRect.right = mTmpToClipRect.left + unscaledThumbWidth;
- // This removes the navigation bar from the last frame, so it better matches the
- // thumbnail. We need to do this explicitly in landscape, because in portrait we
- // already crop vertically.
- mTmpToClipRect.bottom = mTmpToClipRect.bottom - contentInsets.bottom;
+ mTmpFromClipRect.set(containingFrame);
+ mTmpToClipRect.set(containingFrame);
+ // exclude top screen decor (status bar) region from the destination clip.
+ mTmpToClipRect.top = contentInsets.top;
+ if (orientation == Configuration.ORIENTATION_PORTRAIT) {
+ // In portrait, we scale the width and clip to the top/left square
+ scale = thumbWidth / appWidth;
+ scaledTopDecor = (int) (scale * contentInsets.top);
+ int unscaledThumbHeight = (int) (thumbHeight / scale);
+ mTmpToClipRect.bottom = mTmpToClipRect.top + unscaledThumbHeight;
+ } else {
+ // In landscape, we scale the height and clip to the top/left square. We only
+ // scale the part that is not covered by status bar and the nav bar.
+ scale = thumbHeight / (appHeight - contentInsets.top - contentInsets.bottom);
+ scaledTopDecor = (int) (scale * contentInsets.top);
+ int unscaledThumbWidth = (int) (thumbWidth / scale);
+ mTmpToClipRect.right = mTmpToClipRect.left + unscaledThumbWidth;
+ // This removes the navigation bar from the last frame, so it better matches the
+ // thumbnail. We need to do this explicitly in landscape, because in portrait we
+ // already crop vertically.
+ mTmpToClipRect.bottom = mTmpToClipRect.bottom - contentInsets.bottom;
+ }
+
+ mNextAppTransitionInsets.set(contentInsets);
+
+ Animation scaleAnim = new ScaleAnimation(1, scale, 1, scale,
+ computePivot(mTmpRect.left, scale),
+ computePivot(mTmpRect.top, scale));
+ Animation clipAnim = new ClipRectAnimation(mTmpFromClipRect, mTmpToClipRect);
+ Animation translateAnim = new TranslateAnimation(0, 0, 0, -scaledTopDecor);
+
+ AnimationSet set = new AnimationSet(true);
+ set.addAnimation(clipAnim);
+ set.addAnimation(scaleAnim);
+ set.addAnimation(translateAnim);
+
+ a = set;
+ a.setZAdjustment(Animation.ZORDER_TOP);
}
-
- mNextAppTransitionInsets.set(contentInsets);
-
- Animation scaleAnim = new ScaleAnimation(1, scale, 1, scale,
- computePivot(mTmpStartRect.left, scale),
- computePivot(mTmpStartRect.top, scale));
- Animation clipAnim = new ClipRectAnimation(mTmpFromClipRect, mTmpToClipRect);
- Animation translateAnim = new TranslateAnimation(0, 0, 0, -scaledTopDecor);
-
- AnimationSet set = new AnimationSet(true);
- set.addAnimation(clipAnim);
- set.addAnimation(scaleAnim);
- set.addAnimation(translateAnim);
-
- a = set;
- a.setZAdjustment(Animation.ZORDER_TOP);
break;
}
default:
@@ -884,27 +888,48 @@
mTouchResponseInterpolator);
}
- private Animation createAspectScaledThumbnailEnterNonFullscreenAnimationLocked(
- Rect frame, @Nullable Rect surfaceInsets, int taskId) {
- getNextAppTransitionStartRect(taskId, mTmpStartRect);
- float width = frame.width();
- float height = frame.height();
- float scaleWidth = mTmpStartRect.width() / width;
- float scaleHeight = mTmpStartRect.height() / height;
+ private Animation createAspectScaledThumbnailEnterFreeformAnimationLocked(Rect frame,
+ @Nullable Rect surfaceInsets, int taskId) {
+ getNextAppTransitionStartRect(taskId, mTmpRect);
+ return createAspectScaledThumbnailFreeformAnimationLocked(mTmpRect, frame, surfaceInsets,
+ true);
+ }
+
+ private Animation createAspectScaledThumbnailExitFreeformAnimationLocked(Rect frame,
+ @Nullable Rect surfaceInsets, int taskId) {
+ getNextAppTransitionStartRect(taskId, mTmpRect);
+ return createAspectScaledThumbnailFreeformAnimationLocked(frame, mTmpRect, surfaceInsets,
+ false);
+ }
+
+ private AnimationSet createAspectScaledThumbnailFreeformAnimationLocked(Rect sourceFrame,
+ Rect destFrame, @Nullable Rect surfaceInsets, boolean enter) {
+ final float sourceWidth = sourceFrame.width();
+ final float sourceHeight = sourceFrame.height();
+ final float destWidth = destFrame.width();
+ final float destHeight = destFrame.height();
+ final float scaleH = enter ? sourceWidth / destWidth : destWidth / sourceWidth;
+ final float scaleV = enter ? sourceHeight / destHeight : destHeight / sourceHeight;
AnimationSet set = new AnimationSet(true);
- int surfaceInsetsHorizontal = surfaceInsets == null
+ final int surfaceInsetsH = surfaceInsets == null
? 0 : surfaceInsets.left + surfaceInsets.right;
- int surfaceInsetsVertical = surfaceInsets == null
+ final int surfaceInsetsV = surfaceInsets == null
? 0 : surfaceInsets.top + surfaceInsets.bottom;
// We want the scaling to happen from the center of the surface. In order to achieve that,
// we need to account for surface insets that will be used to enlarge the surface.
- ScaleAnimation scale = new ScaleAnimation(scaleWidth, 1, scaleHeight, 1,
- (width + surfaceInsetsHorizontal) / 2, (height + surfaceInsetsVertical) / 2);
- int fromX = mTmpStartRect.left + mTmpStartRect.width() / 2
- - (frame.left + frame.width() / 2);
- int fromY = mTmpStartRect.top + mTmpStartRect.height() / 2
- - (frame.top + frame.height() / 2);
- TranslateAnimation translation = new TranslateAnimation(fromX, 0, fromY, 0);
+ final float scaleHCenter = ((enter ? destWidth : sourceWidth) + surfaceInsetsH) / 2;
+ final float scaleVCenter = ((enter ? destHeight : sourceHeight) + surfaceInsetsV) / 2;
+ final ScaleAnimation scale = enter ?
+ new ScaleAnimation(scaleH, 1, scaleV, 1, scaleHCenter, scaleVCenter)
+ : new ScaleAnimation(1, scaleH, 1, scaleV, scaleHCenter, scaleVCenter);
+ final int sourceHCenter = sourceFrame.left + sourceFrame.width() / 2;
+ final int sourceVCenter = sourceFrame.top + sourceFrame.height() / 2;
+ final int destHCenter = destFrame.left + destFrame.width() / 2;
+ final int destVCenter = destFrame.top + destFrame.height() / 2;
+ final int fromX = enter ? sourceHCenter - destHCenter : destHCenter - sourceHCenter;
+ final int fromY = enter ? sourceVCenter - destVCenter : destVCenter - sourceVCenter;
+ final TranslateAnimation translation = enter ? new TranslateAnimation(fromX, 0, fromY, 0)
+ : new TranslateAnimation(0, fromX, 0, fromY);
set.addAnimation(scale);
set.addAnimation(translation);
return set;
@@ -917,7 +942,7 @@
Animation createThumbnailScaleAnimationLocked(int appWidth, int appHeight, int transit,
Bitmap thumbnailHeader) {
Animation a;
- getDefaultNextAppTransitionStartRect(mTmpStartRect);
+ getDefaultNextAppTransitionStartRect(mTmpRect);
final int thumbWidthI = thumbnailHeader.getWidth();
final float thumbWidth = thumbWidthI > 0 ? thumbWidthI : 1;
final int thumbHeightI = thumbnailHeader.getHeight();
@@ -928,8 +953,8 @@
float scaleW = appWidth / thumbWidth;
float scaleH = appHeight / thumbHeight;
Animation scale = new ScaleAnimation(1, scaleW, 1, scaleH,
- computePivot(mTmpStartRect.left, 1 / scaleW),
- computePivot(mTmpStartRect.top, 1 / scaleH));
+ computePivot(mTmpRect.left, 1 / scaleW),
+ computePivot(mTmpRect.top, 1 / scaleH));
scale.setInterpolator(mDecelerateInterpolator);
Animation alpha = new AlphaAnimation(1, 0);
@@ -945,8 +970,8 @@
float scaleW = appWidth / thumbWidth;
float scaleH = appHeight / thumbHeight;
a = new ScaleAnimation(scaleW, 1, scaleH, 1,
- computePivot(mTmpStartRect.left, 1 / scaleW),
- computePivot(mTmpStartRect.top, 1 / scaleH));
+ computePivot(mTmpRect.left, 1 / scaleW),
+ computePivot(mTmpRect.top, 1 / scaleH));
}
return prepareThumbnailAnimation(a, appWidth, appHeight, transit);
@@ -962,7 +987,7 @@
final int appHeight = containingFrame.height();
Bitmap thumbnailHeader = getAppTransitionThumbnailHeader(taskId);
Animation a;
- getDefaultNextAppTransitionStartRect(mTmpStartRect);
+ getDefaultNextAppTransitionStartRect(mTmpRect);
final int thumbWidthI = thumbnailHeader != null ? thumbnailHeader.getWidth() : appWidth;
final float thumbWidth = thumbWidthI > 0 ? thumbWidthI : 1;
final int thumbHeightI = thumbnailHeader != null ? thumbnailHeader.getHeight() : appHeight;
@@ -974,8 +999,8 @@
float scaleW = thumbWidth / appWidth;
float scaleH = thumbHeight / appHeight;
a = new ScaleAnimation(scaleW, 1, scaleH, 1,
- computePivot(mTmpStartRect.left, scaleW),
- computePivot(mTmpStartRect.top, scaleH));
+ computePivot(mTmpRect.left, scaleW),
+ computePivot(mTmpRect.top, scaleH));
break;
}
case THUMBNAIL_TRANSITION_EXIT_SCALE_UP: {
@@ -1002,8 +1027,8 @@
float scaleW = thumbWidth / appWidth;
float scaleH = thumbHeight / appHeight;
Animation scale = new ScaleAnimation(1, scaleW, 1, scaleH,
- computePivot(mTmpStartRect.left, scaleW),
- computePivot(mTmpStartRect.top, scaleH));
+ computePivot(mTmpRect.left, scaleW),
+ computePivot(mTmpRect.top, scaleH));
Animation alpha = new AlphaAnimation(1, 0);
@@ -1492,15 +1517,15 @@
pw.print(Integer.toHexString(mNextAppTransitionInPlace));
break;
case NEXT_TRANSIT_TYPE_SCALE_UP: {
- getDefaultNextAppTransitionStartRect(mTmpStartRect);
+ getDefaultNextAppTransitionStartRect(mTmpRect);
pw.print(prefix); pw.print("mNextAppTransitionStartX=");
- pw.print(mTmpStartRect.left);
+ pw.print(mTmpRect.left);
pw.print(" mNextAppTransitionStartY=");
- pw.println(mTmpStartRect.top);
+ pw.println(mTmpRect.top);
pw.print(prefix); pw.print("mNextAppTransitionStartWidth=");
- pw.print(mTmpStartRect.width());
+ pw.print(mTmpRect.width());
pw.print(" mNextAppTransitionStartHeight=");
- pw.println(mTmpStartRect.height());
+ pw.println(mTmpRect.height());
break;
}
case NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP: