Android 12(S) 圖形顯示系統 - 應用建立和SurfaceFlinger的溝通橋樑(三)

二的次方發表於2022-01-21

1 前言

上一篇文章中我們已經建立了一個Native示例應用,從使用者的角度瞭解了圖形顯示系統API的基本使用,從這篇文章開始我們將基於這個示例應用深入圖形顯示系統API的內部實現邏輯,分析運作流程。

本篇將聚焦應用和SurfaceFlinger的活動,即應用是如何與SurfaceFlinger這個服務建立連線並進行通訊的。讓我們開始吧!

注:本篇涉及的程式碼位置:

/frameworks/native/libs/gui/

/frameworks/native/libs/gui/include/gui/

/frameworks/native/libs/gui/include/private/gui/

/frameworks/native/services/surfaceflinger/

 


2 應用和SurfaceFlinger的通訊

應用執行一開始便首先要去建立一個Native Surface,此時即開始了與SurfaceFlinger的互動,分步來看建立Surface的過程:

  • SurfaceFlinger系統服務的Binder RPC架構

在分析詳細的程式碼前,我想先展示一下 SurfaceFlinger系統服務的Binder RPC架構,其中涉及哪些類?哪些介面?它們之間的關係如何?在巨集觀上去對這些物件的關係做了解,有助於我們理解具體的程式碼分析。

先看一張基本的類圖:

SurfaceFlinger作為典型的Binder系統服務,遵循Binder服務設計的一般原則:

Interface介面:ISurfaceComposer 、ISurfaceComposerClient

Bp客戶端:BpSurfaceComposer、BpSurfaceComposerClient

Bn服務端:BnSurfaceComposer、BnSurfaceComposerClient

服務實現:SurfaceFlinger、Client

具體Binder的原理在此就不展開講了,相信你在網路上可以搜尋到很多優秀的講解文章。


這裡請先留意兩點:

  1. ComposerService中有成員mComposerService,它代表了SurfaceFlinger服務的代理客戶端;
  2. SurfaceComposerClient中有成員mClient,它代表了SurfaceFlinger服務程式中的Client的代理客戶端(這裡應該是涉及所謂的匿名Binder的概念)

推薦兩篇博文:https://blog.csdn.net/lewif/article/details/50696510

                        https://my.oschina.net/u/3897543/blog/4750360


 

  • 建立SurfaceComposerClient並建立與SurfaceFlinger的連線

應用首先去建立SurfaceComposerClient物件,透過這個物件建立和SurfaceFlinger的連線並進行後續的互動:

sp<SurfaceComposerClient> surfaceComposerClient = new SurfaceComposerClient;
status_t err = surfaceComposerClient->initCheck();
if (err != NO_ERROR) {
    ALOGD("SurfaceComposerClient::initCheck error: %#x\n", err);
    return;
}

SurfaceComposerClient 的定義非常簡單,繼承RefBase,其中成員mClient持有遠端服務的代理客戶端,基本操作都是以它作為橋樑傳遞到SurfaceFlinger的,如下:

// /frameworks/native/libs/gui/include/gui/SurfaceComposerClient.h
class SurfaceComposerClient : public RefBase
{
public:
                SurfaceComposerClient();
                SurfaceComposerClient(const sp<ISurfaceComposerClient>& client);
    virtual     ~SurfaceComposerClient();
    ......
private:
                sp<ISurfaceComposerClient>  mClient;
}

SurfaceComposerClient 的建構函式也十分簡單,進行mStatus的初始化,其中mClient也可以外部傳遞進來初始值,或在onFirstRef的時候進行設定:

// /frameworks/native/libs/gui/SurfaceComposerClient.cpp
SurfaceComposerClient::SurfaceComposerClient()
    : mStatus(NO_INIT)
{
}

SurfaceComposerClient::SurfaceComposerClient(const sp<ISurfaceComposerClient>& client)
    : mStatus(NO_ERROR), mClient(client)
{
}

物件第一次引用onFirstRef的時候,才真正的去建立和SurfaceFlinger的連線:

// /frameworks/native/libs/gui/SurfaceComposerClient.cpp
void SurfaceComposerClient::onFirstRef() {
    sp<ISurfaceComposer> sf(ComposerService::getComposerService());
    if (sf != nullptr && mStatus == NO_INIT) {
        sp<ISurfaceComposerClient> conn;
        conn = sf->createConnection();
        if (conn != nullptr) {
            mClient = conn;
            mStatus = NO_ERROR;
        }
    }
}

先看一下ComposerService的定義,這是一個Singleton,它持有SurfaceFlinger服務的代理客戶端:sp<ISurfaceComposer> mComposerService

// /frameworks/native/libs/gui/include/private/gui/ComposerService.h
// This holds our connection to the composer service (i.e. SurfaceFlinger).

class ComposerService : public Singleton<ComposerService>
{
    sp<ISurfaceComposer> mComposerService;  // composer service的代理端
    sp<IBinder::DeathRecipient> mDeathObserver;
    Mutex mLock;

    ComposerService();
    bool connectLocked();
    void composerServiceDied();
    friend class Singleton<ComposerService>;
public:
    // Get a connection to the Composer Service.  This will block until
    // a connection is established. Returns null if permission is denied.
    static sp<ISurfaceComposer> getComposerService();
};

ComposerService在構建時,呼叫connectLocked獲取SurfaceFlinger(composer service)服務的代理客戶端:

//  /frameworks/native/libs/gui/SurfaceComposerClient.cpp

// ComposerService的建構函式,呼叫到connectLocked去建立和SurfaceFlinger的連線
ComposerService::ComposerService()
: Singleton<ComposerService>() {
    Mutex::Autolock _l(mLock);
    connectLocked();
}

bool ComposerService::connectLocked() {
    const String16 name("SurfaceFlinger");
    mComposerService = waitForService<ISurfaceComposer>(name); // 通過ServiceManager去獲取SurfaceFlinger這個系統服務
    if (mComposerService == nullptr) {
        return false; // fatal error or permission problem
    }

    // Create the death listener.
    class DeathObserver : public IBinder::DeathRecipient {
        ComposerService& mComposerService;
        virtual void binderDied(const wp<IBinder>& who) {
            ALOGW("ComposerService remote (surfaceflinger) died [%p]",
                  who.unsafe_get());
            mComposerService.composerServiceDied();
        }
     public:
        explicit DeathObserver(ComposerService& mgr) : mComposerService(mgr) { }
    };

    mDeathObserver = new DeathObserver(*const_cast<ComposerService*>(this));
    IInterface::asBinder(mComposerService)->linkToDeath(mDeathObserver);
    return true;
}

上面connectLocked方法可以看到呼叫waitForService去向ServiceManager請求名稱為SurfaceFlinger的系統服務,成功後就取得了SurfaceFlinger這個系統服務的遠端代理客戶端,之後就可以透過這個代理跨程式與SurfaceFlinger進行互動了。

DeathObserver是一個監聽器,用於監聽遠端服務的狀態,當遠端服務異常退出Died,觸發該監聽器,進而呼叫到mComposerService.composerServiceDied()做一些清理保護

void ComposerService::composerServiceDied()
{
    Mutex::Autolock _l(mLock);
    mComposerService = nullptr;
    mDeathObserver = nullptr;
}

再回到SurfaceComposerClient::onFirstRef方法中,透過ComposerService::getComposerService()獲取到SurfaceFlinger服務的代理客戶端後,接下來就是去初始化mClient了

// /frameworks/native/libs/gui/SurfaceComposerClient.cpp

sp<ISurfaceComposerClient> conn;
conn = sf->createConnection();
if (conn != nullptr) {
	mClient = conn;
	mStatus = NO_ERROR;
}

進而呼叫到了

// /frameworks/native/libs/gui/include/gui/ISurfaceComposer.h

/*
 * Create a connection with SurfaceFlinger.
 */
virtual sp<ISurfaceComposerClient> createConnection() = 0;

createConnection是一個典型的Binder C/S架構下的跨程式呼叫,傻瓜式的理解呼叫流程:

// 客戶端端傳送資訊
BpSurfaceComposer::createConnection() {
	remote()->transact(BnSurfaceComposer::CREATE_CONNECTION, data, &reply);
    return interface_cast<ISurfaceComposerClient>(reply.readStrongBinder());
}

==>

// 服務端接收到資訊
status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
                                    uint32_t flags) {
    status_t credentialCheck = CheckTransactCodeCredentials(code);
    if (credentialCheck != OK) {
        return credentialCheck;
    }

    status_t err = BnSurfaceComposer::onTransact(code, data, reply, flags);
  
  	....

}

BnSurfaceComposer::onTransact() {
        case CREATE_CONNECTION: {
            CHECK_INTERFACE(ISurfaceComposer, data, reply);
            sp<IBinder> b = IInterface::asBinder(createConnection());
            reply->writeStrongBinder(b);
            return NO_ERROR;
        }
}

==>

// 服務具體實現
sp<ISurfaceComposerClient> SurfaceFlinger::createConnection() {
    const sp<Client> client = new Client(this);
    return client->initCheck() == NO_ERROR ? client : nullptr;
}

SurfaceFlinger::createConnection方法中建立一個Client物件,Client繼承自BnSurfaceComposerClient實現ISurfaceComposerClient介面,可以利用Binder機制傳遞迴客戶端。而且Client物件中含有SurfaceFlinger成員,這樣SurfaceComposerClient::mClient就和SurfaceFlinger建立了連線。


Tips:

SurfaceFlinger程式中建立的Client物件,透過Binder IPC機制返回到了應用程式中,這裡的具體原理感興趣的可以研究下IInterface::asBinder /  writeStrongBinder / readStrongBinder / interface_cast 這些方法。這裡我們就傻瓜式的理解為SurfaceComposerClient::mClient是SurfaceFlinger程式中Client物件的代理客戶端,使用SurfaceComposerClient::mClient就可以呼叫到SurfaceFlinger程式中Client物件的方法。

 


前面的講解看起來紛紛擾擾,簡單的,抽象的概括就是:

  1. 建立SurfaceComposerClient物件;
  2. SurfaceComposerClient::onFirstRef方法中透過ComposerService::getComposerService()獲取到SurfaceFlinger服務的代理客戶端;
  3. 呼叫SurfaceFlinger服務的代理客戶端的createConnection方法,進而跨程式呼叫到SurfaceFlinger::createConnection方法;
  4. SurfaceFlinger::createConnection方法中建立一個Client物件,並透過Binder返回給SurfaceComposerClient::mClient;

之後再呼叫SurfaceComposerClient中的方法時就可以通過mClient這個客戶端去呼叫到SurfaceFlinger服務的功能了

結合上面的類圖和下面的時序圖,大概總結如下


 

3 小結

這一篇文章中講解了應用程式中如何建立和SurfaceFlinger溝通的橋樑,即得到SurfaceFlinger的遠端代理客戶端,之後就通過這個代理客戶端向SurfaceFlinger傳送請求或獲取資訊。

 


必讀:

Android 12(S) 圖形顯示系統 - 開篇

 


 

 

相關文章