WindowManagerService (4) 动画系统 - l-feng/l-feng.github.io GitHub Wiki

Wms不负责窗口的的具体绘制,因此wms动画系统仅会影响 窗口的位置,显示尺寸,与透明度,不会影响窗口所绘制的内容,

窗口内容的动画在窗口的客户端由ViewRootImpl驱动完成。另外动画系统中所显示尺寸与布局过程中的Surfacede 实际尺寸,

这个尺寸决定了其GraphicBuffer的大小以及Canvas可以绘制的区域。则动画过程中的尺寸则是渲染尺寸,只是在输入过程

中将Surface的内容放大放小。

一:android动画原理简介

1:Animation类与Transform

Android提供了平移,缩放,旋转,以及透明度四种类型的动画。这些动画分别由TranslateAnimation类,

ScaleAnimation类,RotateAnimation类以及AlphaAniamtion类实现,他们都是Aniamtion类的子类。

2:动画驱动器Choregrapher

Choregrapher类处理回调的时机为屏幕的垂直(VSync)事件到来之时,其处理回调的过程被当做渲染下一帧的工作的一部分。

在android动画系统中使用Choregrapher和Animation实现动画

二:wms的动画系统框架

WindowManagerService.scheduleAnimationLocked()------->WindowAnimator.mAnimationRunnable()

scheduleAnimationLocked()函数主要是启动窗口动画,mAnimationRunnable()函数主要是负责处理动画帧。

scheduleAnimationLocked()解析:

1:mLayoutToAnim与其类名一样,用于保存来自布局子系统传递给系统的参数

2:判断动画帧是否已经被发送给Choregrapher,如果已经发送,则没有必要发送

3:处理动画帧的Runnable是mAnimator.mAnimationRunnable ,mAnimator在分析WMS构成时候介绍过,

它是WindowAnimator类的对象,是WMS中所有动画的管理者

mAnimationRunnable()函数解析:

使用animatelocked()函数进行动画的渲染。

三:WindowAnimator分析

1:WindowAnimator组成

WMS的窗口管理结构主要是三种成员组成:DisplayContent,WindowToken,WindowState分别对应的是屏幕,

显示组件以及窗口本身。其实动画也有与之对应的组成结构,分别是以屏幕为动画目标的DisplayContentAnimator,

以Activity为动画目标的APPWindowAnimator,以及以窗口为目标的WindowStateAnimator。。

而WindowAnimator主要是协调他们之间的工作,另外WMS管理的不仅仅有窗口动画,还有一些特效动画,

如Dimming,屏幕旋转等,与之对应的还有DimAnimator以及ScreenRotateAnimation。

2:WindowAnimator的AnimateLocked()分析

2.1 记录处理当前帧之前的动画状态到wasAnimating。

2.2 首先处理AppWindowAnimator的动画

2.3 处理屏幕旋转动画

2.4 接下来处理WindowStateAnimator动画

2.5 渲染动画

2.6 渲染Dimming和屏幕旋转效果

2.7 如果有必要,向布局系统请求一次布局

2.8 如果仍有动画处于动画状态,通过wms安排下一帧的工作

四:深入窗口动画

1:WindowStateAnimator

WindowStateAnimator在WindowState的构造函数中随之一起被创建,二者互持对方的引用。WindowState

保存了窗口管理方面的属性,而WindowStateAnimator则保存了窗口的surface的属性。前者重于窗口的管理,

后者重于窗口的显示,

2:开始动画窗口

2.1动画的选择与设置

在wms的relayoutWindow()函数中,当窗口由不可见变为可见时候,执行了下面一条:

winAnimator.applyEnterAnimationLocked();

该函数将会为当前窗口开始一个淡入动画,将窗口显示出来。他调用了WSA中更为通用的启动窗口的函数

applyAnimationLocked()。

调用的具体方法:

relayoutWindow()--->winAnimator.applyEnterAnimationLocked()--->WindowStateAnimator.setAnimation()

具体的函数太懒了就不详细列出来了,从上面的几个函数可以看出,WSA其实并没有给WMS非常大的自由去选择任意的动画,

WMS需要通过一个trransit参数向WSA提出动画的意图,WMP和WSA在根据此意图选择一个既有动画保存在mAnimation中。

2.2 从布局系统到动画系统

重新回到WMS的relayoutWindow()函数,随后它调用了perforLayoutAndPlaceSurfaceLocked()

函数,重新发起一次布局,在布局的最后阶段,调用updateLayoutToAnimationLocked()将包括WSA在内

的所有的Animator传递给动画系统。布局系统将所有布局后的窗口的WSA保存至mLayoutToAnim对象,然后

安排动画系统处理下一帧的操作。mlayoutToAnim就像一辆列车,载满了WSA驶向动画系统

mAnimationRunnable.run()----->copyLayoutToAnimParamsLocked()------>

displayAnimator.mWinAnimators.addAll(winAnimators)------>animateLocked()

2.3 WSA的Transformation计算

animateLocked()------->performAnimationsLocked()------->updataWindowsLocked()---->

stepAnimationLocked()----->WSA.stepAnimation()---->Transformation更新

2.4 WSA的动画渲染

stepAnimationLocked之后,WSA已经做好渲染动画帧了。现在返回到animateLocked(),

在完成performAnimationsLocked()之后,再次遍历所有的DisplayContent下的所有的WSA,

animateLocked()--->prepareSurfaceLocked()----->computeShownFrameLocked()----->

setSurfaceBoundariesLocked()----->设置到surface

computeShownFrameLocked()的实现:

2.4.1: 首先将窗口缩放添加到结果矩阵中

2.4.2: 将WSA自身的Transformation添加到结果矩阵中

2.4.3: 将窗口的实际位置添加到结果矩阵中

2.4.4: 将父窗口的动画变换添加到结果矩阵中

2.4.5: 将appWindowAnimatior的变换添加到结果矩阵中

2.4.6: 将universeBackground的变换添加到结果矩阵中

2.4.7: 将screenRotationAnimation的变换加入到结果矩阵

2.4.8: 将放大镜效果添加到结果矩阵中

2.4.9: 设置透明度

六:窗口的绘制状态与新建到显示的过程

NO_SURFACE------>DRAW_PENDING------>OMMIT_DRAW_PENDING------>READY_TO_SHOW----->HAS_DRAWN