Merge "Adding support for clipping window transition for alternate recents."
This commit is contained in:
59
core/java/android/view/animation/ClipRectAnimation.java
Normal file
59
core/java/android/view/animation/ClipRectAnimation.java
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2014 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 android.view.animation;
|
||||||
|
|
||||||
|
import android.graphics.Rect;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An animation that controls the clip of an object. See the
|
||||||
|
* {@link android.view.animation full package} description for details and
|
||||||
|
* sample code.
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public class ClipRectAnimation extends Animation {
|
||||||
|
private Rect mFromRect = new Rect();
|
||||||
|
private Rect mToRect = new Rect();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor to use when building a ClipRectAnimation from code
|
||||||
|
*
|
||||||
|
* @param fromClip the clip rect to animate from
|
||||||
|
* @param toClip the clip rect to animate to
|
||||||
|
*/
|
||||||
|
public ClipRectAnimation(Rect fromClip, Rect toClip) {
|
||||||
|
if (fromClip == null || toClip == null) {
|
||||||
|
throw new RuntimeException("Expected non-null animation clip rects");
|
||||||
|
}
|
||||||
|
mFromRect.set(fromClip);
|
||||||
|
mToRect.set(toClip);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void applyTransformation(float it, Transformation tr) {
|
||||||
|
int l = mFromRect.left + (int) ((mToRect.left - mFromRect.left) * it);
|
||||||
|
int t = mFromRect.top + (int) ((mToRect.top - mFromRect.top) * it);
|
||||||
|
int r = mFromRect.right + (int) ((mToRect.right - mFromRect.right) * it);
|
||||||
|
int b = mFromRect.bottom + (int) ((mToRect.bottom - mFromRect.bottom) * it);
|
||||||
|
tr.setClipRect(l, t, r, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean willChangeTransformationMatrix() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -17,6 +17,7 @@
|
|||||||
package android.view.animation;
|
package android.view.animation;
|
||||||
|
|
||||||
import android.graphics.Matrix;
|
import android.graphics.Matrix;
|
||||||
|
import android.graphics.Rect;
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
|
|
||||||
@@ -47,6 +48,9 @@ public class Transformation {
|
|||||||
protected float mAlpha;
|
protected float mAlpha;
|
||||||
protected int mTransformationType;
|
protected int mTransformationType;
|
||||||
|
|
||||||
|
private boolean mHasClipRect;
|
||||||
|
private Rect mClipRect = new Rect();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new transformation with alpha = 1 and the identity matrix.
|
* Creates a new transformation with alpha = 1 and the identity matrix.
|
||||||
*/
|
*/
|
||||||
@@ -65,6 +69,8 @@ public class Transformation {
|
|||||||
} else {
|
} else {
|
||||||
mMatrix.reset();
|
mMatrix.reset();
|
||||||
}
|
}
|
||||||
|
mClipRect.setEmpty();
|
||||||
|
mHasClipRect = false;
|
||||||
mAlpha = 1.0f;
|
mAlpha = 1.0f;
|
||||||
mTransformationType = TYPE_BOTH;
|
mTransformationType = TYPE_BOTH;
|
||||||
}
|
}
|
||||||
@@ -98,9 +104,15 @@ public class Transformation {
|
|||||||
public void set(Transformation t) {
|
public void set(Transformation t) {
|
||||||
mAlpha = t.getAlpha();
|
mAlpha = t.getAlpha();
|
||||||
mMatrix.set(t.getMatrix());
|
mMatrix.set(t.getMatrix());
|
||||||
|
if (t.mHasClipRect) {
|
||||||
|
setClipRect(t.getClipRect());
|
||||||
|
} else {
|
||||||
|
mHasClipRect = false;
|
||||||
|
mClipRect.setEmpty();
|
||||||
|
}
|
||||||
mTransformationType = t.getTransformationType();
|
mTransformationType = t.getTransformationType();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Apply this Transformation to an existing Transformation, e.g. apply
|
* Apply this Transformation to an existing Transformation, e.g. apply
|
||||||
* a scale effect to something that has already been rotated.
|
* a scale effect to something that has already been rotated.
|
||||||
@@ -109,6 +121,9 @@ public class Transformation {
|
|||||||
public void compose(Transformation t) {
|
public void compose(Transformation t) {
|
||||||
mAlpha *= t.getAlpha();
|
mAlpha *= t.getAlpha();
|
||||||
mMatrix.preConcat(t.getMatrix());
|
mMatrix.preConcat(t.getMatrix());
|
||||||
|
if (t.mHasClipRect) {
|
||||||
|
setClipRect(t.getClipRect());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -119,6 +134,9 @@ public class Transformation {
|
|||||||
public void postCompose(Transformation t) {
|
public void postCompose(Transformation t) {
|
||||||
mAlpha *= t.getAlpha();
|
mAlpha *= t.getAlpha();
|
||||||
mMatrix.postConcat(t.getMatrix());
|
mMatrix.postConcat(t.getMatrix());
|
||||||
|
if (t.mHasClipRect) {
|
||||||
|
setClipRect(t.getClipRect());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -137,6 +155,39 @@ public class Transformation {
|
|||||||
mAlpha = alpha;
|
mAlpha = alpha;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the current Transform's clip rect
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public void setClipRect(Rect r) {
|
||||||
|
setClipRect(r.left, r.top, r.right, r.bottom);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the current Transform's clip rect
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public void setClipRect(int l, int t, int r, int b) {
|
||||||
|
mClipRect.set(l, t, r, b);
|
||||||
|
mHasClipRect = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the current Transform's clip rect
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public Rect getClipRect() {
|
||||||
|
return mClipRect;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the current Transform's clip rect is set
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public boolean hasClipRect() {
|
||||||
|
return mHasClipRect;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return The degree of transparency
|
* @return The degree of transparency
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -19,18 +19,22 @@ package com.android.server.wm;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.Point;
|
import android.graphics.Point;
|
||||||
|
import android.graphics.Rect;
|
||||||
import android.os.Debug;
|
import android.os.Debug;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.IRemoteCallback;
|
import android.os.IRemoteCallback;
|
||||||
|
import android.os.SystemProperties;
|
||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
import android.view.animation.AlphaAnimation;
|
import android.view.animation.AlphaAnimation;
|
||||||
import android.view.animation.Animation;
|
import android.view.animation.Animation;
|
||||||
import android.view.animation.AnimationSet;
|
import android.view.animation.AnimationSet;
|
||||||
import android.view.animation.AnimationUtils;
|
import android.view.animation.AnimationUtils;
|
||||||
|
import android.view.animation.ClipRectAnimation;
|
||||||
import android.view.animation.Interpolator;
|
import android.view.animation.Interpolator;
|
||||||
import android.view.animation.ScaleAnimation;
|
import android.view.animation.ScaleAnimation;
|
||||||
|
|
||||||
|
import android.view.animation.TranslateAnimation;
|
||||||
import com.android.internal.util.DumpUtils.Dump;
|
import com.android.internal.util.DumpUtils.Dump;
|
||||||
import com.android.server.AttributeCache;
|
import com.android.server.AttributeCache;
|
||||||
import com.android.server.wm.WindowManagerService.H;
|
import com.android.server.wm.WindowManagerService.H;
|
||||||
@@ -125,6 +129,12 @@ public class AppTransition implements Dump {
|
|||||||
private static final int NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN = 4;
|
private static final int NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN = 4;
|
||||||
private int mNextAppTransitionType = NEXT_TRANSIT_TYPE_NONE;
|
private int mNextAppTransitionType = NEXT_TRANSIT_TYPE_NONE;
|
||||||
|
|
||||||
|
// These are the possible states for the enter/exit activities during a thumbnail transition
|
||||||
|
private static final int THUMBNAIL_TRANSITION_ENTER_SCALE_UP = 0;
|
||||||
|
private static final int THUMBNAIL_TRANSITION_EXIT_SCALE_UP = 1;
|
||||||
|
private static final int THUMBNAIL_TRANSITION_ENTER_SCALE_DOWN = 2;
|
||||||
|
private static final int THUMBNAIL_TRANSITION_EXIT_SCALE_DOWN = 3;
|
||||||
|
|
||||||
private String mNextAppTransitionPackage;
|
private String mNextAppTransitionPackage;
|
||||||
private Bitmap mNextAppTransitionThumbnail;
|
private Bitmap mNextAppTransitionThumbnail;
|
||||||
// Used for thumbnail transitions. True if we're scaling up, false if scaling down
|
// Used for thumbnail transitions. True if we're scaling up, false if scaling down
|
||||||
@@ -148,10 +158,13 @@ public class AppTransition implements Dump {
|
|||||||
private final Interpolator mThumbnailFadeoutInterpolator;
|
private final Interpolator mThumbnailFadeoutInterpolator;
|
||||||
|
|
||||||
private int mCurrentUserId = 0;
|
private int mCurrentUserId = 0;
|
||||||
|
private boolean mUseAlternateThumbnailAnimation;
|
||||||
|
|
||||||
AppTransition(Context context, Handler h) {
|
AppTransition(Context context, Handler h) {
|
||||||
mContext = context;
|
mContext = context;
|
||||||
mH = h;
|
mH = h;
|
||||||
|
mUseAlternateThumbnailAnimation =
|
||||||
|
SystemProperties.getBoolean("persist.anim.use_alt_thumbnail", false);
|
||||||
mConfigShortAnimTime = context.getResources().getInteger(
|
mConfigShortAnimTime = context.getResources().getInteger(
|
||||||
com.android.internal.R.integer.config_shortAnimTime);
|
com.android.internal.R.integer.config_shortAnimTime);
|
||||||
mDecelerateInterpolator = AnimationUtils.loadInterpolator(context,
|
mDecelerateInterpolator = AnimationUtils.loadInterpolator(context,
|
||||||
@@ -384,80 +397,10 @@ public class AppTransition implements Dump {
|
|||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
Animation createThumbnailAnimationLocked(int transit, boolean enter, boolean thumb,
|
/**
|
||||||
int appWidth, int appHeight) {
|
* Prepares the specified animation with a standard duration, interpolator, etc.
|
||||||
Animation a;
|
*/
|
||||||
final int thumbWidthI = mNextAppTransitionThumbnail.getWidth();
|
Animation prepareThumbnailAnimation(Animation a, int appWidth, int appHeight, int transit) {
|
||||||
final float thumbWidth = thumbWidthI > 0 ? thumbWidthI : 1;
|
|
||||||
final int thumbHeightI = mNextAppTransitionThumbnail.getHeight();
|
|
||||||
final float thumbHeight = thumbHeightI > 0 ? thumbHeightI : 1;
|
|
||||||
if (thumb) {
|
|
||||||
// Animation for zooming thumbnail from its initial size to
|
|
||||||
// filling the screen.
|
|
||||||
if (mNextAppTransitionScaleUp) {
|
|
||||||
float scaleW = appWidth / thumbWidth;
|
|
||||||
float scaleH = appHeight / thumbHeight;
|
|
||||||
Animation scale = new ScaleAnimation(1, scaleW, 1, scaleH,
|
|
||||||
computePivot(mNextAppTransitionStartX, 1 / scaleW),
|
|
||||||
computePivot(mNextAppTransitionStartY, 1 / scaleH));
|
|
||||||
scale.setInterpolator(mDecelerateInterpolator);
|
|
||||||
|
|
||||||
Animation alpha = new AlphaAnimation(1, 0);
|
|
||||||
alpha.setInterpolator(mThumbnailFadeoutInterpolator);
|
|
||||||
|
|
||||||
// This AnimationSet uses the Interpolators assigned above.
|
|
||||||
AnimationSet set = new AnimationSet(false);
|
|
||||||
set.addAnimation(scale);
|
|
||||||
set.addAnimation(alpha);
|
|
||||||
a = set;
|
|
||||||
} else {
|
|
||||||
float scaleW = appWidth / thumbWidth;
|
|
||||||
float scaleH = appHeight / thumbHeight;
|
|
||||||
a = new ScaleAnimation(scaleW, 1, scaleH, 1,
|
|
||||||
computePivot(mNextAppTransitionStartX, 1 / scaleW),
|
|
||||||
computePivot(mNextAppTransitionStartY, 1 / scaleH));
|
|
||||||
}
|
|
||||||
} else if (enter) {
|
|
||||||
// Entering app zooms out from the center of the thumbnail.
|
|
||||||
if (mNextAppTransitionScaleUp) {
|
|
||||||
float scaleW = thumbWidth / appWidth;
|
|
||||||
float scaleH = thumbHeight / appHeight;
|
|
||||||
a = new ScaleAnimation(scaleW, 1, scaleH, 1,
|
|
||||||
computePivot(mNextAppTransitionStartX, scaleW),
|
|
||||||
computePivot(mNextAppTransitionStartY, scaleH));
|
|
||||||
} else {
|
|
||||||
// noop animation
|
|
||||||
a = new AlphaAnimation(1, 1);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Exiting app
|
|
||||||
if (mNextAppTransitionScaleUp) {
|
|
||||||
if (transit == TRANSIT_WALLPAPER_INTRA_OPEN) {
|
|
||||||
// Fade out while bringing up selected activity. This keeps the
|
|
||||||
// current activity from showing through a launching wallpaper
|
|
||||||
// activity.
|
|
||||||
a = new AlphaAnimation(1, 0);
|
|
||||||
} else {
|
|
||||||
// noop animation
|
|
||||||
a = new AlphaAnimation(1, 1);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
float scaleW = thumbWidth / appWidth;
|
|
||||||
float scaleH = thumbHeight / appHeight;
|
|
||||||
Animation scale = new ScaleAnimation(1, scaleW, 1, scaleH,
|
|
||||||
computePivot(mNextAppTransitionStartX, scaleW),
|
|
||||||
computePivot(mNextAppTransitionStartY, scaleH));
|
|
||||||
|
|
||||||
Animation alpha = new AlphaAnimation(1, 0);
|
|
||||||
|
|
||||||
AnimationSet set = new AnimationSet(true);
|
|
||||||
set.addAnimation(scale);
|
|
||||||
set.addAnimation(alpha);
|
|
||||||
set.setZAdjustment(Animation.ZORDER_TOP);
|
|
||||||
a = set;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pick the desired duration. If this is an inter-activity transition,
|
// Pick the desired duration. If this is an inter-activity transition,
|
||||||
// it is the standard duration for that. Otherwise we use the longer
|
// it is the standard duration for that. Otherwise we use the longer
|
||||||
// task transition duration.
|
// task transition duration.
|
||||||
@@ -478,9 +421,223 @@ public class AppTransition implements Dump {
|
|||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the current thumbnail transition state.
|
||||||
|
*/
|
||||||
|
int getThumbnailTransitionState(boolean enter) {
|
||||||
|
if (enter) {
|
||||||
|
if (mNextAppTransitionScaleUp) {
|
||||||
|
return THUMBNAIL_TRANSITION_ENTER_SCALE_UP;
|
||||||
|
} else {
|
||||||
|
return THUMBNAIL_TRANSITION_ENTER_SCALE_DOWN;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (mNextAppTransitionScaleUp) {
|
||||||
|
return THUMBNAIL_TRANSITION_EXIT_SCALE_UP;
|
||||||
|
} else {
|
||||||
|
return THUMBNAIL_TRANSITION_EXIT_SCALE_DOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This animation runs for the thumbnail that gets cross faded with the enter/exit activity
|
||||||
|
* when a thumbnail is specified with the activity options.
|
||||||
|
*/
|
||||||
|
Animation createThumbnailScaleAnimationLocked(int appWidth, int appHeight, int transit) {
|
||||||
|
Animation a;
|
||||||
|
final int thumbWidthI = mNextAppTransitionThumbnail.getWidth();
|
||||||
|
final float thumbWidth = thumbWidthI > 0 ? thumbWidthI : 1;
|
||||||
|
final int thumbHeightI = mNextAppTransitionThumbnail.getHeight();
|
||||||
|
final float thumbHeight = thumbHeightI > 0 ? thumbHeightI : 1;
|
||||||
|
|
||||||
|
if (mNextAppTransitionScaleUp) {
|
||||||
|
// Animation for the thumbnail zooming from its initial size to the full screen
|
||||||
|
float scaleW = appWidth / thumbWidth;
|
||||||
|
float scaleH = appHeight / thumbHeight;
|
||||||
|
Animation scale = new ScaleAnimation(1, scaleW, 1, scaleH,
|
||||||
|
computePivot(mNextAppTransitionStartX, 1 / scaleW),
|
||||||
|
computePivot(mNextAppTransitionStartY, 1 / scaleH));
|
||||||
|
scale.setInterpolator(mDecelerateInterpolator);
|
||||||
|
|
||||||
|
Animation alpha = new AlphaAnimation(1, 0);
|
||||||
|
alpha.setInterpolator(mThumbnailFadeoutInterpolator);
|
||||||
|
|
||||||
|
// This AnimationSet uses the Interpolators assigned above.
|
||||||
|
AnimationSet set = new AnimationSet(false);
|
||||||
|
set.addAnimation(scale);
|
||||||
|
set.addAnimation(alpha);
|
||||||
|
a = set;
|
||||||
|
} else {
|
||||||
|
// Animation for the thumbnail zooming down from the full screen to its final size
|
||||||
|
float scaleW = appWidth / thumbWidth;
|
||||||
|
float scaleH = appHeight / thumbHeight;
|
||||||
|
a = new ScaleAnimation(scaleW, 1, scaleH, 1,
|
||||||
|
computePivot(mNextAppTransitionStartX, 1 / scaleW),
|
||||||
|
computePivot(mNextAppTransitionStartY, 1 / scaleH));
|
||||||
|
}
|
||||||
|
|
||||||
|
return prepareThumbnailAnimation(a, appWidth, appHeight, transit);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This alternate animation is created when we are doing a thumbnail transition, for the
|
||||||
|
* activity that is leaving, and the activity that is entering.
|
||||||
|
*/
|
||||||
|
Animation createAlternateThumbnailEnterExitAnimationLocked(int thumbTransitState, int appWidth,
|
||||||
|
int appHeight, int transit,
|
||||||
|
Rect containingFrame, Rect contentInsets) {
|
||||||
|
Animation a;
|
||||||
|
final int thumbWidthI = mNextAppTransitionThumbnail.getWidth();
|
||||||
|
final float thumbWidth = thumbWidthI > 0 ? thumbWidthI : 1;
|
||||||
|
final int thumbHeightI = mNextAppTransitionThumbnail.getHeight();
|
||||||
|
final float thumbHeight = thumbHeightI > 0 ? thumbHeightI : 1;
|
||||||
|
|
||||||
|
switch (thumbTransitState) {
|
||||||
|
case THUMBNAIL_TRANSITION_ENTER_SCALE_UP: {
|
||||||
|
// Entering app scales up with the thumbnail
|
||||||
|
float scale = thumbWidth / appWidth;
|
||||||
|
int unscaledThumbHeight = (int) (thumbHeight / scale);
|
||||||
|
int scaledTopDecor = (int) (scale * contentInsets.top);
|
||||||
|
Rect fromClipRect = new Rect(containingFrame);
|
||||||
|
fromClipRect.bottom = (fromClipRect.top + unscaledThumbHeight);
|
||||||
|
Rect toClipRect = new Rect(containingFrame);
|
||||||
|
|
||||||
|
Animation scaleAnim = new ScaleAnimation(scale, 1, scale, 1,
|
||||||
|
computePivot(mNextAppTransitionStartX, scale),
|
||||||
|
computePivot(mNextAppTransitionStartY, scale));
|
||||||
|
Animation alphaAnim = new AlphaAnimation(1, 1);
|
||||||
|
Animation clipAnim = new ClipRectAnimation(fromClipRect, toClipRect);
|
||||||
|
Animation translateAnim = new TranslateAnimation(0, 0, -scaledTopDecor, 0);
|
||||||
|
|
||||||
|
AnimationSet set = new AnimationSet(true);
|
||||||
|
set.addAnimation(alphaAnim);
|
||||||
|
set.addAnimation(clipAnim);
|
||||||
|
set.addAnimation(scaleAnim);
|
||||||
|
set.addAnimation(translateAnim);
|
||||||
|
a = set;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case THUMBNAIL_TRANSITION_EXIT_SCALE_UP: {
|
||||||
|
// Exiting app while the thumbnail is scaling up should fade
|
||||||
|
if (transit == TRANSIT_WALLPAPER_INTRA_OPEN) {
|
||||||
|
// Fade out while bringing up selected activity. This keeps the
|
||||||
|
// current activity from showing through a launching wallpaper
|
||||||
|
// activity.
|
||||||
|
a = new AlphaAnimation(1, 0);
|
||||||
|
} else {
|
||||||
|
// noop animation
|
||||||
|
a = new AlphaAnimation(1, 1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case THUMBNAIL_TRANSITION_ENTER_SCALE_DOWN: {
|
||||||
|
// Entering the other app, it should just be visible while we scale the thumbnail
|
||||||
|
// down above it
|
||||||
|
a = new AlphaAnimation(1, 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case THUMBNAIL_TRANSITION_EXIT_SCALE_DOWN: {
|
||||||
|
// Exiting the current app, the app should scale down with the thumbnail
|
||||||
|
float scale = thumbWidth / appWidth;
|
||||||
|
int unscaledThumbHeight = (int) (thumbHeight / scale);
|
||||||
|
int scaledTopDecor = (int) (scale * contentInsets.top);
|
||||||
|
Rect fromClipRect = new Rect(containingFrame);
|
||||||
|
Rect toClipRect = new Rect(containingFrame);
|
||||||
|
toClipRect.bottom = (toClipRect.top + unscaledThumbHeight);
|
||||||
|
|
||||||
|
Animation scaleAnim = new ScaleAnimation(1, scale, 1, scale,
|
||||||
|
computePivot(mNextAppTransitionStartX, scale),
|
||||||
|
computePivot(mNextAppTransitionStartY, scale));
|
||||||
|
Animation alphaAnim = new AlphaAnimation(1, 1);
|
||||||
|
Animation clipAnim = new ClipRectAnimation(fromClipRect, toClipRect);
|
||||||
|
Animation translateAnim = new TranslateAnimation(0, 0, 0, -scaledTopDecor);
|
||||||
|
|
||||||
|
AnimationSet set = new AnimationSet(true);
|
||||||
|
set.addAnimation(alphaAnim);
|
||||||
|
set.addAnimation(clipAnim);
|
||||||
|
set.addAnimation(scaleAnim);
|
||||||
|
set.addAnimation(translateAnim);
|
||||||
|
|
||||||
|
a = set;
|
||||||
|
a.setZAdjustment(Animation.ZORDER_TOP);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
throw new RuntimeException("Invalid thumbnail transition state");
|
||||||
|
}
|
||||||
|
|
||||||
|
return prepareThumbnailAnimation(a, appWidth, appHeight, transit);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This animation is created when we are doing a thumbnail transition, for the activity that is
|
||||||
|
* leaving, and the activity that is entering.
|
||||||
|
*/
|
||||||
|
Animation createThumbnailEnterExitAnimationLocked(int thumbTransitState, int appWidth,
|
||||||
|
int appHeight, int transit) {
|
||||||
|
Animation a;
|
||||||
|
final int thumbWidthI = mNextAppTransitionThumbnail.getWidth();
|
||||||
|
final float thumbWidth = thumbWidthI > 0 ? thumbWidthI : 1;
|
||||||
|
final int thumbHeightI = mNextAppTransitionThumbnail.getHeight();
|
||||||
|
final float thumbHeight = thumbHeightI > 0 ? thumbHeightI : 1;
|
||||||
|
|
||||||
|
switch (thumbTransitState) {
|
||||||
|
case THUMBNAIL_TRANSITION_ENTER_SCALE_UP: {
|
||||||
|
// Entering app scales up with the thumbnail
|
||||||
|
float scaleW = thumbWidth / appWidth;
|
||||||
|
float scaleH = thumbHeight / appHeight;
|
||||||
|
a = new ScaleAnimation(scaleW, 1, scaleH, 1,
|
||||||
|
computePivot(mNextAppTransitionStartX, scaleW),
|
||||||
|
computePivot(mNextAppTransitionStartY, scaleH));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case THUMBNAIL_TRANSITION_EXIT_SCALE_UP: {
|
||||||
|
// Exiting app while the thumbnail is scaling up should fade or stay in place
|
||||||
|
if (transit == TRANSIT_WALLPAPER_INTRA_OPEN) {
|
||||||
|
// Fade out while bringing up selected activity. This keeps the
|
||||||
|
// current activity from showing through a launching wallpaper
|
||||||
|
// activity.
|
||||||
|
a = new AlphaAnimation(1, 0);
|
||||||
|
} else {
|
||||||
|
// noop animation
|
||||||
|
a = new AlphaAnimation(1, 1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case THUMBNAIL_TRANSITION_ENTER_SCALE_DOWN: {
|
||||||
|
// Entering the other app, it should just be visible while we scale the thumbnail
|
||||||
|
// down above it
|
||||||
|
a = new AlphaAnimation(1, 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case THUMBNAIL_TRANSITION_EXIT_SCALE_DOWN: {
|
||||||
|
// Exiting the current app, the app should scale down with the thumbnail
|
||||||
|
float scaleW = thumbWidth / appWidth;
|
||||||
|
float scaleH = thumbHeight / appHeight;
|
||||||
|
Animation scale = new ScaleAnimation(1, scaleW, 1, scaleH,
|
||||||
|
computePivot(mNextAppTransitionStartX, scaleW),
|
||||||
|
computePivot(mNextAppTransitionStartY, scaleH));
|
||||||
|
|
||||||
|
Animation alpha = new AlphaAnimation(1, 0);
|
||||||
|
|
||||||
|
AnimationSet set = new AnimationSet(true);
|
||||||
|
set.addAnimation(scale);
|
||||||
|
set.addAnimation(alpha);
|
||||||
|
set.setZAdjustment(Animation.ZORDER_TOP);
|
||||||
|
a = set;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
throw new RuntimeException("Invalid thumbnail transition state");
|
||||||
|
}
|
||||||
|
|
||||||
|
return prepareThumbnailAnimation(a, appWidth, appHeight, transit);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
|
Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
|
||||||
int appWidth, int appHeight) {
|
int appWidth, int appHeight, Rect containingFrame, Rect contentInsets) {
|
||||||
Animation a;
|
Animation a;
|
||||||
if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_CUSTOM) {
|
if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_CUSTOM) {
|
||||||
a = loadAnimation(mNextAppTransitionPackage, enter ?
|
a = loadAnimation(mNextAppTransitionPackage, enter ?
|
||||||
@@ -501,7 +658,14 @@ public class AppTransition implements Dump {
|
|||||||
mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN) {
|
mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN) {
|
||||||
mNextAppTransitionScaleUp =
|
mNextAppTransitionScaleUp =
|
||||||
(mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP);
|
(mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP);
|
||||||
a = createThumbnailAnimationLocked(transit, enter, false, appWidth, appHeight);
|
if (mUseAlternateThumbnailAnimation) {
|
||||||
|
a = createAlternateThumbnailEnterExitAnimationLocked(
|
||||||
|
getThumbnailTransitionState(enter), appWidth, appHeight, transit,
|
||||||
|
containingFrame, contentInsets);
|
||||||
|
} else {
|
||||||
|
a = createThumbnailEnterExitAnimationLocked(getThumbnailTransitionState(enter),
|
||||||
|
appWidth, appHeight, transit);
|
||||||
|
}
|
||||||
if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) {
|
if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) {
|
||||||
String animName = mNextAppTransitionScaleUp ?
|
String animName = mNextAppTransitionScaleUp ?
|
||||||
"ANIM_THUMBNAIL_SCALE_UP" : "ANIM_THUMBNAIL_SCALE_DOWN";
|
"ANIM_THUMBNAIL_SCALE_UP" : "ANIM_THUMBNAIL_SCALE_DOWN";
|
||||||
|
|||||||
@@ -3155,7 +3155,22 @@ public class WindowManagerService extends IWindowManager.Stub
|
|||||||
final int height = displayInfo.appHeight;
|
final int height = displayInfo.appHeight;
|
||||||
if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG, "applyAnimation: atoken="
|
if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG, "applyAnimation: atoken="
|
||||||
+ atoken);
|
+ atoken);
|
||||||
Animation a = mAppTransition.loadAnimation(lp, transit, enter, width, height);
|
|
||||||
|
// Determine the visible rect to calculate the thumbnail clip
|
||||||
|
WindowState win = atoken.findMainWindow();
|
||||||
|
Rect containingFrame = new Rect(0, 0, width, height);
|
||||||
|
Rect contentInsets = new Rect();
|
||||||
|
if (win != null) {
|
||||||
|
if (win.mContainingFrame != null) {
|
||||||
|
containingFrame.set(win.mContainingFrame);
|
||||||
|
}
|
||||||
|
if (win.mContentInsets != null) {
|
||||||
|
contentInsets.set(win.mContentInsets);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Animation a = mAppTransition.loadAnimation(lp, transit, enter, width, height,
|
||||||
|
containingFrame, contentInsets);
|
||||||
if (a != null) {
|
if (a != null) {
|
||||||
if (DEBUG_ANIM) {
|
if (DEBUG_ANIM) {
|
||||||
RuntimeException e = null;
|
RuntimeException e = null;
|
||||||
@@ -8608,11 +8623,13 @@ public class WindowManagerService extends IWindowManager.Stub
|
|||||||
wtoken.deferClearAllDrawn = false;
|
wtoken.deferClearAllDrawn = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean useAlternateThumbnailAnimation =
|
||||||
|
SystemProperties.getBoolean("persist.anim.use_alt_thumbnail", false);
|
||||||
AppWindowAnimator appAnimator =
|
AppWindowAnimator appAnimator =
|
||||||
topOpeningApp == null ? null : topOpeningApp.mAppAnimator;
|
topOpeningApp == null ? null : topOpeningApp.mAppAnimator;
|
||||||
Bitmap nextAppTransitionThumbnail = mAppTransition.getNextAppTransitionThumbnail();
|
Bitmap nextAppTransitionThumbnail = mAppTransition.getNextAppTransitionThumbnail();
|
||||||
if (nextAppTransitionThumbnail != null && appAnimator != null
|
if (!useAlternateThumbnailAnimation && nextAppTransitionThumbnail != null
|
||||||
&& appAnimator.animation != null) {
|
&& appAnimator != null && appAnimator.animation != null) {
|
||||||
// This thumbnail animation is very special, we need to have
|
// This thumbnail animation is very special, we need to have
|
||||||
// an extra surface with the thumbnail included with the animation.
|
// an extra surface with the thumbnail included with the animation.
|
||||||
Rect dirty = new Rect(0, 0, nextAppTransitionThumbnail.getWidth(),
|
Rect dirty = new Rect(0, 0, nextAppTransitionThumbnail.getWidth(),
|
||||||
@@ -8636,8 +8653,8 @@ public class WindowManagerService extends IWindowManager.Stub
|
|||||||
drawSurface.release();
|
drawSurface.release();
|
||||||
appAnimator.thumbnailLayer = topOpeningLayer;
|
appAnimator.thumbnailLayer = topOpeningLayer;
|
||||||
DisplayInfo displayInfo = getDefaultDisplayInfoLocked();
|
DisplayInfo displayInfo = getDefaultDisplayInfoLocked();
|
||||||
Animation anim = mAppTransition.createThumbnailAnimationLocked(
|
Animation anim = mAppTransition.createThumbnailScaleAnimationLocked(
|
||||||
transit, true, true, displayInfo.appWidth, displayInfo.appHeight);
|
displayInfo.appWidth, displayInfo.appHeight, transit);
|
||||||
appAnimator.thumbnailAnimation = anim;
|
appAnimator.thumbnailAnimation = anim;
|
||||||
anim.restrictDuration(MAX_ANIMATION_DURATION);
|
anim.restrictDuration(MAX_ANIMATION_DURATION);
|
||||||
anim.scaleCurrentDuration(mTransitionAnimationScale);
|
anim.scaleCurrentDuration(mTransitionAnimationScale);
|
||||||
|
|||||||
@@ -113,6 +113,11 @@ class WindowStateAnimator {
|
|||||||
float mAlpha = 0;
|
float mAlpha = 0;
|
||||||
float mLastAlpha = 0;
|
float mLastAlpha = 0;
|
||||||
|
|
||||||
|
boolean mHasClipRect;
|
||||||
|
Rect mClipRect = new Rect();
|
||||||
|
Rect mTmpClipRect = new Rect();
|
||||||
|
Rect mLastClipRect = new Rect();
|
||||||
|
|
||||||
// Used to save animation distances between the time they are calculated and when they are
|
// Used to save animation distances between the time they are calculated and when they are
|
||||||
// used.
|
// used.
|
||||||
int mAnimDw;
|
int mAnimDw;
|
||||||
@@ -951,6 +956,7 @@ class WindowStateAnimator {
|
|||||||
if (screenAnimation) {
|
if (screenAnimation) {
|
||||||
tmpMatrix.postConcat(screenRotationAnimation.getEnterTransformation().getMatrix());
|
tmpMatrix.postConcat(screenRotationAnimation.getEnterTransformation().getMatrix());
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO (multidisplay): Magnification is supported only for the default display.
|
//TODO (multidisplay): Magnification is supported only for the default display.
|
||||||
if (mService.mAccessibilityController != null && displayId == Display.DEFAULT_DISPLAY) {
|
if (mService.mAccessibilityController != null && displayId == Display.DEFAULT_DISPLAY) {
|
||||||
MagnificationSpec spec = mService.mAccessibilityController
|
MagnificationSpec spec = mService.mAccessibilityController
|
||||||
@@ -985,6 +991,7 @@ class WindowStateAnimator {
|
|||||||
// transforming since it is more important to have that
|
// transforming since it is more important to have that
|
||||||
// animation be smooth.
|
// animation be smooth.
|
||||||
mShownAlpha = mAlpha;
|
mShownAlpha = mAlpha;
|
||||||
|
mHasClipRect = false;
|
||||||
if (!mService.mLimitedAlphaCompositing
|
if (!mService.mLimitedAlphaCompositing
|
||||||
|| (!PixelFormat.formatHasAlpha(mWin.mAttrs.format)
|
|| (!PixelFormat.formatHasAlpha(mWin.mAttrs.format)
|
||||||
|| (mWin.isIdentityMatrix(mDsDx, mDtDx, mDsDy, mDtDy)
|
|| (mWin.isIdentityMatrix(mDsDx, mDtDx, mDsDy, mDtDy)
|
||||||
@@ -998,6 +1005,10 @@ class WindowStateAnimator {
|
|||||||
}
|
}
|
||||||
if (appTransformation != null) {
|
if (appTransformation != null) {
|
||||||
mShownAlpha *= appTransformation.getAlpha();
|
mShownAlpha *= appTransformation.getAlpha();
|
||||||
|
if (appTransformation.hasClipRect()) {
|
||||||
|
mClipRect.set(appTransformation.getClipRect());
|
||||||
|
mHasClipRect = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (mAnimator.mUniverseBackground != null) {
|
if (mAnimator.mUniverseBackground != null) {
|
||||||
mShownAlpha *= mAnimator.mUniverseBackground.mUniverseTransform.getAlpha();
|
mShownAlpha *= mAnimator.mUniverseBackground.mUniverseTransform.getAlpha();
|
||||||
@@ -1149,15 +1160,29 @@ class WindowStateAnimator {
|
|||||||
applyDecorRect(w.mDecorFrame);
|
applyDecorRect(w.mDecorFrame);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!w.mSystemDecorRect.equals(w.mLastSystemDecorRect)) {
|
// By default, the clip rect is the system decor rect
|
||||||
w.mLastSystemDecorRect.set(w.mSystemDecorRect);
|
Rect clipRect = w.mSystemDecorRect;
|
||||||
|
if (mHasClipRect) {
|
||||||
|
|
||||||
|
// If we have an animated clip rect, intersect it with the system decor rect
|
||||||
|
int offsetTop = w.mSystemDecorRect.top;
|
||||||
|
mTmpClipRect.set(w.mSystemDecorRect);
|
||||||
|
mTmpClipRect.offset(0, -offsetTop);
|
||||||
|
mTmpClipRect.intersect(mClipRect);
|
||||||
|
mTmpClipRect.offset(0, offsetTop);
|
||||||
|
clipRect = mTmpClipRect;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!clipRect.equals(mLastClipRect)) {
|
||||||
|
mLastClipRect.set(clipRect);
|
||||||
try {
|
try {
|
||||||
if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(w,
|
if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(w,
|
||||||
"CROP " + w.mSystemDecorRect.toShortString(), null);
|
"CROP " + clipRect.toShortString(), null);
|
||||||
mSurfaceControl.setWindowCrop(w.mSystemDecorRect);
|
mSurfaceControl.setWindowCrop(clipRect);
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
Slog.w(TAG, "Error setting crop surface of " + w
|
Slog.w(TAG, "Error setting crop surface of " + w
|
||||||
+ " crop=" + w.mSystemDecorRect.toShortString(), e);
|
+ " crop=" + clipRect.toShortString(), e);
|
||||||
if (!recoveringMemory) {
|
if (!recoveringMemory) {
|
||||||
mService.reclaimSomeSurfaceMemoryLocked(this, "crop", true);
|
mService.reclaimSomeSurfaceMemoryLocked(this, "crop", true);
|
||||||
}
|
}
|
||||||
@@ -1302,8 +1327,8 @@ class WindowStateAnimator {
|
|||||||
mSurfaceLayer = mAnimLayer;
|
mSurfaceLayer = mAnimLayer;
|
||||||
mSurfaceControl.setLayer(mAnimLayer);
|
mSurfaceControl.setLayer(mAnimLayer);
|
||||||
mSurfaceControl.setMatrix(
|
mSurfaceControl.setMatrix(
|
||||||
mDsDx*w.mHScale, mDtDx*w.mVScale,
|
mDsDx * w.mHScale, mDtDx * w.mVScale,
|
||||||
mDsDy*w.mHScale, mDtDy*w.mVScale);
|
mDsDy * w.mHScale, mDtDy * w.mVScale);
|
||||||
|
|
||||||
if (mLastHidden && mDrawState == HAS_DRAWN) {
|
if (mLastHidden && mDrawState == HAS_DRAWN) {
|
||||||
if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(w,
|
if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(w,
|
||||||
|
|||||||
Reference in New Issue
Block a user