編輯:關於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剪貼板
Android 復制文本內容到系統剪貼板的最簡單實踐,android剪貼板這個例子很簡單,直接上截圖和代碼。 布局文件activity_copy.xml代碼如下: &
Android項目:手機安全衛士(16)—— 復雜 ListView淺析
Android項目:手機安全衛士(16)—— 復雜 ListView淺析 Android項目:手機安全衛士(16)—— 復雜 ListView 1
安卓開源項目周報1220,安卓開源項目1220
安卓開源項目周報1220,安卓開源項目1220由OpenDigg 出品的安卓開源項目周報第二期來啦。我們的安卓開源周報集合了OpenDigg一周來新收錄的優質的