Android的应用启动时,或者切换Activity时都会以动画的方式显示前后两屏的切换过程。动画的原理很简单,把一帧一帧的图像按一定时间间隔显示出来就完成了。
动画的绘制需要定时驱动,通常的做法是启动一个定时消息,每隔一定时间发一个消息,收到消息后输出一帧画面。Android支持VSync信号后,动画的驱动就有VSync信号承担了。
窗口动画的基本元素是窗口Surface中保存的图像,通过对窗口的Surface设置不同的变换矩阵和透明度,然后强制Surface刷新,就能在屏幕上显示出窗口的变化过程。
Choreographer对象初始化
我们先来看WMS中的mChoreographer 变量
final Choreographer mChoreographer = Choreographer.getInstance();
该变量是一个线程局部存储变量,在它的initialValue中创建了Choreographer对象并返回。这里使用线程局部存储的目录就是保证在线程中只有一个Choreographer对象。
-
public static Choreographer getInstance() {
-
return sThreadInstance.get();
-
}
-
private
static final ThreadLocal<Choreographer> sThreadInstance =
-
new ThreadLocal<Choreographer>() {
-
@Override
-
protected Choreographer initialValue() {
-
Looper looper = Looper.myLooper();
-
if (looper == null) {
-
throw
new IllegalStateException(
"The current thread must have a looper!");
-
}
-
return
new Choreographer(looper);
-
}
-
};
再来看下Choreographer的构造函数,这里主要是创建了FrameDisplayEventReceiver用来接受VSync信号的对象。
-
private Choreographer(Looper looper) {
-
mLooper = looper;
-
mHandler =
new FrameHandler(looper);
-
mDisplayEventReceiver = USE_VSYNC ?
new FrameDisplayEventReceiver(looper) : null;
//接受VSync信号对象
-
mLastFrameTimeNanos = Long.MIN_VALUE;
-
-
mFrameIntervalNanos = (
long)(
1000000000 / getRefreshRate());
//计算刷新的时间间隔
-
-
mCallbackQueues =
new CallbackQueue[CALLBACK_LAST +
1];
-
for (
int i =
0; i <= CALLBACK_LAST; i++) {
-
mCallbackQueues[i] =
new CallbackQueue();
-
}
-
}
FrameDisplayEventReceiver接受VSync信号
我们在http://blog.csdn.net/kc58236582/article/details/52892384( Android6.0 VSync信号如何到用户进程 )这篇博客已经分析过FrameDisplayEventReceiver的原理了,当VSync信号过来时,最后会调用到FrameDisplayEventReceiver类的onVsync函数:
-
@
Override
-
public
void
onVsync
(long timestampNanos, int builtInDisplayId, int frame) {
-
if (builtInDisplayId != SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN) {
-
scheduleVsync();
-
return;
-
}
-
-
-
long now = System.nanoTime();
-
if (timestampNanos > now) {
-
Log.w(TAG,
"Frame time is " + ((timestampNanos - now) *
0.000001f)
-
+
" ms in the future! Check that graphics HAL is generating vsync "
-
+
"timestamps using the correct timebase.");
-
timestampNanos = now;
-
}
-
-
if (mHavePendingVsync) {
-
Log.w(TAG,
"Already have a pending vsync event. There should only be "
-
+
"one at a time.");
-
}
else {
-
mHavePendingVsync =
true;
-
}
-
-
mTimestampNanos = timestampNanos;
-
mFrame = frame;
-
Message msg = Message.obtain(mHandler,
this);
-
msg.setAsynchronous(
true);
-
mHandler.sendMessageAtTime(msg, timestampNanos / TimeUtils.NANOS_PER_MS);
-
}
这主要是发送了一个信号,而是是Runnable的那种消息。
因此我们主要看下这个类的run函数,这里就是调用了Choreographer的doFrame函数。
-
@
Override
-
public
void
run
() {
-
mHavePendingVsync =
false;
-
doFrame(mTimestampNanos, mFrame);
-
}
doFrame函数
doFrame函数主要有一些VSync时间逻辑处理如果抛弃该VSync信号的话会调用scheduleVsyncLocked函数让SurfaceFlinger发送一个VSync信号,如果正常会调用4个doCallBacks函数。
-
void doFrame(long frameTimeNanos, int frame) {
-
final
long startNanos;
-
synchronized (mLock) {
-
......
-
-
long intendedFrameTimeNanos = frameTimeNanos;
-
startNanos = System.nanoTime();
-
final
long jitterNanos = startNanos - frameTimeNanos;
-
if (jitterNanos >= mFrameIntervalNanos) {
-
final
long skippedFrames = jitterNanos / mFrameIntervalNanos;
-
final
long lastFrameOffset = jitterNanos % mFrameIntervalNanos;
-
frameTimeNanos = startNanos - lastFrameOffset;
-
}
-
-
if (frameTimeNanos < mLastFrameTimeNanos) {
-
if (DEBUG_JANK) {
-
Log.d(TAG,
"Frame time appears to be going backwards. May be due to a "
-
+
"previously skipped frame. Waiting for next vsync.");
-
}
-
scheduleVsyncLocked();
//让SurfaceFlinger立马发送一个VSync信号
-
return;
-
}
-
-
mFrameInfo.setVsync(intendedFrameTimeNanos, frameTimeNanos);
-
mFrameScheduled =
false;
-
mLastFrameTimeNanos = frameTimeNanos;
-
}
-
-
try {
-
Trace.traceBegin(Trace.TRACE_TAG_VIEW,
"Choreographer#doFrame");
-
-
mFrameInfo.markInputHandlingStart();
-
doCallbacks(Choreographer.CALLBACK_INPUT, frameTimeNanos);
//按键相关
-
-
mFrameInfo.markAnimationsStart();
-
doCallbacks(Choreographer.CALLBACK_ANIMATION, frameTimeNanos);
//动画相关
-
-
mFrameInfo.markPerformTraversalsStart();
-
doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameTimeNanos);
//power相关
-
-
doCallbacks(Choreographer.CALLBACK_COMMIT, frameTimeNanos);
-
} finally {
-
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
-
}
-
}
doCallbacks函数,我们首先会检查当前这个CallBackType是否有对应的CallBack回调,如果没有直接return,如果有的话会调用其回调的run函数。
-
void doCallbacks(int callbackType, long frameTimeNanos) {
-
CallbackRecord callbacks;
-
synchronized (mLock) {
-
final
long now = System.nanoTime();
-
callbacks = mCallbackQueues[callbackType].extractDueCallbacksLocked(
-
now / TimeUtils.NANOS_PER_MS);
-
if (callbacks == null) {
//没有对应CallBack回调
-
return;
-
}
-
mCallbacksRunning =
true;
-
-
// safe by ensuring the commit time is always at least one frame behind.
-
if (callbackType == Choreographer.CALLBACK_COMMIT) {
-
final
long jitterNanos = now - frameTimeNanos;
-
Trace.traceCounter(Trace.TRACE_TAG_VIEW,
"jitterNanos", (
int) jitterNanos);
-
if (jitterNanos >=
2 * mFrameIntervalNanos) {
-
final
long lastFrameOffset = jitterNanos % mFrameIntervalNanos
-
+ mFrameIntervalNanos;
-
if (DEBUG_JANK) {
-
mDebugPrintNextFrameTimeDelta =
true;
-
}
-
frameTimeNanos = now - lastFrameOffset;
-
mLastFrameTimeNanos = frameTimeNanos;
-
}
-
}
-
}
-
try {
-
for (CallbackRecord c = callbacks; c != null; c = c.next) {
-
c.run(frameTimeNanos);
//调用回调run函数
-
}
-
}
-
......
-
}
这也就意味着当你没有CallBackType对应的回调,每次VSync信号过来到doFrame函数再到doCallBacks函数都是没有意义的。
WMS启动动画
那我们下面看在哪里把CallBackType对应的回调加入了,这里我们只关注动画相关的。
上面我们说到VSync会不断的发送,每秒60多次,但是动画不会不停的播放,就是这个CallBackType对应的回调没有。哪动画的启动和结束也就是受这个影响,而就是在WMS中调用scheduleAnimationLocked函数发起的动画启动。
-
void scheduleAnimationLocked() {
-
if (!mAnimationScheduled) {
-
mAnimationScheduled =
true;
-
mChoreographer.postFrameCallback(mAnimator.mAnimationFrameCallback);
-
}
-
}
这里就是调用Choreographer设置CallBackType,相关的回调。这里我们的callbackType是CALLBACK_ANIMATION
-
public void postFrameCallback(FrameCallback callback) {
-
postFrameCallbackDelayed(callback,
0);
-
}
-
-
public void postFrameCallbackDelayed(FrameCallback callback, long delayMillis) {
-
if (callback == null) {
-
throw
new IllegalArgumentException(
"callback must not be null");
-
}
-
-
postCallbackDelayedInternal(CALLBACK_ANIMATION,
-
callback, FRAME_CALLBACK_TOKEN, delayMillis);
-
}
我们最后看postCallbackDelayedInternal函数,就是在mCallBackQueues对应的CallBackType中增加相应的回调。这里也就是前面在WMS的scheduleAnimationLocked的参数mAnimator.mAnimationFrameCallback就是回调。
-
private void postCallbackDelayedInternal(int callbackType,
-
Object action, Object token, long delayMillis) {
-
synchronized (mLock) {
-
final
long now = SystemClock.uptimeMillis();
-
final
long dueTime = now + delayMillis;
-
mCallbackQueues[callbackType].addCallbackLocked(dueTime, action, token);
-
-
if (dueTime <= now) {
-
scheduleFrameLocked(now);
-
}
else {
-
Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_CALLBACK, action);
-
msg.arg1 = callbackType;
-
msg.setAsynchronous(
true);
-
mHandler.sendMessageAtTime(msg, dueTime);
-
}
-
}
-
}
我们来看下scheduleFrameLocked函数,我们注意mFrameScheduled这个变量,这个时候赋值为true,后面就是用这个变量来控制每次VSync信号过来调用doFrame函数的时候是否要播放动画
-
private void scheduleFrameLocked(long now) {
-
if (!mFrameScheduled) {
-
mFrameScheduled =
true;
//注意这个变量
-
if (USE_VSYNC) {
-
if (isRunningOnLooperThreadLocked()) {
-
scheduleVsyncLocked();
//尽快让SurfaceFlinger中的EventThread发送一个VSync信号
-
}
else {
-
Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_VSYNC);
-
msg.setAsynchronous(
true);
-
mHandler.sendMessageAtFrontOfQueue(msg);
-
}
-
}
else {
-
final
long nextFrameTime = Math.max(
-
mLastFrameTimeNanos / TimeUtils.NANOS_PER_MS + sFrameDelay, now);
-
if (DEBUG_FRAMES) {
-
Log.d(TAG,
"Scheduling next frame in " + (nextFrameTime - now) +
" ms.");
-
}
-
Message msg = mHandler.obtainMessage(MSG_DO_FRAME);
-
msg.setAsynchronous(
true);
-
mHandler.sendMessageAtTime(msg, nextFrameTime);
-
}
-
}
-
}
我们再回过头来看doFrame函数,当mFrameScheduled为false时,VSync信号过来该函数直接return不会播放动画。
-
void doFrame(long frameTimeNanos, int frame) {
-
final
long startNanos;
-
synchronized (mLock) {
-
if (!mFrameScheduled) {
-
return;
// no work to do
-
}
继续看postCallbackDelayedInternal函数中增加的回调,这个回调在WindowAnimator的构造函数中就新建了Choreographer.FrameCallback回调
-
WindowAnimator(final WindowManagerService service) {
-
mService = service;
-
mContext = service.mContext;
-
mPolicy = service.mPolicy;
-
-
mAnimationFrameCallback =
new Choreographer.FrameCallback() {
-
public
void doFrame(
long frameTimeNs) {
-
synchronized (mService.mWindowMap) {
-
mService.mAnimationScheduled =
false;
-
animateLocked(frameTimeNs);
-
}
-
}
-
};
-
}
我们最后看回调的run函数,如果是FRAME_CALLBACK_TOKEN,就是调用回调的doFrame函数。
-
private
static final
class CallbackRecord {
-
public CallbackRecord next;
-
public
long dueTime;
-
public Object action;
// Runnable or FrameCallback
-
public Object token;
-
-
public void run(long frameTimeNanos) {
-
if (token == FRAME_CALLBACK_TOKEN) {
-
((FrameCallback)action).doFrame(frameTimeNanos);
-
}
else {
-
((Runnable)action).run();
-
}
-
}
-
}
播放动画
在上面doFrame函数启动动画,而动画的播放主要在WindowAnimator的animateLocked函数。
-
private void animateLocked(long frameTimeNs) {
-
......
-
boolean wasAnimating = mAnimating;
-
mAnimating =
false;
//设置mAnimating为false
-
mAppWindowAnimating =
false;
-
-
SurfaceControl.openTransaction();
-
SurfaceControl.setAnimationTransaction();
-
try {
-
final
int numDisplays = mDisplayContentsAnimators.size();
-
for (
int i =
0; i < numDisplays; i++) {
-
final
int displayId = mDisplayContentsAnimators.keyAt(i);
-
updateAppWindowsLocked(displayId);
-
......
-
-
// Update animations of all applications, including those
-
// associated with exiting/removed apps
-
updateWindowsLocked(displayId);
-
updateWallpaperLocked(displayId);
-
-
final WindowList windows = mService.getWindowListLocked(displayId);
-
final
int N = windows.size();
-
for (
int j =
0; j < N; j++) {
-
windows.get(j).mWinAnimator.prepareSurfaceLocked(
true);
//输出动画帧
-
}
-
}
-
-
for (
int i =
0; i < numDisplays; i++) {
-
final
int displayId = mDisplayContentsAnimators.keyAt(i);
-
-
testTokenMayBeDrawnLocked(displayId);
-
-
final ScreenRotationAnimation screenRotationAnimation =
-
mDisplayContentsAnimators.valueAt(i).mScreenRotationAnimation;
-
if (screenRotationAnimation != null) {
-
screenRotationAnimation.updateSurfacesInTransaction();
-
}
-
-
mAnimating |= mService.getDisplayContentLocked(displayId).animateDimLayers();
-
-
if (mService.mAccessibilityController != null
-
&& displayId == Display.DEFAULT_DISPLAY) {
-
mService.mAccessibilityController.drawMagnifiedRegionBorderIfNeededLocked();
-
}
-
}
-
-
if (mAnimating) {
//为true,继续调用WMS的scheduleAnimationLocked播放下一帧
-
mService.scheduleAnimationLocked();
-
}
-
-
......
-
finally {
-
SurfaceControl.closeTransaction();
-
}
-
-
......
-
boolean doRequest =
false;
-
if (mBulkUpdateParams !=
0) {
-
doRequest = mService.copyAnimToLayoutParamsLocked();
-
}
-
-
if (hasPendingLayoutChanges || doRequest) {
-
mService.requestTraversalLocked();
//重新刷新UI
-
}
-
-
if (!mAnimating && wasAnimating) {
-
mService.requestTraversalLocked();
-
}
-
}
animateLocked方法先将mAnimating 设置为false,然后调用updateWindowsLocked函数和updateWallpaperLocked函数,updateWindowsLocked这个函数会调用WindowStateAnimator类的stepAnimationLocker方法,如果动画已经显示完最后一帧,stepAnimationLocker方法将会WindowStateAnimator类的mAnimating设置为false,表示该窗口的动画已经结束。而在updateWallpaperLocked函数中会判断所有窗口的动画是否已经结束,只要有一个动画没结束,就会将winAnimator的mAnimating设置为true。
-
for (
int i = windows.size() -
1; i >=
0; i--) {
-
final WindowState win = windows.get(i);
-
WindowStateAnimator winAnimator = win.mWinAnimator;
-
if (winAnimator.mSurfaceControl == null) {
-
continue;
-
}
-
-
final
int flags = win.mAttrs.flags;
-
-
if (winAnimator.mAnimating) {
-
......
-
mAnimating =
true;
-
}
-
......
再回到animatelocked方法,当mAnimating为true是会调用WMS的scheduleAnimationLocked方法继续显示动画,否则动画显示就结束了。
下面我们总结下动画的播放过程:需要播放动画时,先会调用WMS的scheduleAnimationLocked方法。调用这个方法后,才会接受并处理一次VSync信号,对VSync信号的处理,就是所有需要绘制的窗口根据各自动画的谁知重新调整窗口Surface的变化矩阵和透明度;如果还有窗口动画需要显示,继续调用scheduleAnimationLocked方法准备下一帧。
准备一帧动画的时间可以跨越多个VSync信号周期,但是只有收到VSync信号才能更新窗口的Surface的属性和内容,对应用而言收到VSync信号意味着SurfaceFlinger中已经把上次设置的动画数据取走了,可以安全地设置下一帧动画的属性和内容了。
窗口动画对象WindowStateAnimator
窗口对象WindowState中定义了一个类型为WindowStateAnimator的成员变量mWinAnimator,用来表示窗口的动画对象。
下面是一些成员变量
-
boolean mAnimating;
//表示是否正在显示动画
-
boolean mLocalAnimating;
//表示窗口动画是否已经初始化
-
Animation mAnimation;
//表示窗口动画对象
-
boolean mAnimationIsEntrance;
//
-
boolean mHasTransformation;
//表示当前动画的mTransformation是否可用
-
boolean mHasLocalTransformation;
//表示当前动画时一个窗口动画还是Activity动画
-
final Transformation mTransformation =
new Transformation();
//变换矩阵对象
当前正在显示的动画有两种类型,一种的窗口切换动画,一种是Activity切换动画,这里使用了mLocalAnimating和mHasLocalTransformation分别表示窗口动画的状态。
stepAnimationLocked是WindowStateAnimator类中显示动画首先调用的方法,它会初始化WindowStateAnimator对象的一些成员变量
-
boolean stepAnimationLocked(long currentTime) {
-
final DisplayContent displayContent = mWin.getDisplayContent();
-
if (displayContent != null && mService.okToDisplay()) {
-
-
if (mWin.isDrawnLw() && mAnimation != null) {
//窗口准备好绘制了,窗口动画对象不为空
-
mHasTransformation =
true;
-
mHasLocalTransformation =
true;
-
if (!mLocalAnimating) {
//还没有初始化窗口对象
-
final DisplayInfo displayInfo = displayContent.getDisplayInfo();
-
if (mAnimateMove) {
-
mAnimateMove =
false;
-
mAnimation.initialize(mWin.mFrame.width(), mWin.mFrame.height(),
//初始化窗口对象
-
mAnimDw, mAnimDh);
-
}
else {
-
mAnimation.initialize(mWin.mFrame.width(), mWin.mFrame.height(),
-
displayInfo.appWidth, displayInfo.appHeight);
-
}
-
mAnimDw = displayInfo.appWidth;
-
mAnimDh = displayInfo.appHeight;
-
mAnimation.setStartTime(mAnimationStartTime !=
-1
-
? mAnimationStartTime
-
: currentTime);
-
mLocalAnimating =
true;
// 设置为true代表已经初始化窗口对象
-
mAnimating =
true;
-
}
-
if ((mAnimation != null) && mLocalAnimating) {
-
mLastAnimationTime = currentTime;
-
if (stepAnimation(currentTime)) {
//通过时间判断动画是否显示完毕
-
return
true;
-
}
-
}
-
}
-
mHasLocalTransformation =
false;
-
if ((!mLocalAnimating || mAnimationIsEntrance) && mAppAnimator != null
//没有设置窗口动画或者窗口动画结束了
-
&& mAppAnimator.animation != null) {
-
// 如果有Activity动画,将mAnimating设为true
-
mAnimating =
true;
-
mHasTransformation =
true;
-
mTransformation.clear();
-
return
false;
-
}
else
if (mHasTransformation) {
-
// Little trick to get through the path below to act like
-
// we have finished an animation.
-
mAnimating =
true;
-
}
else
if (isAnimating()) {
-
mAnimating =
true;
-
}
-
}
else
if (mAnimation != null) {
-
mAnimating =
true;
-
}
-
-
if (!mAnimating && !mLocalAnimating) {
-
return
false;
-
}
-
-
-
mAnimating =
false;
-
mKeyguardGoingAwayAnimation =
false;
-
mAnimatingMove =
false;
-
mLocalAnimating =
false;
-
......
-
mHasLocalTransformation =
false;
-
......
-
mTransformation.clear();
-
......
-
-
return
false;
-
}
该方法的工作就是设置WindowStateAnimator对象的几个成员变量,首先调用WindowState对象的isDrawnLw来判断窗口系统的状态,只有准备好了才能显示,接着判断mAnimation是否为空,不为空代表已经设置好了动画对象。
接下来判断mLocalAnimating变量的值,为false则调用mAnimation的intialize方法来完成动画对象的初始化(主要设置动画的高度和宽度),然后将mLocalAnimating和mAnimating设为true。完成初始化后,接着调用stepAnimation方法来判断动画是否已经显示完成,没有完成返回true。
如果没有设置动画或者动画已经结束了,则还有判断窗口所在的Activity是否还存在动画,如果有,将mAnimating设置true(表示还要继续播放动画),如果同时mHasTransformation的值仍然为true,或者isAnimating方法返回true,也将mAnimating设置为true。
isAnimating会根据当前动画对象mAnimation是否为空,它的附加窗口的动画对象是否为空,以及窗口所在的Activity的动画对象是否为空等条件来判断,这表示只要有可能mAnimating就会设置为true。这样的目的尽量让动画完成显示,即使没有可显示的动画,多刷新几次不会有副作用,但如果少画了一次,屏幕上就可能留下不正确画面了。
-
boolean isAnimating() {
-
return mAnimation != null
-
|| (mAttachedWinAnimator != null && mAttachedWinAnimator.mAnimation != null)
-
|| (mAppAnimator != null && mAppAnimator.isAnimating());
-
}
动画生成及显示
我们再看看动画的生成过程,WindowStateAnimator的prepareSurfaceLocked方法来完成计算一帧动画并显示工作:
-
public void prepareSurfaceLocked(final boolean recoveringMemory) {
-
......
-
computeShownFrameLocked();
//计算要显示的动画帧
-
-
setSurfaceBoundariesLocked(recoveringMemory);
-
-
if (mIsWallpaper && !mWin.mWallpaperVisible) {
-
hide();
//如果是壁纸窗口,隐藏
-
}
else
if (w.mAttachedHidden || !w.isOnScreen()) {
-
hide();
//如果窗口不可见,隐藏
-
......
-
}
else
if (mLastLayer != mAnimLayer
-
|| mLastAlpha != mShownAlpha
-
|| mLastDsDx != mDsDx
-
|| mLastDtDx != mDtDx
-
|| mLastDsDy != mDsDy
-
|| mLastDtDy != mDtDy
-
|| w.mLastHScale != w.mHScale
-
|| w.mLastVScale != w.mVScale
-
|| mLastHidden) {
//每个值是否有变化
-
displayed =
true;
-
mLastAlpha = mShownAlpha;
-
mLastLayer = mAnimLayer;
-
mLastDsDx = mDsDx;
-
mLastDtDx = mDtDx;
-
mLastDsDy = mDsDy;
-
mLastDtDy = mDtDy;
-
w.mLastHScale = w.mHScale;
-
w.mLastVScale = w.mVScale;
-
-
if (mSurfaceControl != null) {
-
try {
-
mSurfaceAlpha = mShownAlpha;
-
mSurfaceControl.setAlpha(mShownAlpha);
-
mSurfaceLayer = mAnimLayer;
-
mSurfaceControl.setLayer(mAnimLayer);
-
mSurfaceControl.setMatrix(
-
mDsDx * w.mHScale, mDtDx * w.mVScale,
-
mDsDy * w.mHScale, mDtDy * w.mVScale);
-
-
if (mLastHidden && mDrawState == HAS_DRAWN) {
-
if (showSurfaceRobustlyLocked()) {
//输出动画帧
-
mLastHidden =
false;
-
if (mIsWallpaper) {
-
mService.dispatchWallpaperVisibility(w,
true);
-
}
-
mAnimator.setPendingLayoutChanges(w.getDisplayId(),
-
WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM);
-
}
else {
-
w.mOrientationChanging =
false;
-
}
-
}
-
if (mSurfaceControl != null) {
-
w.mToken.hasVisible =
true;
-
}
-
}
catch (RuntimeException e) {
-
Slog.w(TAG,
"Error updating surface in " + w, e);
-
if (!recoveringMemory) {
-
mService.reclaimSomeSurfaceMemoryLocked(
this,
"update",
true);
-
}
-
}
-
}
-
}
-
......
-
}
该函数先调用了computeShownFrameLocked函数计算当前需要显示的动画帧数据,mAnimLayer表示窗口的Z轴、mShownAlpha窗口透明度;mDsDx、mDtDx、mDsDy和mDtDy表示二维变换矩阵;w.mHScale w.mVScale表示窗口的缩放比例
只有计算出的数据和上一次数据不一样才会调用showSurfaceRobustlyLocked输出动画帧。
我们再来看WindowStateAnimator的prepareSurfaceLocked函数中下面一段代码,会调用showSurfaceRobustlyLocked函数显示window,当返回true代表成功,会把mLastHidden为false,代表上次没有隐藏。
-
if (showSurfaceRobustlyLocked()) {
-
mLastHidden =
false;
-
if (mIsWallpaper) {
-
mService.dispatchWallpaperVisibility(w,
true);
-
}
-
// This draw means the difference between unique content and mirroring.
-
// Run another pass through performLayout to set mHasContent in the
-
// LogicalDisplay.
-
mAnimator.setPendingLayoutChanges(w.getDisplayId(),
-
WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM);
-
}
else {
-
w.mOrientationChanging =
false;
-
}
我们再来看下showSurfaceRobustlyLocked函数,会调用mSurfaceControl的show函数显示窗口,当然这中间如果出错,或者没有mSurfaceControl对象,会调用WMS的reclaimSomeSurfaceMemoryLocked来回收系统资源。
-
boolean showSurfaceRobustlyLocked() {
-
try {
-
if (mSurfaceControl != null) {
-
mSurfaceShown =
true;
-
mSurfaceControl.show();
-
if (mWin.mTurnOnScreen) {
-
if (DEBUG_VISIBILITY) Slog.v(TAG,
-
"Show surface turning screen on: " + mWin);
-
mWin.mTurnOnScreen =
false;
-
mAnimator.mBulkUpdateParams |= SET_TURN_ON_SCREEN;
-
}
-
}
-
return
true;
-
}
catch (RuntimeException e) {
-
Slog.w(TAG,
"Failure showing surface " + mSurfaceControl +
" in " + mWin, e);
-
}
-
-
mService.reclaimSomeSurfaceMemoryLocked(
this,
"show",
true);
-
-
return
false;
-
}