天天看點

Android 7.1 GUI系統-surfaceflinger(四)

surfaceflinger的啟動:

Android P 圖形顯示系統 https://www.jianshu.com/u/f92447ae8445

Android GUI系統之SurfaceFlinger https://blog.csdn.net/vviccc/article/details/104860616

frameworks/native/services/surfaceflinger/surfaceflinger.rc
service surfaceflinger /system/bin/surfaceflinger
    class core
    user system
    group graphics drmrpc readproc
    onrestart restart zygote
    writepid /dev/stune/foreground/tasks
           

surfaceflinger屬于系統的底層支撐服務,應該在系統開機的早期就要起來,比如開機動畫的繪制就要依賴surfaceflinger,從它的rc檔案可知,這個服務的class是core,是以在解析init.rc時,通過class_startcore就啟動了所有class是core的服務。而且在surfaceflinger重新開機時,關鍵程序zygote也會重新開機。

插播截取的一段init.rc的代碼看下究竟:

system/core/rootdir/init.rc
//長按power鍵,Healthd會通過發一個property信号觸發一個full boot,也即是當屬性sys.boot_from_charger_mode滿足了值為1時就會觸發,接着會觸發late-init 這個action。
on property:sys.boot_from_charger_mode=1
	class_stop charger
	trigger late-init

//late-init這個action,主要是挂載檔案系統,然後觸發boot。
on late-init
	trigger early-fs
	trigger fs
	trigger late-fs
	trigger boot

//在boot事件中,基礎網絡初始話,基本的kernel參數,系統服務和背景程序的權限設定等,最後啟動class類型是core的系統服務。
on boot
	hostname localhost
	write /proc/sys/vm/overcommit_memory 1
	chmod 0664 /sys/module/lowmemorykiller/parameters/adj
	chown system system /sys/power/state
	class_start core
           

接着分析surfaceflinger的啟動。

main_surfaceflinger.cpp

int main(int, char**)@main_surfaceflinger.cpp {
//下面這三行代碼是一個獨立的程序起來時,必須調用的,其中ps->startThreadPool()會間接調用到IPCThreadState::self()->joinThreadPool(mIsMain);最終讓這個程序進入一個binder_loop的循環。
	ProcessState::self()->setThreadPoolMaxThreadCount(4);
	sp<ProcessState> ps(ProcessState::self());
	ps->startThreadPool();
//執行個體化一個surfaceflinger,就是new SurfaceFlinger();
	sp<SurfaceFlinger> flinger = DisplayUtils::getInstance()→getSFInstance();
//設定程序優先級,PRIORITY_URGENT_DISPLAY這是級别還是很高的。
	setpriority(PRIO_PROCESS, 0, PRIORITY_URGENT_DISPLAY);
//在client發起連接配接之前執行初始化。
	flinger→init();
//把surfaceflinger,GpuService注冊到ServiceManager。
	sp<IServiceManager> sm(defaultServiceManager());
	sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false);
	sp<GpuService> gpuservice = new GpuService();
	sm->addService(String16(GpuService::SERVICE_NAME), gpuservice, false);
//運作surfaceflinger,等待client的請求。
	flinger->run();
	return 0;
}
           

SurfaceFlinger的構造函數中沒有做太多事情,隻是給變量賦了初始值,在它第一次被引用時會執行其onFirstRef函數。

void SurfaceFlinger::onFirstRef()@SurfaceFlinger.cpp{
//初始化事件隊列MessageQueue,
    mEventQueue.init(this);
}
           

//這個MessageQueue.cpp是surfaceflinger自定義的,是消息循環處理機制的管理者,但是并不是系統标準的消息隊列。

void MessageQueue::init(const sp<SurfaceFlinger>& flinger)@MessageQueue.cpp{
    mFlinger = flinger;
//Looper是系統中通用的實作,system/core/libutils/looper.cpp
    mLooper = new Looper(true);
//Handler也是surfaceflinger自定義的一個事件處理器,是MessageQueue.h的内部類,并不是通用的Handler。
    mHandler = new Handler(*this);
}
           

//surfaceflinger的初始化,包括egl的運作環境的設定,跟vsync脈沖信号有關的EventThread等。這塊内容不在這裡做展開。

void SurfaceFlinger::init() @SurfaceFlinger.cpp{
	mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
	eglInitialize(mEGLDisplay, NULL, NULL);
	sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync,
		vsyncPhaseOffsetNs, true, "app");
	mEventThread = new EventThread(vsyncSrc, *this);
	mHwc = new HWComposer(this);
	mHwc->setEventHandler(static_cast<HWComposer::EventHandler*>(this));
	mEventControlThread = new EventControlThread(this);
	mEventControlThread->run("EventControl", PRIORITY_URGENT_DISPLAY);
	initializeDisplays();
}
           

接下來分析surfaceflinger的工作線程是怎麼運作起來的。

void SurfaceFlinger::run() @SurfaceFlinger.cpp{
//可以看到這裡是一個無線循環。
    do {
        waitForEvent();
    } while (true);
}
           

//進一步調用MessageQueue中的waitMessage。

void SurfaceFlinger::waitForEvent() @SurfaceFlinger.cpp{
    mEventQueue.waitMessage();
}
           

//這裡依然是死循環,永遠不會跳出,即使發生了錯誤,這也可以了解,surfaceflinger是整個GUI系統的核心,如果它退出了,基本系統也就癱了。

void MessageQueue::waitMessage() @MessageQueue.cpp{
    do {
        IPCThreadState::self()->flushCommands();
        int32_t ret = mLooper->pollOnce(-1);
        switch (ret) {
            case Looper::POLL_WAKE:
            case Looper::POLL_CALLBACK:
                continue;
            case Looper::POLL_ERROR:
                ALOGE("Looper::POLL_ERROR");
                continue;
            case Looper::POLL_TIMEOUT:
                // timeout (should not happen)
                continue;
            default:
                // should not happen
                ALOGE("Looper::pollOnce() returned unknown status %d", ret);
                continue;
        }
    } while (true);
}
           

在上面的循環中,會通過mLooper->pollOnce(-1);不斷的讀取消息進行處理。前面說過這裡的MessageQueue并不是android系統通用的消息隊列,它是消息循環處理機制的管理者,在它的init函數中也看到,内部包含了looper和hander,Looper中的mMessageEnvelopes才是真正存儲消息的地方,而這個handle也隻是一個中介,并沒有實際去處理發給surfaceflinger的消息請求,而是進一步回調了surfaceflinger的onMessageReceived方法。

void MessageQueue::Handler::handleMessage(const Message& message) @MessageQueue.cpp{
    switch (message.what) {
        case INVALIDATE:
            android_atomic_and(~eventMaskInvalidate, &mEventMask);
            mQueue.mFlinger->onMessageReceived(message.what);
            break;
        case REFRESH:
            android_atomic_and(~eventMaskRefresh, &mEventMask);
            mQueue.mFlinger->onMessageReceived(message.what);
            break;
    }
}
           

通過上面的分析,知道surfaceflinger的消息處理架構是通過MessageQueue把消息請求發送到Looper的mMessageEnvelopes隊列,然後通過mLooper->pollOnce(-1);方法依次取出事件處理,其中的handle會把INVALIDATE,REFRESH這兩類消息請求轉給surfaceflinger做實質的處理。

應用程式向surfaceflinger發送的消息請求分同步、異步兩種,異步推送就是消息發過去就直接傳回了,不需要等待執行結果。接下來主要看下同步的請求是怎麼處理的?

以前面的應用程式申請建立一個layer為例:

status_t Client::createSurface()@Client.cpp{
	 class MessageCreateLayer : public MessageBase {
		virtual bool handler() {
			result = flinger->createLayer(name, client, w, h, format, flags,
				handle, gbp);
			return true;
		}
	}
	sp<MessageBase> msg = new MessageCreateLayer(mFlinger.get(),…);
	mFlinger->postMessageSync(msg);
}
           

省略了很多代碼,隻關注消息處理相關的,這裡通過postMessageSync發出一個同步消息,

status_t SurfaceFlinger::postMessageSync(const sp<MessageBase>& msg,
        nsecs_t reltime, uint32_t /* flags */) @SurfaceFlinger.cpp{
    status_t res = mEventQueue.postMessage(msg, reltime);
    if (res == NO_ERROR) {
        msg->wait();
    }
    return res;
}
           

在上面的函數中,除了調用mEventQueue.postMessage把消息入隊外,還調用了msg->wait();這個wait從字面意思也能看出是讓調用者線程挂起了。

//下面的MessageQueue依然是surfaceflinger自定義的類。

MessageQueue.h
class MessageBase : public MessageHandler{
	void wait() const { barrier.wait(); }
}
           

這裡是使用barrier來實作的同步,這個barrier隻在surfaceflinger中有使用,應該說是專門為surfaceflinger設計的,是以有必要去了解下它的實作原理:

frameworks/native/services/surfaceflinger/Barrier.h
class Barrier
{
public:
    inline Barrier() : state(CLOSED) { }
    inline ~Barrier() { }
//釋放等待在這個barrier上的線程。
    void open() {
        Mutex::Autolock _l(lock);
        state = OPENED;
        cv.broadcast();
    }
//重新設定barrier,wait方法會被block,直到open方法被調用。
    void close() {
        Mutex::Autolock _l(lock);
        state = CLOSED;
    }
//這裡會一直等待,直到barrier的狀态是OPEN。
    void wait() const {
        Mutex::Autolock _l(lock);
        while (state == CLOSED) {
            cv.wait(lock);
        }
    }
private:
    enum { OPENED, CLOSED };
    mutable     Mutex       lock;
    mutable     Condition   cv;
    volatile    int         state;
};
           

可以看到barrier是基于Mutex和condition實作的一個模型。Mutex實際上是基于pthread接口的在封裝,隻要是涉及到對某個共享資源的通路,都可以認為是Mutex的問題領域;但是有時候對某一個共享資源的通路的目的,隻是想判斷它是不是滿足了某個條件,比如state==CLOSED,并且什麼時候滿足這一條件是未知的,這種情況下,如果依然用Mutex來處理,就要一直去輪詢,這顯然是太浪費cpu資源了,是以才有了condition,但是condition本身并不完整,比如它沒有指定具體的條件是什麼,是以它需要被填充了具體條件才能真正的使用,這裡的barrier就是一個填充了具體條件的condition,這裡的具體條件就是state == CLOSED或者state == OPEN。

介紹完了Barrier的實作原理,再來看下它是怎麼使用的,postMessageSync時調用了barrier.wait()把調用者線程挂起,那什麼時候把它喚醒呢?一種可能的情況就是這個消息請求被處理了,就應該把調用者喚醒,讓他繼續執行未完成的工作。

是以要從消息處理的接口入手:

前面分析過,在MessageQueue的waitMessage中,是通過mLooper->pollOnce(-1);不斷的讀取消息進行處理的。

system/core/libutils/Looper.cpp
int Looper::pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData) @Looper.cpp{
	result = pollInner(timeoutMillis);
}
           

//從pollInner看出,它調用了message的handle中的方法handleMessage。

int Looper::pollInner(int timeoutMillis) {
	const MessageEnvelope& messageEnvelope = mMessageEnvelopes.itemAt(0);
	sp<MessageHandler> handler = messageEnvelope.handler;
	handler->handleMessage(message);
}
           

是以要看發送的那條消息中的handler是哪裡來的?

MessageCreateLayer繼承自MessageBase(MessageQueue.cpp中),

MessageQueue.cpp
void MessageBase::handleMessage(const Message&) {
    this->handler();
    barrier.open();
};
           

由于MessageBase的handler的方法是純虛函數,是以這裡調用的handle是子類的handler的方法,也即是MessageCreateLayer中的handler方法,這個方法會調用surfaceflinger來完成請求。

然後調用了barrier.open();喚醒被等待的線程。

分析了surfaceflinger的消息處理機制,再來看應用程式端是如何跟surfaceflinger通信的。

前面在分析BufferQueue時,引用過GLTest::SetUp()中一段代碼,其中建立了SurfaceComposerClient執行個體,可以作為應用程式跟surfaceflinger通信的一個橋梁。

SurfaceComposerClient.cpp
void SurfaceComposerClient::onFirstRef() {
    sp<ISurfaceComposer> sm(ComposerService::getComposerService());
    if (sm != 0) {
        sp<ISurfaceComposerClient> conn = sm->createConnection();
        if (conn != 0) {
            mClient = conn;
            mStatus = NO_ERROR;
        }
    }
}
           

上面的實作中,首先擷取surfaceflinger的句柄ISurfaceComposer,這個名字起的容易誤解,surfaceflinger雖然注冊在ServiceManager中的名字是“surfaceflinger”,但是其服務端實作的binder接口卻是ISurfaceComposer,可以從它的繼承關系得到驗證:

class SurfaceFlinger : public BnSurfaceComposer,private Ibinder::DeathRecipient,
	private HWComposer::EventHandler{}

接着SurfaceComposerClient::onFirstRef() 分析,通過surfaceflinger的 createConnection傳回一個ISurfaceComposerClient 執行個體,ISurfaceComposerClient對應的服務端是Client,
sp<ISurfaceComposerClient> SurfaceFlinger::createConnection()
	@SurfaceFlinger.cpp{
    sp<ISurfaceComposerClient> bclient;
    sp<Client> client(new Client(this));
    status_t err = client->initCheck();
    if (err == NO_ERROR) {
        bclient = client;
    }
    return bclient;
}
           

這個Client才是surfaceflinger跟應用程式互動的紐帶,比如應用程式申請surface的請求就是經過client傳遞到surfaceFlinger,可以任務client是surfaceflinger安排在應用程式中一個代理,任何有UI界面的應用程式在surfaceflinger中都有對應的Client執行個體,但是應用程式并沒有直接使用Client,而是通過ISurfaceComposerClient,ISurfaceComposerClient是應用程式與Client之間的binder接口,是以應用程式端一個請求先是通過ISurfaceComposerClient,然後傳到Client,client收到者請求後,沒有讓surfaceflinger馬上執行,而是把讓先投遞到surfaceflinger的消息隊列,然後讓client所在的線程wait,因為surfaceflinger會處理所有應用程式的請求,不能來一個請求就就打斷surfaceflinger正在執行的操作,最後SurfaceFlinger處理完成後,傳回結果,喚醒wait的應用程式。

繼續閱讀