Android Surface創建

一、 OverView

Android Surface的創建涉及三個進程

  1. App 進程
    Surface本質上是一個Native Window, 並且保存着需要在屏幕上顯示的數據(buffer), 它通常包含 triple-buffers 以防止Jank。
    那麼誰要創建Surface呢? 當然是App了,App需要將自己的內容顯示在屏幕上,所以App負責發起Surface創建請求,創建好Surface後, 就可以直接可以在canvas上畫圖等,最終都會保存到Surface裏的buffer裏,最後由SurfaceFlinger合成並顯示。

  2. System_Server進程
    主要是其中的WindowManagerService, 負責接收APP請求,向SurfaceFlinger發起具體的請求創建Surface, 且WMS需要創建Surface的輔助管理類,如SurfaceControl。
    爲什麼需要與system進程打交道呢?App直接通知SurfaceFlinger創建Surface不就行了?爲什麼還需要通過system進程呢?個人猜想可能是統一由WMS管理,以及當前系統中的窗口的Z -order計算, 減輕SurfaceFlinger的負擔。

  3. SurfaceFlinger
    爲App進程創建具體的Surface, 在SurfaceFlinger裏對應成Layer, 然後負責管理、合成顯示。

本文以這三個進程創建Surface過程來寫。 先來一張 OverView 圖

Surface overview

二、 與App進程相關的類

2.1 WMS中Session類的代理 IWindowSession

IWindowSession主要是App與WMS進行交互的類,它在ViewRootImpl中聲明, 在ViewRootImpl構造函數中實例化, 如下代碼

final IWindowSession mWindowSession;

public ViewRootImpl(Context context, Display display) {
    mWindowSession = WindowManagerGlobal.getWindowSession();
}

而mWindowSession具體又是通過 WindowManagerGlobal的靜態函數 getWindowSession()獲得

public static IWindowSession getWindowSession() {
    synchronized (WindowManagerGlobal.class) {
        if (sWindowSession == null) {
             ...
             IWindowManager windowManager = getWindowManagerService();
             sWindowSession = windowManager.openSession(...) //在WMS中打開一個Session 
             ...
        }
        return sWindowSession;
    }
}

由定義可知, sWindowSession聲明爲靜態變量,可知在整個App的生命中,只有一個sWindowSession實例。
另外 App端的 sWindowSession拿到的是IWindowSession.Stub.Proxy即 WMS中Session的代理, 如 圖P1所示。

2.2 Surface類

Surface是定義在ViewRootImpl中的成員,定義時並實例化了,如下

final Surface mSurface = new Surface();

由於 ViewRootImpl的個數與addView的調用次數相關,一個Activity可以多次調用addView, 也就是說一個Activity可以有多個Surface.

另外Surface被定義成final,也就是說mSurface不能重新再賦值了。

注意: 在ViewRootImpl中聲明的Surface只是一個空殼,它並沒有與真正的Surface映射起來,所以此時它是無效的Surface.

App進程通過 relayout 函數去創建真實Surface。

mWindowSession.relayout(..., mSurface);

三、System_Server進程中的Surface

system_server是一大塊,而與Surface相關的操作主要由WMS完成的。

3.1 Session和SurfaceSession

3.1.1 Session類

由第二節可知, Session是通過openSession創建的

public IWindowSession openSession(...) {
    Session session = new Session(this, callback, client, inputContext);
    return session;
}

3.1.2 SurfaceSession類

SurfaceSession的創建是在WindowState生成後創建的, 如

win.attach()   //在WMS的addWindow()
void attach() { //WindowState類
    mSession.windowAddedLocked();
}
void windowAddedLocked() {  //在Session類中
    if (mSurfaceSession == null) {
        mSurfaceSession = new SurfaceSession();
        mService.mSessions.add(this);
    }
    mNumWindow++;
}

可以把Session類理解APP與WMS之間的已經連接好的會話層。WMS將所有的Session加入到 mSessions裏。

Session和SurfaceSession可以參見圖中的P2

3.1.3 SurfaceSession的native層

接着上面看SurfaceSession的構造函數,

private long mNativeClient; // SurfaceComposerClient的Jni對象指針
public SurfaceSession() {
    mNativeClient = nativeCreate();
}

調用nativeCreate在JNI中進行創建,具體是創建什麼呢? 從mNativeClient的定義註釋可以猜測應該是創建一個SurfaceComposerClient,並且將其JNI對象地址保存到mNativeClient中,

static jlong nativeCreate(JNIEnv* env, jclass clazz) {
    SurfaceComposerClient* client = new SurfaceComposerClient();
    ...
    return reinterpret_cast<jlong>(client);  //獲得SurfaceComposerClient的地址
}

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

SurfaceComposerClient的相關UML可以參考圖中 P3所示。
另外SurfaceComposerClient繼承RefBase,所以在初始化後會調用一次onFirstRef

void SurfaceComposerClient::onFirstRef() {
    sp<ISurfaceComposer> sm(ComposerService::getComposerService()); //獲得SurfaceFlinger service
     sp<ISurfaceComposerClient> conn = sm->createConnection(); 
     //在SurfaceFlinger中創建Connection,也就是一個SurfaceFlinger的一個Client
}

createConnection會返回SurfaceFlingerClient類的Binder代理BpSurfaceComposerClient, 見P4所示。

注意: Session/SurfaceSession/SurfaceComposerClient 都是與APP相關的而非與某個Activity相關, 也就是它們相對於具體APP來說有且僅有一個實例。

3.2 SurfaceControl

當與APP相關的WMS(Session/SurfaceSession/BpSurfaceComposerClient),SurfaceFlinger(Client/BnSurfaceComposerClient 見第四節)相關類已經建立好後,此時就可以創建Surface了。

具體是在 ViewRootImpl的relayoutWindow(), 由performTraversals()調用

private void performTraversals() {
    ...
    boolean hadSurface = mSurface.isValid(); // 此時mSurface是空殼
    relayoutResult = relayoutWindow(params, viewVisibility, insetsPending);
    if (!hadSurface) {
        if (mSurface.isValid()) {  //mSurface有了正確的引用了
        ...
      }
    }
}

在relayoutWindow之前, mSurface僅是一個空殼,而在relayoutWindow之後, mSurface就已經創建好了,且有效。

private int relayoutWindow(...)
    int relayoutResult = mWindowSession.relayout(..., mSurface);
}

relayoutWindow “直接” 調用了WMS的relayoutWindow()

public int relayoutWindow(..., Surface outSurface) {
         //獲得WindowState, 表示一個Window
    WindowState win = windowForClientLocked(session, client, false); 
    WindowStateAnimator winAnimator = win.mWinAnimator; 
        //創建SurfaceControl
    result = createSurfaceControl(outSurface, result, win, winAnimator); 
}

3.2.1 創建java側的SurfaceControl

調用WindowStateAnimator的createSurfaceControl

private int createSurfaceControl(Surface outSurface, int result, WindowState win,
        WindowStateAnimator winAnimator) {
    WindowSurfaceController surfaceController = winAnimator.createSurfaceLocked();
    if (surfaceController != null) {
        surfaceController.getSurface(outSurface); 
    } 
    ...
    return result;
}

--- in WindowStateAnimator
WindowSurfaceController createSurfaceLocked() {
    mSurfaceController = new WindowSurfaceController(mSession.mSurfaceSession, ...);
    ...
    mSurfaceController.setPositionAndLayer(mTmpSize.left, mTmpSize.top, layerStack, mAnimLayer);
}

public WindowSurfaceController(SurfaceSession s, ...) {
  mSurfaceControl = new SurfaceControl(...)
}

它們之間建立的關係圖參考P5所示,


3.2.2 創建Native的SurfaceControl

現在看下SurfaceControl的構造函數,

public SurfaceControl(SurfaceSession session,...){
    mNativeObject = nativeCreate(session, name, w, h, format, flags);
}

調用jni層的nativeCreate函數來創建native層的SurfaceControl

static jlong nativeCreate(...) {
    sp<SurfaceComposerClient> client(android_view_SurfaceSession_getClient(env, sessionObj));
    sp<SurfaceControl> surface = client->createSurface(String8(name.c_str()), w, h, format, flags);
    return reinterpret_cast<jlong>(surface.get());
}

代碼中 client拿到的是 SurfaceComposerClient, 如P6所示,

sp<SurfaceControl> SurfaceComposerClient::createSurface(...)
{    
    sp<SurfaceControl> sur;
    if (mStatus == NO_ERROR) {
        sp<IBinder> handle;
        sp<IGraphicBufferProducer> gbp;
        status_t err = mClient->createSurface(name, w, h, format, flags, &handle, &gbp);
        if (err == NO_ERROR) {
            sur = new SurfaceControl(this, handle, gbp); //創建SurfaceControl
        }
    }
    return sur;
}

接着通過SurfaceComposerClient在SurfaceFlinger中創建Surface, 並且會返回SurfaceFlinger中的Handle以及IGraphicsBufferProducer的代理,如P7所示。

當SurfaceFlinger中創建好Surface後,在WMS的JNI層創建一個SurfaceControl, SurfaceControl顧名思義就是控制、操作Surface的類.

但是特別注意,這裏的SurfaceControl實際上是WMS控制、操作Surface(比如Surface的Z order值,以及position, 透明度等的設置)的而非APP.

3.2.3 創建Native層的Surface

在Java端的SurfaceControl創建好後,就開始創建真正的Native的Surface。回憶一下之前說的App端的Surface只是一個空殼,因爲它還沒有與真正的Native端的Surface聯繫起來。在這一小節將會把App端的Surface與真正的Surface聯繫起來。

--- in WindowSurfaceController
WindowSurfaceController surfaceController = winAnimator.createSurfaceLocked();
if (surfaceController != null) {
    surfaceController.getSurface(outSurface);  //獲得surface
}

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

這裏的outSurface是哪個surface??, 從Session中的relayout定義來看

    public int relayout(IWindow window, int seq, WindowManager.LayoutParams attrs,
            int requestedWidth, int requestedHeight, int viewFlags,
            int flags, Rect outFrame, Rect outOverscanInsets, Rect outContentInsets,
            Rect outVisibleInsets, Rect outStableInsets, Rect outsets, Rect outBackdropFrame,
            Configuration outConfig, Surface outSurface) {

這個outSurface會是App端傳過來的Surface麼?之前我一直以爲該Surface是App的Surface, 然而並不是

App調用relayout,實際上是IWindowSession的Proxy類中的relayout,代碼如下

public int relayout(android.view.IWindow window, int seq, android.view.WindowManager.LayoutParams attrs,  ... , 
        android.view.Surface outSurface) throws android.os.RemoteException {
    android.os.Parcel _data = android.os.Parcel.obtain();
    android.os.Parcel _reply = android.os.Parcel.obtain();
    int _result;
    try {
        ...
        mRemote.transact(Stub.TRANSACTION_relayout, _data, _reply, 0);
        _reply.readException();
        _result = _reply.readInt();
        ...
        if ((0 != _reply.readInt())) {
            outSurface.readFromParcel(_reply);
        }
    } finally {
        _reply.recycle();
        _data.recycle();
    }
    return _result;
}

從代碼來看App端的outSurface並沒有傳到_data裏,也就是並沒有傳遞給Server端,相反,它是從_reply這個Parcel裏讀出來的。

現在來看下Server端的處理,在IWindowSession.Stub的onTransact裏

case TRANSACTION_relayout: {
    ...
    android.view.Surface _arg15;
    _arg15 = new android.view.Surface();
    int _result = this.relayout(...);
    reply.writeNoException();
    reply.writeInt(_result);
    ...
    if ((_arg15 != null)) {
        reply.writeInt(1);
        _arg15.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
    } else {
        reply.writeInt(0);
    }
    return true;
}

_arg15這個參數就是Surface, 原來是在Server端(SystemServer進程中)生成的Surface, 也就是圖1中那個臨時在System_server創建的Surface. 最後將該臨時生成的Surface寫入到reply的Parcel中。


下面的函數就是將native的surface引用到system_serve臨時產生的那個surface裏

--- in Surface.java
public void copyFrom(SurfaceControl other) {
    long surfaceControlPtr = other.mNativeObject; //獲得native surfacecontrol的地址
    long newNativeObject = nativeCreateFromSurfaceControl(surfaceControlPtr); //創建native surface
    synchronized (mLock) {
        setNativeObjectLocked(newNativeObject); //將native surface的地址保存到App端的Surface裏
    }
}

通過將Native Surface的地址保存到SystemServer進程Java側的臨時Surface裏

static jlong nativeCreateFromSurfaceControl(JNIEnv* env, jclass clazz,
        jlong surfaceControlNativeObj) {
    sp<SurfaceControl> ctrl(reinterpret_cast<SurfaceControl *>(surfaceControlNativeObj));
    sp<Surface> surface(ctrl->getSurface());   
    return reinterpret_cast<jlong>(surface.get());
}

sp<Surface> SurfaceControl::getSurface() const 
{
    if (mSurfaceData == 0) {
        mSurfaceData = new Surface(mGraphicBufferProducer, false); //創建Surface
    }   
    return mSurfaceData;
}

最後看下App端的Surface是怎麼引用到正確的值的呢?
由上面可知App端的Surface通過是outSurface.readFromParcel(_reply);引用的

----- in Surface.java
public void readFromParcel(Parcel source) {
    synchronized (mLock) {
        mName = source.readString();
        setNativeObjectLocked(nativeReadFromParcel(mNativeObject, source));
    }
}

static jlong nativeReadFromParcel(JNIEnv* env, jclass clazz,
        jlong nativeObject, jobject parcelObj) {
    Parcel* parcel = parcelForJavaObject(env, parcelObj);

    android::view::Surface surfaceShim;

    // Calling code in Surface.java has already read the name of the Surface
    // from the Parcel
    surfaceShim.readFromParcel(parcel, /*nameAlreadyRead*/true);
    sp<Surface> self(reinterpret_cast<Surface *>(nativeObject));
    ...
    sp<Surface> sur;
    if (surfaceShim.graphicBufferProducer != nullptr) {
         //生成正確的Surface
        sur = new Surface(surfaceShim.graphicBufferProducer, true);
        sur->incStrong(&sRefBaseOwner);
    }
        
    return jlong(sur.get());
}

//獲得 GraphicBufferProducer binder對象
status_t Surface::readFromParcel(const Parcel* parcel, bool nameAlreadyRead) { 
    sp<IBinder> binder;
    status_t res = parcel->readStrongBinder(&binder);
    graphicBufferProducer = interface_cast<IGraphicBufferProducer>(binder);
    return OK;
}

具體的類圖參見 P8, P9

3.3 設置position與Layer

事實上這步發生在3.2.3之前

mSurfaceController.setPositionAndLayer(mTmpSize.left, mTmpSize.top, layerStack, mAnimLayer);
void setPositionAndLayer(float left, float top, int layerStack, int layer) {
    SurfaceControl.openTransaction();  
    try {
        mSurfaceX = left;
        mSurfaceY = top;
        try {
            mSurfaceControl.setPosition(left, top);
            mSurfaceControl.setLayerStack(layerStack);
            mSurfaceControl.setLayer(layer);
            mSurfaceControl.setAlpha(0);
            mSurfaceShown = false;
        } catch (RuntimeException e) {
        }
    } finally {
        SurfaceControl.closeTransaction();
    }
}

openTransaction與closeTransaction是成對出現的,本質上是爲了一次性提交多個屬性,而非一次一個一個的提交,這樣performance會相對高些,另外frame也會相對穩定些(這個待續).

setPosition/setLayer這些函數調用流程如下

SurfaceControl(java) -> SurfaceControl(jni) -> SurfaceComposerClient -> Composer
以setPosition爲例

bool Layer::setPosition(float x, float y, bool immediate) {
    if (mCurrentState.requested.transform.tx() == x && mCurrentState.requested.transform.ty() == y)
        return false;
    mCurrentState.sequence++;
    mCurrentState.requested.transform.set(x, y);
    if (immediate && !mFreezePositionUpdates) {
        mCurrentState.active.transform.set(x, y);
    }    
    mFreezePositionUpdates = mFreezePositionUpdates || !immediate;

    mCurrentState.modified = true;
    setTransactionFlags(eTransactionNeeded);
    return true;
}
}

getLayerStateLocked首先拿到ComposerState, 如果沒有,則新創建一個,最後放到 mComposerStates track起來,最後把相關的屬性存放到 CompserState中。最後通過SurfaceControl.closeTransaction();一併將ComposerState提交到SurfaceFlinger中對應的Layer類中的mCurrentState中, 並通過 Layer->setPosition將Surface的position設置到Layer中

注意: setPositionAndLayer通過setLayer將 Window的Z -order傳遞下去,這裏是WindowStateAnimator的mAnimLayer,

四、SurfaceFlinger中的Surface

4.1 創建APP對應的Client

sp<ISurfaceComposerClient> SurfaceFlinger::createConnection()
{
    sp<ISurfaceComposerClient> bclient;
    sp<Client> client(new Client(this)); 
    ...
    return bclient;
}

Client繼承BnSurfaceComposerClient, 與WMS中的BpSurfaceComposerClient相對應。

4.2 創建Surface

WMS通過SurfaceFlinger的Client來創建相應的Surface

Client通過MessageCreateLayer將創建Surface的請求放到隊列中, 遵循先入先出的原則。 當Message被執行時,會調用SurfacefFlinger的createLayer()函數,咦,這裏的 surface就變成了Layer??

status_t SurfaceFlinger::createLayer(...) {
    createNormalLayer(...); //其實有兩種選擇一個是Normal Layer, 另一種是Dim Layer
    addClientLayer(...)
}

創建Layer分兩步,一步是創建Layer, 另一步是將Layer track起來

4.2.1 創建 Layer

status_t SurfaceFlinger::createNormalLayer(...)
{
    ...
    *outLayer = new Layer(this, client, name, w, h, flags);
    if (err == NO_ERROR) { 
        *handle = (*outLayer)->getHandle(); 
        *gbp = (*outLayer)->getProducer();
    }
    return err;
}

實例化Layer, 而由於Layer繼承於RefBase, 在實例化後會調用一次 onFirstRef

void Layer::onFirstRef() {
    sp<IGraphicBufferProducer> producer;
    sp<IGraphicBufferConsumer> consumer;
    BufferQueue::createBufferQueue(&producer, &consumer);
    mProducer = new MonitoredProducer(producer, mFlinger);
    mSurfaceFlingerConsumer = new SurfaceFlingerConsumer(consumer, mTextureName);
}

在 onFirstRef裏會爲 Layer創建 BufferQueue模型 也就是典型的生產者/消費者模式,這個在後續講。
具體可以參考 P11, P12, P13, P14

4.2.2 SurfaceFlinger Tracks Layer

status_t SurfaceFlinger::addClientLayer(...)
{
        if (mCurrentState.layersSortedByZ.size() >= MAX_LAYERS) {
            return NO_MEMORY;
        }
        mCurrentState.layersSortedByZ.add(lbc);
        mGraphicBufferProducerList.add(IInterface::asBinder(gbc));
    client->attachLayer(handle, lbc);
    return NO_ERROR;
}

具體可以參考P15, P16所示

五、小結

至此,整個Surface的UML圖已經建立起來了。
但是僅僅是很生硬的把UML圖畫出來,是吧? 下面來小結一下,

5.1 APP/WMS/SurfaceFlinger通信流程創建

App啓動Main Activity,

  1. 首先創建好與WMS通信的媒介Session,
  2. 然後通過Session將Window加入到WMS中,這時會觸發 SurfaceSession的創建
  3. SurfaceSession的創建又會在WMS Native創建SurfaceComposerClient,
  4. 最終在SurfaceFlinger裏創建與SurfaceComposerClient對應的Client
    至此 整個通信通道(APP(Session) -> WMS, WMS(SurfaceComposerClient) -> SurfaceFlinger(Client))已經建立起來了。

5.2 對Window進行佈局(relayout)

Choreographer會接收 SurfaceFlinger 的Vsync信號, 參考Android SurfaceFlinger SW Vsync模型
然後執行 doFrame -> performTraverals()
接着通過 Session去請求WMS 對Window佈局 (relayout)

relayout 主要是

  1. 創建 Jave/Native端的 SurfaceControl
  2. 通過 SurfaceComposerClient 通知 Client(SurfaceFlinger中)去創建 Layer, 並由SurfaceFlinger管理起來
  3. SurfaceControl創建好後就開始創建真正的 native的Surface
  4. App Surface通過relayout返回的parcel創建出App端的Surface

整體代碼流程如下圖所示

Surface flowchart



作者:wbo4958
鏈接:https://www.jianshu.com/p/64e5c866b4ae
來源:簡書
著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章