Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android4.4深入淺出之SurfaceFlinger框架-渲染一個surface(二)

Android4.4深入淺出之SurfaceFlinger框架-渲染一個surface(二)

編輯:關於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() {
    sp sm(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();
            sp handle;
            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 msg = new MessageCreateLayer(mFlinger.get(), name, this, w, h, format, flags, handle, gbp);定義了一個消息封裝了surface,mFlinger->postMessageSync(msg);這個向SF發出一個異步信號,這個信號會喚醒SF處於休眠狀態的UI渲染線程核心處理部分。

我們看下這個函數:

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流程系列文章看接下去是怎麼渲染的。




  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved