Android ISurface PostBuffer 处理流程

1 ISurface 的Create

    想了解surface的create 和surfaceflinger 可参考这篇文章,比较详细:

http://blog.csdn.net/yili_xie/archive/2009/11/12/4803527.aspx

    Android 起步比较早的大牛们挺多,我现在只能一步步踏着革命先烈的后尘。

    每个相应的应用都会有个相应的ISurface 的对象被set进来,例如camera 的cameraService,opencore的MIO。我们只需要知道这么用就可以了。


2 App调用流程。

    看过code就知道,这个调用是很简单的。

    先初始化memory

  1. mFrameHeap =  new  MemoryHeapBase(frameSize * kBufferCount);  
  2. if  (mFrameHeap->heapID() < 0)  
  3. {  
  4.     LOGE("Error creating frame buffer heap" );  
  5.     return   false ;  
  6. }  

    把memory 注册到ISurface上

  1. ISurface::BufferHeap buffers(displayWidth, displayHeight,  
  2.                              displayWidth, displayHeight, PIXEL_FORMAT_RGB_565, mFrameHeap);  
  3. mSurface->registerBuffers(buffers);  

 调用postBuffer 即可

   mSurface->postBuffer(mFrameBuffers[mFrameBufferIndex]);

   这里摘抄的是android_surface_output.cpp中的code,  cameraService中的和它没什么区别。

   在这里我们重点要讨论的是postBuffer的处理过程。


3 postBuffer 处理过程。(default,我们的系统中不支持overlay)

    在ISurface.cpp中实现了两个public BpInterface<ISurface>的类:BpSurface BnSurface

    BpSurface 是使用Binder实现服务端的调用。

    BnSurface 是surfaceFlinger 向回的调用。

    我们写 mSurface->postBuffer实际上调用的是BpSurface::postBuffer

    它的实现是:

    remote()->transact(POST_BUFFER, data, &reply, IBinder::FLAG_ONEWAY);

    (Binder的机制我还不是很清楚)从developer的网站上有对 binder调用这样的注释:

The key IBinder API is transact() matched by Binder.onTransact(). These methods allow you to send a call to an IBinder object and receive a call coming in to a Binder object, respectively. This transaction API is synchronous, such that a call to transact() does not return until the target has returned from Binder.onTransact(); this is the expected behavior when calling an object that exists in the local process, and the underlying inter-process communication (IPC) mechanism ensures that these same semantics apply when going across processes.

    也就是说整个binder调用过程是同步的。

    之后回调到:BnSurface::onTransact

  1. case  POST_BUFFER: {  
  2.     CHECK_INTERFACE(ISurface, data, reply);  
  3.     ssize_t offset = data.readInt32();  
  4.     postBuffer(offset);  
  5.     return  NO_ERROR;  
  6. break ;  

    这里就调用到了LayerBuffer 中的postBuffer :LayerBuffer::BufferSource::postBuffer(ssize_t offset)

    关于surfaceflinger中这几个layer的概念,也可以参考一醉千年的博客,我自己暂时还不是很清晰。

  1. if  (buffers.heap != 0) {  
  2.     buffer = new  LayerBuffer::Buffer(buffers, offset);  
  3.     if  (buffer->getStatus() != NO_ERROR)  
  4.         buffer.clear();  
  5.     setBuffer(buffer);  
  6.     mLayer.invalidate();  
  7. }  

 
     这里的setBuffer(buffer);会对你要post的buffer做一个记录。然后通过LayerBase::invalidate()调用mFlinger->signalEvent()

触发一个事件,就返回了。

     而SurfaceFlinger 会再SurfaceFlinger::threadLoop()中处理这个事件。最终还会调用到 LayerBuffer::BufferSource::onDraw函数。在layer中实现surface中的数据的合成处理等.

    回到我们对postBuffer的调用,可发现这是两个进程的处理。client进程调用后只是通知surfaceflinger我要显示一个 surface,而surfaceflinger什么时候去处理,什么时候真正去使用这块memory,client并不知道。因此binder虽是同步 的调用,而buffer却是异步的处理。我自己做个试验,在postBuffer之后立刻去修改post的这块memory的内容,最终发现应该显示的内 容被改掉了。而postBuffer之后睡个40ms,屏幕就没有花,说明在修改memory之前surfaceflinger已经完成了这个 buffer的draw工作。

http://blog.csdn.net/saphy/archive/2010/07/01/5707413.aspx

原文地址:https://www.cnblogs.com/eustoma/p/2415842.html