1 前言
上一篇文章中我們已經建立了一個Native示例應用,從使用者的角度瞭解了圖形顯示系統API的基本使用,從這篇文章開始我們將基於這個示例應用深入圖形顯示系統API的內部實現邏輯,分析運作流程。
本篇將聚焦應用和SurfaceFlinger的活動,即應用是如何與SurfaceFlinger這個服務建立連線並進行通訊的。讓我們開始吧!
注:本篇涉及的程式碼位置:
/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的原理在此就不展開講了,相信你在網路上可以搜尋到很多優秀的講解文章。
這裡請先留意兩點:
- ComposerService中有成員mComposerService,它代表了SurfaceFlinger服務的代理客戶端;
- 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物件的方法。
前面的講解看起來紛紛擾擾,簡單的,抽象的概括就是:
- 建立SurfaceComposerClient物件;
- SurfaceComposerClient::onFirstRef方法中透過ComposerService::getComposerService()獲取到SurfaceFlinger服務的代理客戶端;
- 呼叫SurfaceFlinger服務的代理客戶端的createConnection方法,進而跨程式呼叫到SurfaceFlinger::createConnection方法;
- SurfaceFlinger::createConnection方法中建立一個Client物件,並透過Binder返回給SurfaceComposerClient::mClient;
之後再呼叫SurfaceComposerClient中的方法時就可以通過mClient這個客戶端去呼叫到SurfaceFlinger服務的功能了
結合上面的類圖和下面的時序圖,大概總結如下
3 小結
這一篇文章中講解了應用程式中如何建立和SurfaceFlinger溝通的橋樑,即得到SurfaceFlinger的遠端代理客戶端,之後就通過這個代理客戶端向SurfaceFlinger傳送請求或獲取資訊。
必讀:
Android 12(S) 圖形顯示系統 - 開篇