Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 從Android Bootanimation理解SurfaceFlinger的客戶端建立

從Android Bootanimation理解SurfaceFlinger的客戶端建立

編輯:關於Android編程

本文均屬自己閱讀源碼的點滴總結,轉賬請注明出處謝謝。

歡迎和大家交流。qq:1037701636 email:[email protected]

Android源碼版本Version:4.2.2; 硬件平台 全志A31

step1.前面的幾張博文都在記錄SurfaceFLinger側,也就是所謂的Server端,接下去就和大家來看看客戶端是如何將要處理的圖形信息請求SF來傳遞出去的呢。大家學習的一個方式都是通過android啟動的第一個開機畫面來入手的,先來看看啟動的函數,再來看這個類BootAnimation。

int main(int argc, char** argv)//由surfaceflinger來觸發init進程來啟動它
{
#if defined(HAVE_PTHREADS)
    setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_DISPLAY);
#endif

    char value[PROPERTY_VALUE_MAX];
    property_get("debug.sf.nobootanimation", value, "0");
    int noBootAnimation = atoi(value);
    ALOGI_IF(noBootAnimation,  "boot animation disabled");
    if (!noBootAnimation) {

        sp proc(ProcessState::self());
        ProcessState::self()->startThreadPool();//這裡會進行binder的驅動初始化

        // create the boot animation object
        sp boot = new BootAnimation();//初始化並會調用BootAnimation的onFirstRef,啟動一個線程
        boot->playBootMusic("/system/media/boot.wav");
        IPCThreadState::self()->joinThreadPool();

    }
    return 0;
}

我們會問Bootanimation是在哪裡啟動的呢,可以看我之前寫的文章android從init到開機動畫啟動關閉流程一簡易圖(surfaceflinger啟動的位置)裡面講到了SF啟動之後init主進程才有可能啟動它,因為bootanimation在init.rc是配置為disable,在SF裡面會出現的readyToRun函數內的startBootAnim();//開啟動畫屬性,通過設置內存屬性值來觸發Init進程來啟動:

void SurfaceFlinger::startBootAnim() {
    // start boot animation
    property_set("service.bootanim.exit", "0");
    property_set("ctl.start", "bootanim");
}


在BootAnimation的main函數中,開始新建類的對象。

BootAnimation::BootAnimation() : Thread(false)
{
    mSession = new SurfaceComposerClient();//SurfaceComposerClient,msession:sp
}

可以想象的到,作為線程類Thread的派生類,明顯的很多事情是在thread的readyToRun和ThreadLoop裡面發生的,而新線程也一般就是在OnFirstRef中啟動run函數的。

在BootAnimation的構造函數中看到了一個SurfaceComposerClient類,理解為界面合成客戶端,的確BootAnimation將會作為一個客戶端請求SF去完成圖層的渲染。那麼SCC是如何和SF交互的呢,我們來看SCC的構造過程。

SurfaceComposerClient::SurfaceComposerClient()
    : mStatus(NO_INIT), mComposer(Composer::getInstance())
{
}

void SurfaceComposerClient::onFirstRef() {
    sp sm(ComposerService::getComposerService());//獲得SurfaceFlinger的proxy BpSurfaceComposer
    if (sm != 0) {
        sp conn = sm->createConnection();//建立一個連接,獲得SurfaceFlinger遠程的客戶端BpSurfaceComposerClient,對應於服務端的Client
        if (conn != 0) {
            mClient = conn;//BpISurfaceComposerClient保存在mclient
            mStatus = NO_ERROR;
        }
    }
}

在調用構造函數時初始化一個Composer類成員變量,且為單列模式。再來看onFirstRef中的操作,ComposerService::getComposerService:

sp ComposerService::getComposerService() {
    ComposerService& instance = ComposerService::getInstance();//ComposerService對象創建,單列模式BpSurfaceComposer,保存在其成員mComposerService
    Mutex::Autolock _l(instance.mLock);
    if (instance.mComposerService == NULL) {
        ComposerService::getInstance().connectLocked();
        assert(instance.mComposerService != NULL);
        ALOGD("ComposerService reconnected");
    }
    return instance.mComposerService;//成員代碼BpSurfaceComposer
}

內部又出現一個ComposerService這個單列模式,看看他的構造函數:

ComposerService::ComposerService()
: Singleton() {
    Mutex::Autolock _l(mLock);
    connectLocked();
}

果然會調用一個connectLocked函數:

void ComposerService::connectLocked() {
    const String16 name("SurfaceFlinger");
    while (getService(name, &mComposerService) != NO_ERROR) {//返回surfaceflinger的代理到mComposerService
        usleep(250000);
    }

很清楚的是getService,可以想象的是應該是和ServiceManger在交互了,如下:

status_t getService(const String16& name, sp* outService)
{
    const sp sm = defaultServiceManager();
    if (sm != NULL) {
        *outService = interface_cast(sm->getService(name));
        if ((*outService) != NULL) return NO_ERROR;
    }
    return NAME_NOT_FOUND;
}

果然在這裡就是看到了通用的客戶端和SM的交互過程了,這裡就是實現了客戶端請求SM返回SurfaceFlinger的服務端在本地的代理proxy。最終保存到mCompserService變量中且該對象的類型為BpSurfaceComposer和SF(實際上SF繼承了BnSurfaceComposer這個本地對象)處建立起基於Binder的C/S通信架構。

好了上面的代碼執行了這麼多就是為了調用sm->createConnection()函數,這個就是典型的Binder通信方式了,可以看到:

    virtual sp createConnection()
    {
        uint32_t n;
        Parcel data, reply;
        data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
        remote()->transact(BnSurfaceComposer::CREATE_CONNECTION, data, &reply);
        return interface_cast(reply.readStrongBinder());//返回的Bpbinder轉為SurfaceComposerClient
    }

最終返回的是一個BpSurfaceComposerClient,當然核心的處理都是SF在建立的。那麼回到SurfaceFlinger裡面看看這個BpSurfaceComposerClient對象在SF裡的實際角色吧。

SF最終會調用createConnection()函數(這個過程分別經過了BnSurfaceComposer的onTransact處理,SF繼承了BnSurfaceComposer).

sp SurfaceFlinger::createConnection()
{
    sp bclient;
    sp client(new Client(this));//客戶端遠程調用時new一個BnSurfaceComposerClient
    status_t err = client->initCheck();
    if (err == NO_ERROR) {
        bclient = client;
    }
    return bclient;
}

可以看到這裡是調用了這個Client,而基於Binder通信架構的話這個Client肯定是繼承了BnSurfaceComposerClient,故BnSurfaceComposerClient在SF中其實是一個Client類,

status_t BnSurfaceComposer::onTransact(//內部函數由繼承類SF來完成
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    switch(code) {
        case CREATE_CONNECTION: {
            CHECK_INTERFACE(ISurfaceComposer, data, reply);
            sp b = createConnection()->asBinder();//創建一個Bpbinder
            reply->writeStrongBinder(b);//返回給客戶端一個BpBinder的handle
        } break;

最終轉為Binder類型,寫入到Binder分配一個唯一的handle,最終寫回給BpSurfaceComposer客戶端供進一步的BpSurfaceComposerClient和Client之間的通信,而這個Client的代理最終保存在SurfaceComposerClient類對象的成員函數mClient中去。


step2.接著看Bootanimation裡的readyToRun(),內部有如下的一個函數即創建本地的Surface。

    // create the native surface
    sp control = session()->createSurface(String8("BootAnimation"),
            dinfo.w, dinfo.h, PIXEL_FORMAT_RGB_565);//請求surfaceflinger來創建一個surface

session()函數返回之前創建的SurfaceComposerClient,上述函數實際實現如下:

sp SurfaceComposerClient::createSurface(
        const String8& name,
        uint32_t w,
        uint32_t h,
        PixelFormat format,
        uint32_t flags)
{
    sp result;
    if (mStatus == NO_ERROR) {
        ISurfaceComposerClient::surface_data_t data;
        sp surface = mClient->createSurface(&data, name,
                w, h, format, flags);//對應的由SF側的錍lient來完成, BpSurface
        if (surface != 0) {
            result = new SurfaceControl(this, surface, data);//將得到的surface關聯到一個SurfaceControl
        }
    }
    return result;
}

很顯然可以看到是有mClient來實現的,故在SF側就是由之前的new Client處創建的一個Client來完成這個交互的。故回到Client的onTransact函數中去

status_t Client::onTransact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
     ....return BnSurfaceComposerClient::onTransact(code, data, reply, flags);//內部就是調用繼承類Client的createSurface
}

接著往下看:

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);
            surface_data_t params;
            String8 name = data.readString8();
            uint32_t w = data.readInt32();
            uint32_t h = data.readInt32();
            PixelFormat format = data.readInt32();
            uint32_t flags = data.readInt32();
            sp s = createSurface(?ms, name, w, h,
                    format, flags);//創建一個surface
            params.writeToParcel(reply);
            reply->writeStrongBinder(s->asBinder());//本地的BBinder寫入給客戶端
            return NO_ERROR;
        } break;......

因為BnSurfaceComposerClient被Client繼承,故實際調用的還是Client的createrSurface()函數,相關的實現見下一博文SurfaceFlinger中Surface和Layer的建立。





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