編輯:關於android開發
SurfaceFlinger在前面的篇幅了,多有涉及。
SurfaceFlinger是GUI刷新UI的核心,所以任何關於SurfaceFlinger的改進都會對android UI系統有重大影響。
SurfaceFlinger主要分為4個部分
1)黃油計劃---project butter
2)啟動過程
3)SurfaceFlinger & BufferQueue的關系
4)Vsync信號的處理
就是給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
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; } } }
任何有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方法。這個方法之前已經分析過了。
微信支付,信支付記錄片,防止以後很久沒做在次犯二 把官方例子集成進項目後 scheme就是你創建應用的AppID 然後還有在配置文件的appid也要換掉
Android 復制文本內容到系統剪貼板的最簡單實踐,android剪貼板這個例子很簡單,直接上截圖和代碼。 布局文件activity_copy.xml代碼如下: &
Android項目:手機安全衛士(16)—— 復雜 ListView淺析 Android項目:手機安全衛士(16)—— 復雜 ListView 1
安卓開源項目周報1220,安卓開源項目1220由OpenDigg 出品的安卓開源項目周報第二期來啦。我們的安卓開源周報集合了OpenDigg一周來新收錄的優質的