編輯:關於Android編程
SurfaceFlinger自啟動之後,主要有三種類型線程參與工作:
1.binder線程,負責監控binder設備完成與客戶端的交接
2.控制台事件監控線程,負責監控硬件幀緩沖區的睡眠/喚醒狀態切換事件。
3.UI渲染線程,負責渲染UI。
一 UI渲染線程
UI渲染線程平時是處於休眠狀態,一旦binder線程監測到有其他進程發過來的請求渲染UI的消息就會喚醒UI渲染線程,另一方面一旦SurfaceFlinger服務的控制台事件監控線程發現硬件幀緩沖區即將要進入睡眠或者喚醒狀態時,它就會往SurfaceFlinger服務的UI渲染線程的消息隊列中發送一個消息,以便SurfaceFlinger服務的UI渲染線程可以執行凍結或者解凍顯示屏的操作。(摘自老羅的android之旅)接下來我從客戶端一個請求渲染UI的請求入手開始研究渲染UI的整個過程
UI渲染線程的運行過程:
這裡在說明一下,SurfaceFlinger的各個代理負責的事情:前面講述的BpSurfaceComposer是SF在客戶端的Binder代理,BnSurfaceComposer是本地對象負責和BpXXX交互,他們主要負責客戶端請求連的整個過程和監控binder設備。而客戶端與server端真正的交易則交給BpSurfaceComposerClient和BnSurfaceComposerClient來做,他們負責通知管理一個UI的渲染等重要過程。那我就從BpSurfaceComposerClient代理入手,還記得這個BpSurfaceComposerClient是哪裡誕生的嗎?在之前客戶端請求連接到server的時候:
void SurfaceComposerClient::onFirstRef() { spsm(ComposerService::getComposerService()); if (sm != 0) { sp conn = sm->createConnection(); if (conn != 0) { mClient = conn; mStatus = NO_ERROR; } } }
當中的一句 mClient = conn;即把返回來的surfacecomposerclient保存了下來,又因為mClient是強指針,導致最終其實mClient就是BpSurfaceComposerClient類的對象,具體原因之前在研究SF啟動過程中有詳細說明。從連接之後,就獲得了一個BpSurfaceComposerClient對象,這樣連接後就可以進行下一步的渲染工作了。我們再看下BpSurfaceComposerClient這個類:
class BpSurfaceComposerClient : public BpInterface{ public: BpSurfaceComposerClient(const sp & impl) : BpInterface (impl) { } virtual status_t createSurface(const String8& name, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, sp * handle, sp * gbp) { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposerClient::getInterfaceDescriptor()); data.writeString8(name); data.writeInt32(w); data.writeInt32(h); data.writeInt32(format); data.writeInt32(flags); remote()->transact(CREATE_SURFACE, data, &reply); *handle = reply.readStrongBinder(); *gbp = interface_cast (reply.readStrongBinder()); return reply.readInt32(); } virtual status_t destroySurface(const sp & handle) { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposerClient::getInterfaceDescriptor()); data.writeStrongBinder(handle); remote()->transact(DESTROY_SURFACE, data, &reply); return reply.readInt32(); } };
他有兩個成員函數,分別是createSurface和destroySurface對應創建和銷毀一個surface。兩個核心函數的核心語句都在remote()->transact(CREATE_SURFACE, data, &reply);
即transact這個函數,之前也介紹過這是和binder設備打交道的必經之路。不做過多深入,這裡意思就是簡單的發個消息 CREATE_SURFACE給服務端,並把一個surface的信息打包成data一並發送過去。
server端這邊會有線程監控binder設備,一旦收到消息自然調用對應的函數。這裡就是BnSurfaceComposerClient負責了,不過這邊跟之前的BnSurfaceComposer有點不一樣,BnSurfaceComposerClient派生出一個Client類來負責這件事了,我們來看下這個類:
class Client : public BnSurfaceComposerClient { public: Client(const sp& flinger); ~Client(); status_t initCheck() const; // protected by SurfaceFlinger::mStateLock void attachLayer(const sp & handle, const sp & layer); void detachLayer(const Layer* layer); sp getLayerUser(const sp & handle) const; private: // ISurfaceComposerClient interface virtual status_t createSurface( const String8& name, uint32_t w, uint32_t h,PixelFormat format, uint32_t flags, sp * handle, sp * gbp); virtual status_t destroySurface(const sp & handle); virtual status_t onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags); // constant sp mFlinger; // protected by mLock DefaultKeyedVector< wp , wp > mLayers; // thread-safe mutable Mutex mLock; };
其實核心的成員函數就兩個 一個是createSurface和onTransact。首先看onTransact,畢竟他負責接收消息。
status_t Client::onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { // these must be checked IPCThreadState* ipc = IPCThreadState::self(); const int pid = ipc->getCallingPid(); const int uid = ipc->getCallingUid(); const int self_pid = getpid(); if (CC_UNLIKELY(pid != self_pid && uid != AID_GRAPHICS && uid != 0)) { // we're called from a different process, do the real check if (!PermissionCache::checkCallingPermission(sAccessSurfaceFlinger)) { ALOGE("Permission Denial: " "can't openGlobalTransaction pid=%d, uid=%d", pid, uid); return PERMISSION_DENIED; } } return BnSurfaceComposerClient::onTransact(code, data, reply, flags); }
這裡前面的語句為了判斷是否得到進入使用SF的權限,看他的返回 BnSurfaceComposerClient::onTransact(code, data, reply, flags);直接調用了另外一個onTransact接著看BnSurfaceComposerClient類中的onTransact
status_t BnSurfaceComposerClient::onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { switch(code) { case CREATE_SURFACE: { CHECK_INTERFACE(ISurfaceComposerClient, data, reply); String8 name = data.readString8(); uint32_t w = data.readInt32(); uint32_t h = data.readInt32(); PixelFormat format = data.readInt32(); uint32_t flags = data.readInt32(); sphandle; sp gbp; status_t result = createSurface(name, w, h, format, flags, &handle, &gbp); reply->writeStrongBinder(handle); reply->writeStrongBinder(gbp->asBinder()); reply->writeInt32(result); return NO_ERROR; } break; case DESTROY_SURFACE: { CHECK_INTERFACE(ISurfaceComposerClient, data, reply); reply->writeInt32( destroySurface( data.readStrongBinder() ) ); return NO_ERROR; } break; default: return BBinder::onTransact(code, data, reply, flags); } }
這才是處理的核心中間人,還記得剛剛傳的消息是CREATE_SURFACE,所以這裡走第一個分支,首先解析數據包得到一些數據例如surface名字,長寬,還有格式等。然後在經過createSurface創建,但是到這裡有個問題,這裡的createSurface沒有指明屬於哪個類,發現去追蹤起定義這追蹤不到,這才想起這是調用了他子類Client的函數。我們回到之前client類中的createSurface;
status_t Client::createSurface( const String8& name, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, sp* handle, sp * 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 * handle; sp * 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 * handle, sp * 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 msg = new MessageCreateLayer(mFlinger.get(), name, this, w, h, format, flags, handle, gbp); mFlinger->postMessageSync(msg); return static_cast ( msg.get() )->getResult(); }
這個函數才真正的是程序進入SF領域的分水嶺,函數內部定義了一個MessageCreateLayer類,我的理解是這個類把一個surface封裝成了一個消息,這個消息當中含有surface的所有信息。sp
我們看下這個函數:
status_t SurfaceFlinger::postMessageSync(const sp& msg, nsecs_t reltime, uint32_t flags) { status_t res = mEventQueue.postMessage(msg, reltime); if (res == NO_ERROR) { msg->wait(); } return res; }
調用postMessage()
status_t MessageQueue::postMessage( const sp& messageHandler, nsecs_t relTime) { const Message dummyMessage; if (relTime > 0) { mLooper->sendMessageDelayed(relTime, messageHandler, dummyMessage); } else { mLooper->sendMessage(messageHandler, dummyMessage); } return NO_ERROR; }
這邊 無論是sendMessageDelayed還是sendMessage都將會觸發線程,將主線程(渲染UI)喚醒。那麼我用一張圖來介紹下主線程:
圖畫的很粗糙不過大致走向就是這樣,當主線程收到消息後,就執行handleMessage。到這裡可以去參考之前錢幾篇SF流程系列文章看接下去是怎麼渲染的。
一、Ant 打包:(下載ant、配置環境變量就不說了) 1、進入命令行模式,並切換到項目目錄,執行如下命令為ADT創建的項目添加ant build支持: andro
使用Android Sutdio創建一個新的工程後,接下來記錄創建NDK工程的基本步驟。本文將達到:1. 創建NDK工程2. 在JNI中輸出Log語句3. 指定編譯的so
AsyncTask的隱蔽陷阱先來看一個實例這個例子很簡單,展示了AsyncTask的一種極端用法,挺怪的。復制代碼 代碼如下:public class AsyncTask
App工程文件分析關於如何創建一個最簡單的Android App請參照鏈接:《 Android學習筆記(一)環境安裝及第一個hello world 》 http://ww