Android6.0 WMS(六) WMS动画管理(2)

2019-04-04 23:16

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函数的时候是否要播放动画

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片 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, \ }

Message msg = mHandler.obtainMessage(MSG_DO_FRAME); msg.setAsynchronous(true);

mHandler.sendMessageAtTime(msg, nextFrameTime); } } }

我们再回过头来看doFrame函数,当mFrameScheduled为false时,VSync信号过来该函数直接return不会播放动画。

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片 void doFrame(long frameTimeNanos, int frame) { final long startNanos; synchronized (mLock) {

if (!mFrameScheduled) { return; // no work to do }

继续看postCallbackDelayedInternal函数中增加的回调,这个回调在WindowAnimator的构造函数中就新建了Choreographer.FrameCallback回调

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片 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函数。

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片 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函

数。

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片 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。

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片 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,用来表示窗口的动画对象。 下面是一些成员变量

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片 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对象的一些成员变量

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片 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();


Android6.0 WMS(六) WMS动画管理(2).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:旅游资源 读书笔记

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: