Android Surface 系统简单学习

来源:互联网 发布:苹果5怎么用3g网络 编辑:程序博客网 时间:2024/05/01 05:51
wallpaper_android

####Activity的View 在应用开发的时候,我们需要设置Activity的View,就是Activity视图的部分。而Activity内部的View又究竟是怎样一个结构呢?怎么跟更贴近底层的部分交互的呢?

Activity中有一个Window,具体的实现其实是PhoneWindow对象,那些View其实就是跟这个window关联的。window又跟windowmanager相互关联(其实就是包含了一个LocalWindowManager对象,LocalWindowManager跟WindowManagerImpl都实现了WindowManager,而LocalWindowManager将它的工作委托给WindowManagerImpl去做)

其实PhoneWindow里面又包含了一个DecorView,DecorView里面包含我们使用setContentView设置的View。具体图像如下

surface1

phonewindow跟View其实根本就不是一级,WindowManager是用来管理Window的。我们平时使用WindowManager来做FlowView的时候,FlowView跟普通的Activity中的View就不是一样的,WindowManager添加的View级别相对来说更高,因为Activity中使用的View其实是添加在DecorView下面的,而DecorView里面还添加了标题栏。而最后是将decorView添加到WindowManager中的,Activity中setContentView的View与直接用WindowManager添加的View,你可以理解为两个并行独立的。

在Android的源码中,WindowManager是将View添加到一个ViewRoot当中的,这个ViewRoot是什么呢?ViewRoot继承了Handler类。写过基础的应用都知道,Handler类用来进行消息通信的。ViewRoot就是通过HandleMessage的方式来与Surface部分进行消息通信的。ViewRoot在是Activity所在的进程,ViewRoot通过Binder通信与WindowManagerService进行通信。

WindowManagerService由System_Server进程启动,SurfaceFlinger服务也在这个进程中,Activity的显然需要与WindowManagerService建立联系。

ViewRoot通过IWindowSession与WindowManagerService进行跨进程通信。

ViewRoot内部有一个W类型的对象,它也是一个机遇Binder通信的类,W是IWindow的Bn端,用于响应请求。

ViewRoot与WindowManagerService建立连接的目的是这样的,WindowManagerService所在的SystemServer进程接收到按键信息(当然也包括其他的一些信息),WindowManagerService找到UI位于屏幕顶部的进程所对应的IWindow对象,调用这个IWindow对象的dispatchKey,通过跨进程调用,最后调用ViewRoot对应的,真正处理这个事件的View。

Activity的绘制,其实就是在surface上lock一个Canvas,然后在这个Canvas上面绘制。就是这样从ViewRoot到最底层的View,一层一层地绘制,再具体的,都是由各个View自己绘制了(onDraw函数)。

Surface

Surface与RootView通信

ViewRoot有一个Surface的成员变量

  1. private final Surface mSurface = new Surface();

WindowManagerService中也有一个Surface,但是它的初始化是这样的

  1. Surface createSurfaceLocked(){
  2. ......
  3. try{
  4. mSurface = new Surface(mSession.mSurfaceSession,mSession.mPid,mAttrs.getTitle().toString(),0,w,h,mAttrs.format,flags);
  5. }
  6. ...
  7. Surface.openTransaction();
  8. ......
  9. Surface.closeTransaction();
  10. }

两个部分的Surface看似是毫无关系,但是实际上,在使用createSurfaceLocked() 的时候,会将creaeSurfaceLocked 创建的Surface copy到ViewRoot层的Surface中。也就是这样,将底层的Surface对象传到上层,供Activity的界面部分使用,用来绘图。(具体可参看源代码)。整个流程大概是这样的

  • RootView.relayoutWindow
  • WindowManagerService.Session.relayout
  • WindowManagerService.relayoutWindow
  • WindowManagerService.createSurfaceLocked()
  • outSurface.copyFrom(surface)

最后一步是将WindowManagerService的surface与ViewRoot 的outSurface联系起来的关键点,outSurface是作为参数,从RootView传到WindowManagerService的。在邓凡平的博客中,称之为乾坤大挪移

ViewRoot其实是通过Binder与WindowManagerService进行跨进程调用通信的。

Surface绘图

Surface中有一个Canvas,Canvas是用于记载画图的动作,Canvas提供了许多画图的动作,想画一个矩形,画一段文字等等。

画图需要了解这么一个函数lockCanvas,lockCanvas获取一块存储区域,然后将它与Canvas绑定在一起,然后UI在Canvas上面的绘画,就直接记录到那块存储区域了。另外lockCanvas也是可以对屏幕中的一部分区域进行绑定,进行绘制。

lock之后,需要unlock,有个unlockCanvasAndPost用来释放。

Surface入门总结

在《深入理解Android》这本书中有段总结挺好的,我截取了部分来总结

  1. 使用SurfaceControl的writeToParcel将SurfaceControl写入到Parcel中,将其设置到Java层的Surface对象中
  2. Java层根据Parcel信息包,重新构造一个Surface
  3. 调用Surface的lock
  4. UI画图
  5. 调用Surface的unlockAndPost

SurfaceFlinger

在这里还是使用《深入理解Android》的总结简单介绍

  1. 调用waitForEvent等待重绘或者事务处理
  2. 如果有事务处理请求,则调用HandleTransaction进行处理
  3. 调用handlePageFlip,对各个显示层进行PageFlip。对于Layer类,它会生成一个新的纹理。
  4. 调用handleRepaint,它会遍历各个显示层的onDraw函数
  5. 调用unlockClients,遍历各个显示层的finishPageFlip函数
  6. 调用postFrameBuffer,将混合后的内容投递屏幕

这篇文章是我对《深入理解Android》关于深入理解Surface系统部分的一个简单的总结,以及自己部分的体悟。感觉只看别人写的书,可能是无用的,要自己去看源码,别人写的书只是一个思维方式上的借鉴,真正要深入理解明白,还是要亲躬力行。只有自己的东西,才能够真正地闲手拈来。如果自己不思考,很容易就陷入到别人的思维顺序了,但是这个又并不会一定适合自己。


感觉看这部分对于我来说还是非常吃力,但坚信书读百遍,其义自现。就像啃甘蔗一样,也许牙齿费力点,但是会有甘甜流出。

0 0