7.SurfaceFlinger SurfaceFlinger在前面的篇幅了,多有涉及。 SurfaceFlinger是GUI刷新UI的核心,所以任何關於SurfaceFlinger的改進都會對android UI系統有重大影響。 SurfaceFlinger主要分為4個部分 1)黃油計劃 proj ...
7.SurfaceFlinger
SurfaceFlinger在前面的篇幅了,多有涉及。
SurfaceFlinger是GUI刷新UI的核心,所以任何關於SurfaceFlinger的改進都會對android UI系統有重大影響。
SurfaceFlinger主要分為4個部分
1)黃油計劃---project butter
2)啟動過程
3)SurfaceFlinger & BufferQueue的關係
4)Vsync信號的處理
7.1黃油計劃
就是給android系統,圖上一層“黃油”。我們來看看andorid是怎麼給SurfaceFlinger塗上這層黃油的。
butter 由2個組成部分,Vsync & Triple buffer。
Triple buffer:
上面講到雙緩衝區技術,也提到FrameBufferNativeWindow 在申請buffer的時候,可以是2,或者是3.
這個3 就是馬上要講到的Triple Buffer技術。
我們先會過來看看雙緩衝技術。
之前說 雙緩衝,是把一個buffer放在bitmap上,等到這個所有元素都準備好以後,在把bitmap刷到屏幕上。
這樣會解決卡頓的感覺。
我們考慮一種情況,假設屏幕刷新頻率是66Hz,CPU頻率是100Hz.
之前已經講了雙緩衝技術,這裡簡單過一下。
如上面的假設,UI的刷新是0.015s,而buffer的準備是0.01s
一個Frame Buffer代表一幀圖像。
0.01s:
此時,buffer已經準備好數據,而顯示器只顯示了圖像的2/3
0.015s
顯示器顯示了第一幀圖像,而buffer已經填充了第二幀的1/3
0.02s
Buffer已經準備好了第二幀,而顯示器出現了問題,1/3的內容屬於第二幀,2/3的內容屬於第一幀。
這就是android引入雙緩衝技術的原因。
如果buffer準備的時間,比屏幕刷新圖像的速度慢呢?
顯示屏的每一次刷新,就是對顯示器屏幕的掃描,但是它是有間隔的(物理設備嘛,肯定有這個間隔)。
典型的PC顯示器屏幕刷新頻率是60Hz,這是因為一秒60幀,從人的角度看,就會覺得很流暢。
所以間隔1/60秒,也就是16ms 如果我們準備時間<=16ms,那就可以做到“無縫連接”。畫面就很流程。
這段空隙稱為VBI。 這個時間就是交換緩衝區最佳的時間。而這個交換的動作就是Vsync 也是SurfaceFlinger的重點。
如果我們圖像準備時間<=16ms. OK,畫面是很流暢的,但是我們無法保證設備性能一定很very good。所以也有可能畫面準備時間超過16ms
![](http://upload-images.jianshu.io/upload_images/2187677-9456cfbaf7c4f39c.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
我們看看這張圖。 剛開始buffer裡面有數據A,這時候,可以直接顯示在屏幕上。 過了16ms以後,數據B還沒準備好,屏幕只能繼續顯示A。這樣就浪費了依次交換的機會。 到下一次交換,B被顯示在屏幕上。 這裡有段時間被浪費了。 等到下一次A的時候,過了16ms,還是沒有準備好,繼續浪費。所以雙緩衝區技術,也有很大浪費。 有沒有辦法規避呢, 比如上圖 B & A之間的這段時間,如果我增加一個buffer,C。 這樣B準備好以後,雖然C沒有好,但是B可以顯示在屏幕上,等到下一次16ms到了以後,C已經準備好了,這樣可以很大程度上減少CPU時間的浪費。 也就是空間換時間的一種思想。 所以多緩衝區就是,就是可以根據系統的實際記憶體情況,來判斷buffer的數量。
7.2 SurfaceFlinger的啟動
SurfaceFlinger 我們前面已經說了,它其實就是一個service。
void SurfaceFlinger::onFirstRef() { mEventQueue.init(this); }
初始化事件隊列。
void MessageQueue::init(const sp<SurfaceFlinger>& flinger) { mFlinger = flinger; mLooper = new Looper(true); mHandler = new Handler(*this); }
創建了looper & Handler
但是這個looper什麼時候起來的呢?
void MessageQueue::waitMessage() { do { IPCThreadState::self()->flushCommands(); int32_t ret = mLooper->pollOnce(-1); switch (ret) { case Looper::POLL_WAKE: case Looper::POLL_CALLBACK: continue; case Looper::POLL_ERROR: ALOGE("Looper::POLL_ERROR"); case Looper::POLL_TIMEOUT: // timeout (should not happen) continue; default: // should not happen ALOGE("Looper::pollOnce() returned unknown status %d", ret); continue; } } while (true); }
可以看到最終會調用looper啟動函數。可以看到Looper::POLL_TIMEOUT: android什麼都沒做,儘管它們不應該發生。
其實handler兜了一圈,發現最後還是回到surfaceflinger來處理:
void SurfaceFlinger::onMessageReceived(int32_t what) { ATRACE_CALL(); switch (what) { case MessageQueue::TRANSACTION: { handleMessageTransaction(); break; } case MessageQueue::INVALIDATE: { bool refreshNeeded = handleMessageTransaction(); refreshNeeded |= handleMessageInvalidate(); refreshNeeded |= mRepaintEverything; if (refreshNeeded) { // Signal a refresh if a transaction modified the window state, // a new buffer was latched, or if HWC has requested a full // repaint signalRefresh(); } break; } case MessageQueue::REFRESH: { handleMessageRefresh(); break; } } }
7.3 client
任何有UI界面App都在surfaceflinger裡面有client。
所以是一個app對應一個surfaceflinger裡面的client(ISurfaceComposerClient)。
下麵我們來分析surfaceflinger的2個重要函數:
sp<ISurfaceComposerClient> SurfaceFlinger::createConnection() { sp<ISurfaceComposerClient> bclient; sp<Client> client(new Client(this)); status_t err = client->initCheck(); if (err == NO_ERROR) { bclient = client; } return bclient; }
返回ISurfaceComposerClient,也就是client的bind對象實體。
其實就上面標紅的一句,進行必要的有效性檢查,現在代碼:
status_t Client::initCheck() const { return NO_ERROR; }
有了clinet以後,看下surface的產生。
status_t Client::createSurface( const String8& name, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp) { /* * createSurface must be called from the GL thread so that it can * have access to the GL context. */ class MessageCreateLayer : public MessageBase { SurfaceFlinger* flinger; Client* client; sp<IBinder>* handle; sp<IGraphicBufferProducer>* gbp; status_t result; const String8& name; uint32_t w, h; PixelFormat format; uint32_t flags; public: MessageCreateLayer(SurfaceFlinger* flinger, const String8& name, Client* client, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp) : flinger(flinger), client(client), handle(handle), gbp(gbp), name(name), w(w), h(h), format(format), flags(flags) { } status_t getResult() const { return result; } virtual bool handler() { result = flinger->createLayer(name, client, w, h, format, flags, handle, gbp); return true; } }; sp<MessageBase> msg = new MessageCreateLayer(mFlinger.get(), name, this, w, h, format, flags, handle, gbp); mFlinger->postMessageSync(msg); return static_cast<MessageCreateLayer*>( msg.get() )->getResult(); }
到來到去,其實就2句話:
postMessageSync,其實就是一開始不會直接創建surface,然後放入surfaceflinger隊列里,這樣不會打斷現在的操作。
然後啟動createlayer方法。這個方法之前已經分析過了。
參考:
《深入理解android內核設計思想》 林學森