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