Android的UI顯示原理之Surface的建立

本文是Android視圖層源碼分析系列第二篇文章,經過上一篇文章深刻剖析Window組成已經瞭解到WindowManager.addView(contentView)最終會交給WindowManagerService處理,WindowManagerService會建立這個contentView相關的UI載體Surface,本文的目的就是理清Surface的建立過程,以及它與SurfaceFlinger的關係。java

文章比較長,但但願你能夠堅持看完,相信會有必定收穫的android

本文是基於Google Android Repo中的較新的源碼分析的。Android UI渲染這一塊變化仍是比較大的,邏輯可能和網上大部分文章有一些出入。git

在本文正式開始以前,咱們先來了解一下與SurfaceFlinger相關的基礎知識:github

  • 與SurfaceFlinger相關的基礎知識

SurfaceFlinger能夠說是Android UI渲染體系的核心,在Android系統啓動時會啓動SurfaceFlinger服務,它的主要做用就是被Android應用程序調用,把繪製(測量,佈局,繪製)後的窗口(Surface)渲染到手機屏幕上。因此整個 UI刷新過程可能像下面這張圖:bash

固然實際上的UI渲染原理可沒有像上圖那樣這麼簡單。爲了接下來在源碼追蹤的過程當中不迷路,咱們帶着下面幾個問題來開始分析:微信

  1. WindowManagerService是如何管理Window的?
  2. Surface是如何建立的?
  3. SurfaceFlinger是如何管理多個應用的UI渲染的?
  4. SurfaceFlinger中UI渲染的基本單元是什麼?

ok,接下來就開始Android UI顯示原理之Surface的建立的主要流程分析。因爲整個體系的源碼流程很複雜,所以在追蹤源碼時我只貼了一些整個流程分析中的主要節點,而且加了一些註釋。session

在上一篇文章中咱們知道,ViewRootImpl管理着整個view tree。 對於ViewRootImpl.setView(),咱們能夠簡單的把它當作一個UI渲染操做的入口,所以咱們就從這個方法開始看:app

WindowManagerService對於Window的管理

ViewRootImpl.javaide

public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
    ...
    //mWindowSession是一個aidl,ViewRootImpl利用它來和WindowManagerService交互
    //mWindow是一個aidl,WindowManagerService能夠利用這個對象與服務端交互
    //mAttachInfo能夠理解爲是一個data bean,能夠跨進程傳遞
    res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
            getHostVisibility(), mDisplay.getDisplayId(), mWinFrame,
            mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
            mAttachInfo.mOutsets, mAttachInfo.mDisplayCutout, mInputChannel);
    ...
}
複製代碼

ViewRootImpl.setView()方法會向WindowManagerService請求添加一個Window,mWindowSession.addToDisplay()跨進程最終調用到了WindowManagerService.addWindow():函數

WindowManagerService.java

public int addWindow(Session session, IWindow client...) {
    ...
    //WindowState用來描述一個Window
    final WindowState win = new WindowState(this, session, client, token, parentWindow,
                appOp[0], seq, attrs, viewVisibility, session.mUid,
                session.mCanAddInternalSystemWindow);
    ...
    win.attach();  //會建立一個SurfaceSession

    mWindowMap.put(client.asBinder(), win); //mWindowMap是WindowManagerService用來保存當前全部Window新的的集合
    ...
    win.mToken.addWindow(win); //一個token下會有多個win state。 其實token與PhoneWindow是一一對應的。
    ...
}
複製代碼

WindowStateWindowManagerService用來描述應用程序的一個Window的對象。上面註釋我標註了win.attach(),這個方法能夠說是WindowSurfaceFlinger連接的起點,它最終會調用到Session.windowAddedLocked():

Session.java

void windowAddedLocked(String packageName) {
    ...
    if (mSurfaceSession == null) { 
        ...
        mSurfaceSession = new SurfaceSession();
        ...
    }
}

//SurfaceSession類的構造方法
public final class SurfaceSession {
    private long mNativeClient; // SurfaceComposerClient*

    public SurfaceSession() {
        mNativeClient = nativeCreate(); 
    }
複製代碼

這裏調用了native方法nativeCreate(),這個方法實際上是返回了一個SurfaceComposerClient指針。那這個對象是怎麼建立的呢?

SurfaceComposerClient的建立

android_view_SurfaceSession.cpp

static jlong nativeCreate(JNIEnv* env, jclass clazz) {
    SurfaceComposerClient* client = new SurfaceComposerClient(); //構造函數其實並無作什麼
    client->incStrong((void*)nativeCreate);
    return reinterpret_cast<jlong>(client);
}
複製代碼

即構造了一個SurfaceComposerClient對象。並返回它的指針。這個對象一個應用程序就有一個,它是應用程序與SurfaceFlinger溝通的橋樑,爲何這麼說呢?在SurfaceComposerClient指針第一次使用時會調用下面這個方法:

//這個方法在第一次使用SurfaceComposerClient的指針的時候會調用
void SurfaceComposerClient::onFirstRef() {
    ....
    sp<ISurfaceComposerClient> conn;
    //sf 就是SurfaceFlinger
    conn = (rootProducer != nullptr) ? sf->createScopedConnection(rootProducer) :
            sf->createConnection();
    ...
}
複製代碼

即經過SurfaceFlinger(它自己具備跨進程通訊的能力)建立了一個ISurfaceComposerClient對象:

SurfaceFlinger.cpp

sp<ISurfaceComposerClient> SurfaceFlinger::createConnection() {
    return initClient(new Client(this)); //initClient這個方法其實並無作什麼,
}
複製代碼

即構造了一個Client對象,Client實現了ISurfaceComposerClient接口。是一個能夠跨進程通訊的aidl對象。即SurfaceComposerClient能夠經過它來和SurfaceFlinger通訊。除此以外它還能夠建立Surface,而且維護一個應用程序的全部Layer(下文會分析到它是什麼)它是一個十分重要的對象,咱們先來看一下它的組成,它所涉及的其餘東西在下文分析中都會講到:

Client.h

class Client : public BnSurfaceComposerClient
{
public:
    ...
    void attachLayer(const sp<IBinder>& handle, const sp<Layer>& layer);
    void detachLayer(const Layer* layer);
    ...
private:
    // ISurfaceComposerClient interface。   gbp很重要,它維護這一個應用程序的渲染 Buffer隊列
    virtual status_t createSurface(...sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp);

    virtual status_t destroySurface(const sp<IBinder>& handle); 

    //跨進程通訊方法
    virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags);
    ...

    // constant
    sp<SurfaceFlinger> mFlinger;

    // protected by mLock
    DefaultKeyedVector< wp<IBinder>, wp<Layer> > mLayers; // 一個應用程序的全部Layer
    ...
};
複製代碼

通過上面這一頓源碼分析,咱們大概知道了ViewRootImpl.setView()所引起的主要操做:

  1. WindowManagerService建立了一個WindowState。用來表示客戶端的一個Window
  2. WindowManagerService建立了一個SurfaceSession,SurfaceSession會與SurfaceFlinger構建連接,建立了一個SurfaceComposerClient對象,一個應用程序只具備一個這個對象。
  3. SurfaceComposerClient建立了一個Client, 這個對象十分重要,它維護這應用程序的渲染核心數據,並負責與SurfaceFlinger通訊。

以下圖:

通過上面的步驟,應用程序的ViewRootImpl已經被WindowManagerService識別,而且應用程序已經與SurfaceFlinger創建鏈接。即建立了SurfaceComposerClientClient對象

文章開始就已經說了SurfaceWindow(ViewRootImpl)的UI載體,那Surface是在哪裏建立的呢?

Surface的建立

其實一個ViewRootImpl就對應一個Surface。這點能夠經過ViewRootImpl的源碼看出:

ViewRootImpl.java

public final Surface mSurface = new Surface();
複製代碼

ViewRootImpl在構造的時候就new 了一個 Surface。但其實這個新new的Surface並無什麼邏輯,它的構造函數是空的。那麼Surface究竟是在哪裏建立的呢?

觸發Surface的建立操做

咱們仍是回到ViewRootImpl.setView()來看一下:

public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
    ...
    requestLayout(); //susion 請求layout。先添加到待渲染隊列中  
    ...
    res = mWindowSession.addToDisplay(mWindow, ...); //WindowManagerService會建立mWindow對應的WindowState
    ...
}
複製代碼

即在向WindowManagerService請求建立WindowState以前,調用了requestLayout(),這個方法會引發ViewRootImpl所管理的整個view tree的從新渲染。它最終會調用到scheduleTraversals():

void scheduleTraversals() {
    ...
    mChoreographer.postCallback(Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
    ...
}
複製代碼

對於Choreographer本文不作詳細的分析,能夠去參考 Android Choreographer 源碼分析的分析來了解這個類。

scheduleTraversals()會經過Choreographer來post一個mTraversalRunnableChoreographer接收顯示系統的時間脈衝(垂直同步信號-VSync信號,16ms發出一次),在下一個frame渲染時控制執行這個mTraversalRunnable

可是mTraversalRunnable的執行至少要在應用程序與SurfaceFlinger創建鏈接以後。這是由於渲染操做是由SurfaceFlinger負責調度了,若是應用程序尚未與SurfaceFlinger建立鏈接,那SurfaceFlinger固然不會渲染這個應用程序。因此在執行完mWindowSession.addToDisplay(mWindow, ...)以後,纔會執行mTraversalRunnable:

ViewRootImpl.java

final class TraversalRunnable implements Runnable {
    @Override
    public void run() {
        doTraversal();
    }
}
複製代碼

doTraversal()會調用到ViewRootImpl.performTraversals(),大部分同窗可能知道這個方法是一個view treemeasure/layout/draw的控制方法:

private void performTraversals() {
    finalView host = mView; //mView是一個Window的根View,對於Activity來講就是DecorView
    ...
    relayoutWindow(params, viewVisibility, insetsPending);
    ...
    performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
    ...         
    performLayout(lp, mWidth, mHeight);
    ...
    performDraw();
    ...
}
複製代碼

Surface的具體建立就由relayoutWindow(params, viewVisibility, insetsPending)這個方法來完成的。這個方法會經過IPC調用到WindowManagerService.relayoutWindow():

ViewRootImpl.java

private int relayoutWindow(WindowManager.LayoutParams params, ...) throws RemoteException {
    ...
    int relayoutResult = mWindowSession.relayout(mWindow,..., mSurface);
    ...
}
複製代碼

上面我省略了mWindowSession.relayout()方法的不少參數,不過有一個十分重要的參數我沒有省略,就是mSurface。前面已經分析了它就是一個空的Surface對象。其實:

真正的Surface建立是由SurfaceControl完成的,應用程序ViewRootImplSurface只是一個指針,指向這個Surface

下面就來看一下SurfaceControl是如何建立Surface的:

mWindowSession.relayout()會調用到WindowManagerService.relayoutWindow():

WindowManagerService.java

//這裏的outSurface其實就是ViewRootImpl中的那個Surface
public int relayoutWindow(Session session, IWindow client....Surface outSurface){ 
    ...
    result = createSurfaceControl(outSurface, result, win, winAnimator);  
    ...
}

private int createSurfaceControl(Surface outSurface, int result, WindowState win,WindowStateAnimator winAnimator) {
    ...
    surfaceController = winAnimator.createSurfaceLocked(win.mAttrs.type, win.mOwnerUid);
    ...
    surfaceController.getSurface(outSurface);
}
複製代碼

winAnimator.createSurfaceLocked其實是建立了一個SurfaceControl。即上面是先構造SurfaceControl,而後在構造Surface

SurfaceControl的建立

winAnimator.createSurfaceLocked實際上是經過SurfaceControl的構造函數建立了一個SurfaceControl對象,這個對象的做用其實就是負責維護Surface,Surface其實也是由這個對象負責建立的,咱們看一下這個對象的構造方法:

SurfaceControl.java

long mNativeObject; //成員指針變量,指向native建立的SurfaceControl

private SurfaceControl(SurfaceSession session, String name, int w, int h, int format, int flags,
            SurfaceControl parent, int windowType, int ownerUid){
    ...
    mNativeObject = nativeCreate(session, name, w, h, format, flags,
        parent != null ? parent.mNativeObject : 0, windowType, ownerUid);
    ...
}
複製代碼

即調用了nativeCreate()並返回一個SurfaceControl指針:

android_view_SurfaceControl.cpp

static jlong nativeCreate(JNIEnv* env, ...) {
    //這個client其實就是前面建立的SurfaceComposerClinent
    sp<SurfaceComposerClient> client(android_view_SurfaceSession_getClient(env, sessionObj)); 
    sp<SurfaceControl> surface; //建立成功以後,這個指針會指向新建立的SurfaceControl
    status_t err = client->createSurfaceChecked(String8(name.c_str()), w, h, format, &surface, flags, parent, windowType, ownerUid);
    ...
    return reinterpret_cast<jlong>(surface.get()); //返回這個SurfaceControl的地址
}
複製代碼

即調用到SurfaceComposerClient.createSurfaceChecked():

SurfaceComposerClient.cpp

//outSurface會指向新建立的SurfaceControl
status_t SurfaceComposerClient::createSurfaceChecked(...sp<SurfaceControl>* outSurface..) 
{
    sp<IGraphicBufferProducer> gbp; //這個對象很重要
    ...
    err = mClient->createSurface(name, w, h, format, flags, parentHandle, windowType, ownerUid, &handle, &gbp);
    if (err == NO_ERROR) {
        //SurfaceControl建立成功, 指針賦值
        *outSurface = new SurfaceControl(this, handle, gbp, true);
    }
    return err;
}
複製代碼

上面這個方法其實是調用Client.createSurface()來建立一個Surface。在建立時有一個很重要的參數sp<IGraphicBufferProducer> gbp,在下面源碼分析中咱們也要重點注意它。這是由於應用所渲染的每一幀,實際上都會添加到IGraphicBufferProducer中,來等待SurfaceFlinger的渲染。這個過程咱們在下一篇文章中會分析,咱們先繼續來看一下Surface是如何被Client建立的:

Client.cpp

status_t Client::createSurface(...)
{
    ...
    //gbp 直接透傳到了SurfaceFlinger
    return mFlinger->createLayer(name, this, w, h, format, flags, windowType, ownerUid, handle, gbp, &parent);
}
複製代碼

??? 不是說好的要建立Surface呢?怎麼變成mFlinger->createLayer()? 額,我也不明白這個忽然轉變,不過咱們只要知道:

SurfaceSurfaceFlinger中對應的實體實際上是Layer

咱們繼續看一下mFlinger->createLayer()

SurfaceFlinger.cpp

status_t SurfaceFlinger::createLayer(const String8& name,const sp<Client>& client...)
{
    status_t result = NO_ERROR;
    sp<Layer> layer; //將要建立的layer
    switch (flags & ISurfaceComposerClient::eFXSurfaceMask) {
        case ISurfaceComposerClient::eFXSurfaceNormal:
            result = createBufferLayer(client,
                    uniqueName, w, h, flags, format,
                    handle, gbp, &layer); // 注意gbp,這時候尚未構造呢!
            break;
            ... //Layer 分爲好幾種,這裏不所有列出
    }
    ...
    result = addClientLayer(client, *handle, *gbp, layer, *parent);  //這個layer和client相關聯, 添加到Client的mLayers集合中。
    ...
    return result;
}
複製代碼

SurfaceFlinger.createLayer()方法能夠看出Layer分爲好幾種。咱們這裏只對普通的BufferLayer的建立作一下分析,看createBufferLayer():

status_t SurfaceFlinger::createBufferLayer(const sp<Client>& client... sp<Layer>* outLayer)
{
    ...
    sp<BufferLayer> layer = new BufferLayer(this, client, name, w, h, flags);
    status_t err = layer->setBuffers(w, h, format, flags);  //設置layer的寬高
    if (err == NO_ERROR) {
        *handle = layer->getHandle(); //建立handle
        *gbp = layer->getProducer(); //建立 gbp IGraphicBufferProducer
        *outLayer = layer; //把新建的layer的指針拷貝給outLayer,這樣outLayer就指向了新建的BufferLayer
    }
    return err;
}
複製代碼

前面我說過IGraphicBufferProducer(gbp)是一個很重要的對象,它涉及到SurfaceFlinger的渲染邏輯,下面咱們就看一下這個對象的建立邏輯:

IGraphicBufferProducer(gbp)的建立

BufferLayer.cpp

sp<IGraphicBufferProducer> BufferLayer::getProducer() const {
    return mProducer;
}
複製代碼

mProducer實際上是Layer的成員變量,它的建立時機是Layer第一次被使用時:

void BufferLayer::onFirstRef() {
    ...
    BufferQueue::createBufferQueue(&producer, &consumer, true); 
    mProducer = new MonitoredProducer(producer, mFlinger, this);
    ...
}
複製代碼

因此mProducer的實例是MonitoredProducer,但其實它只是一個裝飾類,它實際功能都委託給構造它的參數producer:

BufferQueue.cpp

void BufferQueue::createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
    ...
    sp<IGraphicBufferProducer> producer(new BufferQueueProducer(core, consumerIsSurfaceFlinger));
    sp<IGraphicBufferConsumer> consumer(new BufferQueueConsumer(core)); //注意這個consumer
    ...
    *outProducer = producer;
    *outConsumer = consumer;
}
複製代碼

因此實際實現mProducer的工做的queueProducerBufferQueueProducer

因此構造一個SurfaceControl所作的工做就是建立了一個SurfaceControl,並讓SurfaceFlinger建立了一個對應的LayerLayer中有一個IGraphicBufferProducer,它的實例是BufferQueueProducer

能夠用下面這個圖來描述SurfaceControl的建立過程:

從SurfaceControl中獲取Surface

咱們回看WindowManagerService.createSurfaceControl(), 來看一下java層的Surface對象究竟是個什麼:

WindowManagerService.java

private int createSurfaceControl(Surface outSurface, int result, WindowState win,WindowStateAnimator winAnimator) {
    ...
    surfaceController = winAnimator.createSurfaceLocked(win.mAttrs.type, win.mOwnerUid);
    ...
    surfaceController.getSurface(outSurface);
}
複製代碼

上面咱們已經瞭解了winAnimator.createSurfaceLocked的整個過程,咱們看一下surfaceController.getSurface(outSurface), surfaceControllerWindowSurfaceController的實例:

//WindowSurfaceController.java
void getSurface(Surface outSurface) {
    outSurface.copyFrom(mSurfaceControl);
}

//Surface.java
public void copyFrom(SurfaceControl other) {
    ...
    long surfaceControlPtr = other.mNativeObject;
    ...
    long newNativeObject = nativeGetFromSurfaceControl(surfaceControlPtr);
    ...
    mNativeObject = ptr; // mNativeObject指向native建立的Surface
}
複製代碼

Surface.copyFrom()方法調用nativeGetFromSurfaceControl()來獲取一個指針,這個指針是根據前面建立的SurfaceControl的指針來尋找的,即傳入的參數surfaceControlPtr:

android_view_Surface.cpp

static jlong nativeGetFromSurfaceControl(JNIEnv* env, jclass clazz, jlong surfaceControlNativeObj) {
    sp<SurfaceControl> ctrl(reinterpret_cast<SurfaceControl *>(surfaceControlNativeObj)); //把java指針轉化內native指針
    sp<Surface> surface(ctrl->getSurface()); //直接構造一個Surface,指向 ctrl->getSurface()
    if (surface != NULL) {
        surface->incStrong(&sRefBaseOwner); //強引用
    }
    return reinterpret_cast<jlong>(surface.get());
}
複製代碼

這裏的ctrl指向前面建立的SurfaceControl,繼續追溯ctrl->getSurface():

SurfaceControl.cpp

sp<Surface> SurfaceControl::getSurface() const
{
    Mutex::Autolock _l(mLock);
    if (mSurfaceData == 0) {
        return generateSurfaceLocked();
    }
    return mSurfaceData;
}

sp<Surface> SurfaceControl::generateSurfaceLocked() const
{
    //這個mGraphicBufferProducer其實就是上面分析的BufferQueueProducer
    mSurfaceData = new Surface(mGraphicBufferProducer, false); 
    return mSurfaceData;
}
複製代碼

即直接new了一個nativie的Surface返回給java層,java層的Surface指向的就是native層的Surface

因此Surface的實際建立能夠用下圖表示:

通過上面這個圖,也能夠理解SurfaceControl爲何叫SurfaceControl了。

本文到這裏已經很長了,對於UI的渲染過程:即ViewRootImpl是如何渲染到Surface到下一篇文章再分析。

歡迎關注個人Android進階計劃看更多幹貨

歡迎關注個人微信公衆號:susion隨心

參考文章:

AndroidUI系列—淺談圖像渲染機制

一篇文章看明白 Android 圖形系統 Surface 與 SurfaceFlinger 之間的關係

相關文章
相關標籤/搜索