編輯:關於Android編程
前沿:
如果對SurfaceFlinger架構的工作原理較為熟悉的話,本文閱讀起來會相對容易些。之所以撰寫本文是因為在閱讀Camera HAL3的實現過程中大量的出現了類似與SurfaceFlinger的工作模式。本文將以CallbackProcessor模塊的為入口,和大家進行分享。
1 Preview模塊Surface與SurfaceFlinger的基礎知識
開發過Android Camera模塊的人,基本都應該熟悉實時采集的視頻如果要顯示到手機屏上,對應的Framework層就應該構建一個Surface對象,這對所有Android版本都是通用的。該Surface本質是一個在APP端的ANativeWindow,是需要從SurfaceFlinger端的Gralloc模塊獲取Buffer的,然後填充幀圖像數據並送顯示的過程。詳細內容可以參考之前的專欄我心所向之Android4.2關於SurfaceFlinger相關的內容。
由於目前Android系統版本升級過快,在5.0以上的版本中SurfaceFlinger部分框架發生了變化(目前還沒有深入去研讀過),了解到的是:
一方面他去掉了SurfaceTexture/SurfaceTextureClient等內容,增強了Surface的功能。
另一方面BufferQueue的使用也更加簡單與明了,Producer與Consumer的關系也更加明確,BufferQueue不再是以前的消費者角色,轉而成為ProducerBufferQueue和Consumer相互關聯的橋梁。
此外,如果你在深入的話,會了解到Gralloc模塊中非framebuff的緩存管理與共享不在是那個Ashmem匿名共享內存,而是出現了一種新的內存管理機制/dev/ION/,後面會和大家分享他部分的工作機制。
對於SurfaceFlinger與Camera Preview Surface而言,ANativeWindow作為兩者的共性負責管理和維護Buffer的創建與共享,在SurfaceFlinger端ANativeWindow創建buffer,在Surface側通過dequeuebuffer獲取buffer handle到本地進行共享,在填充完數據後通過queuebuffer告訴SurfaceFlinger當前buffer可用,這樣就形成了一個buffer生產與消費的關系,基於這種原理我們在Camera3Device中除了看到正常的Preview Surface之外還看到了其他模塊中出現了Surface的創建。
2 CallbackProcessor::updateStream() 創建Surface
sp上述代碼看上去很簡單,但就是他最終形成了一個bufferstream Product和Consumer的處理,這種方式也為Camera2Client下出現多路stream,多路數據流存在奠定了基礎,下面我們來簡單的描述他的工作機制。producer; sp consumer; BufferQueue::createBufferQueue(&producer, &consumer);//BufferQueueProducer與BufferQueueConsumer mCallbackConsumer = new CpuConsumer(consumer, kCallbackHeapCount); mCallbackConsumer->setFrameAvailableListener(this);//當前CallbackProcessor繼承於CpuConsumer::FrameAvailableListener mCallbackConsumer->setName(String8(Camera2Client::CallbackConsumer)); mCallbackWindow = new Surface(producer);//用於queue操作,這裡直接進行本地的buffer操作
2.1 BufferQueue::createBufferQueue
void BufferQueue::createBufferQueue(sp當前Android5.1版本中可以看到BufferQueue已經改變了原先的角色,成為了一個用於創建一組操作BufferQueue的接口,實現了BufferQueueProducer與BufferQueueConsumer的創建。更本質說現在BufferQueue的工作量已經很小,基本由Surface來全盤操作。這裡通過BufferQueueCore會將BufferQueueProducer與BufferQueueConsumer綁定在一起,BufferQueueProducer可以說是替代了舊版本Android4.2中的SurfaceTextureClient,而BufferQueueConsumer則直接是SurfaceTexture以及BufferQueue的替代者。下圖是在Android4.2.2中Surface和SurfaceFlinger間基於Bn/BpSurfaceTexture的多進程間buffer的queue操作機制。* outProducer, sp * outConsumer, const sp & allocator) { LOG_ALWAYS_FATAL_IF(outProducer == NULL, BufferQueue: outProducer must not be NULL); LOG_ALWAYS_FATAL_IF(outConsumer == NULL, BufferQueue: outConsumer must not be NULL); sp core(new BufferQueueCore(allocator)); LOG_ALWAYS_FATAL_IF(core == NULL, BufferQueue: failed to create BufferQueueCore); sp producer(new BufferQueueProducer(core));//本地Bn的BufferQueueProducer LOG_ALWAYS_FATAL_IF(producer == NULL, BufferQueue: failed to create BufferQueueProducer); sp consumer(new BufferQueueConsumer(core));//本地Bn的BufferQueueConsumer LOG_ALWAYS_FATAL_IF(consumer == NULL, BufferQueue: failed to create BufferQueueConsumer); *outProducer = producer; *outConsumer = consumer; }
2.2 CpuConsumer
在2.1中本質上是創建了BufferQueueProducer和BufferQueueConsumer,一般是成對出現。
這個CpuConsumer的地位本質是和SurfaceFlinger是一樣的,主要角色就是來處理已經帶有幀數據的buffer塊,所以整個的處理機制都是類型的,其中兩者均為繼承一個ConsumerBase類,用於實現對buffer塊的處理。
CpuConsumer::CpuConsumer(const sp& bq, uint32_t maxLockedBuffers, bool controlledByApp) : ConsumerBase(bq, controlledByApp), mMaxLockedBuffers(maxLockedBuffers), mCurrentLockedBuffers(0) { // Create tracking entries for locked buffers mAcquiredBuffers.insertAt(0, maxLockedBuffers); mConsumer->setConsumerUsageBits(GRALLOC_USAGE_SW_READ_OFTEN); mConsumer->setMaxAcquiredBufferCount(maxLockedBuffers); }
2.3 mCallbackConsumer->setFrameAvailableListener(this)
這裡所完成的過程是需要Consumer去將一個listener加入到Productor端去,便於在幀數據可用時,可以監聽到並告知Consumer去做數據的處理,Product需要在數據可用時觸發這個listener的onFrameAvailable,從而讓數據從Productor轉到Consumer則,數據處理應該是在同一進程的而不是跨進程。
如果作為Consumer如CPUConsumer沒有使用setFrameAvailableListener將自己加入到listener中去,會由ConsumerBase的接口onFrameAvailable來替代完成。
2.4 mCallbackWindow = new Surface(producer)
這裡是建立一個Surface,也就是類型於Preview模式下創建的Surface,兩者的本質是一樣的。在Android5.1中,Surface已經擁有了絕對的控制權,Preview模式下的Surface是跨進程的和SF進行交互,故構造函數傳入的sp
ANativeWindow::setSwapInterval = hook_setSwapInterval; ANativeWindow::dequeueBuffer = hook_dequeueBuffer; ANativeWindow::cancelBuffer = hook_cancelBuffer; ANativeWindow::queueBuffer = hook_queueBuffer; ANativeWindow::query = hook_query; ANativeWindow::perform = hook_perform; ANativeWindow::dequeueBuffer_DEPRECATED = hook_dequeueBuffer_DEPRECATED; ANativeWindow::cancelBuffer_DEPRECATED = hook_cancelBuffer_DEPRECATED; ANativeWindow::lockBuffer_DEPRECATED = hook_lockBuffer_DEPRECATED; ANativeWindow::queueBuffer_DEPRECATED = hook_queueBuffer_DEPRECATED;一般對Buffer的操作都先是基於Struct ANativeWindow這個本地的窗口類來處理,再是通過hook到實際的surface再交由GraphicBufferProducer來完成的。
3 Android5.1下Surface的queuebuffer操作邏輯
對比上一圖可知,當前CPUConsumer模式下,從queuebuffer的處理過程來看更加體現出Productor和Consumer這種設計模式,整個架構代碼看起來也更明了,這也是谷歌不斷升級系統去冗存精的道理吧。整個用戶在調用這種邏輯是,只需幾句代碼就可以獲得對一個buffer塊的讀與寫的操作接口,具體後續在分析Camera HAL3的數據流時可以很深刻的看到。
總的來說Surface在Camera3Device的架構下,與HAL3相組合是充當了消費者,與CPUCOnsumer或者Surfaceflinger來說就是生產者。或者說surface充當了buffer信息的傳輸與過渡。
自定義控件是一些android程序員感覺很難攻破的難點,起碼對我來說是這樣的,但是我們可以在網上找一些好的博客關於自定義控件好好拿過來學習研究下,多練,多寫點也能找到感覺
Service 是一個可以在後台執行長時間運行操作而不使用用戶界面的應用組件。 例如,服務可以處理網絡事務、播放音樂,執行文件 I/O 或與內容提供程序交互,而所有這一切
在上一篇文章寫了SAX解析XML,感覺Pull方式和SAX方式非常相似,只是SAX需要一個輔助的類,解析時觸發事件後在回調方法裡面寫代碼,而Pull則通過調
1、什麼是ActivityActivity是Android四大組件之一,用於顯示View。Activity是一個應用程序組件,提供一個用戶交互的接口,其本身是沒有界面的,