Android Surface創(chuàng)建

轉(zhuǎn)載請標注來處: http://www.itdecent.cn/p/64e5c866b4ae

一、 OverView

Android Surface的創(chuàng)建涉及三個進程

  1. App 進程
    Surface本質(zhì)上是一個Native Window, 并且保存著需要在屏幕上顯示的數(shù)據(jù)(buffer), 它通常包含 triple-buffers 以防止Jank。
    那么誰要創(chuàng)建Surface呢? 當(dāng)然是App了,App需要將自己的內(nèi)容顯示在屏幕上,所以App負責(zé)發(fā)起Surface創(chuàng)建請求,創(chuàng)建好Surface后, 就可以直接可以在canvas上畫圖等,最終都會保存到Surface里的buffer里,最后由SurfaceFlinger合成并顯示。

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

  3. SurfaceFlinger
    為App進程創(chuàng)建具體的Surface, 在SurfaceFlinger里對應(yīng)成Layer, 然后負責(zé)管理、合成顯示。

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

Surface overview

二、 與App進程相關(guān)的類

2.1 WMS中Session類的代理 IWindowSession

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

final IWindowSession mWindowSession;

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

而mWindowSession具體又是通過 WindowManagerGlobal的靜態(tài)函數(shù) getWindowSession()獲得

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

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

2.2 Surface類

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

final Surface mSurface = new Surface();

由于 ViewRootImpl的個數(shù)與addView的調(diào)用次數(shù)相關(guān),一個Activity可以多次調(diào)用addView, 也就是說一個Activity可以有多個Surface.

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

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

App進程通過 relayout 函數(shù)去創(chuàng)建真實Surface。

mWindowSession.relayout(..., mSurface);

三、System_Server進程中的Surface

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

3.1 Session和SurfaceSession

3.1.1 Session類

由第二節(jié)可知, Session是通過openSession創(chuàng)建的

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

3.1.2 SurfaceSession類

SurfaceSession的創(chuàng)建是在WindowState生成后創(chuàng)建的, 如

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之間的已經(jīng)連接好的會話層。WMS將所有的Session加入到 mSessions里。

Session和SurfaceSession可以參見圖中的P2

3.1.3 SurfaceSession的native層

接著上面看SurfaceSession的構(gòu)造函數(shù),

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

調(diào)用nativeCreate在JNI中進行創(chuàng)建,具體是創(chuàng)建什么呢? 從mNativeClient的定義注釋可以猜測應(yīng)該是創(chuàng)建一個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的相關(guān)UML可以參考圖中 P3所示。
另外SurfaceComposerClient繼承RefBase,所以在初始化后會調(diào)用一次onFirstRef

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

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

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

3.2 SurfaceControl

當(dāng)與APP相關(guān)的WMS(Session/SurfaceSession/BpSurfaceComposerClient),SurfaceFlinger(Client/BnSurfaceComposerClient 見第四節(jié))相關(guān)類已經(jīng)建立好后,此時就可以創(chuàng)建Surface了。

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

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

在relayoutWindow之前, mSurface僅是一個空殼,而在relayoutWindow之后, mSurface就已經(jīng)創(chuàng)建好了,且有效。

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

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

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

3.2.1 創(chuàng)建java側(cè)的SurfaceControl

調(diào)用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(...)
}

它們之間建立的關(guān)系圖參考P5所示,


3.2.2 創(chuàng)建Native的SurfaceControl

現(xiàn)在看下SurfaceControl的構(gòu)造函數(shù),

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

調(diào)用jni層的nativeCreate函數(shù)來創(chuàng)建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); //創(chuàng)建SurfaceControl
        }
    }
    return sur;
}

接著通過SurfaceComposerClient在SurfaceFlinger中創(chuàng)建Surface, 并且會返回SurfaceFlinger中的Handle以及IGraphicsBufferProducer的代理,如P7所示。

當(dāng)SurfaceFlinger中創(chuàng)建好Surface后,在WMS的JNI層創(chuàng)建一個SurfaceControl, SurfaceControl顧名思義就是控制、操作Surface的類.

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

3.2.3 創(chuàng)建Native層的Surface

在Java端的SurfaceControl創(chuàng)建好后,就開始創(chuàng)建真正的Native的Surface?;貞浺幌轮罢f的App端的Surface只是一個空殼,因為它還沒有與真正的Native端的Surface聯(lián)系起來。在這一小節(jié)將會把App端的Surface與真正的Surface聯(lián)系起來。

--- 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調(diào)用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里讀出來的。

現(xiàn)在來看下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這個參數(shù)就是Surface, 原來是在Server端(SystemServer進程中)生成的Surface, 也就是圖1中那個臨時在System_server創(chuàng)建的Surface. 最后將該臨時生成的Surface寫入到reply的Parcel中。


下面的函數(shù)就是將native的surface引用到system_serve臨時產(chǎn)生的那個surface里

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

通過將Native Surface的地址保存到SystemServer進程Java側(cè)的臨時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); //創(chuàng)建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 設(shè)置position與Layer

事實上這步發(fā)生在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是成對出現(xiàn)的,本質(zhì)上是為了一次性提交多個屬性,而非一次一個一個的提交,這樣performance會相對高些,另外frame也會相對穩(wěn)定些(這個待續(xù)).

setPosition/setLayer這些函數(shù)調(diào)用流程如下

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, 如果沒有,則新創(chuàng)建一個,最后放到 mComposerStates track起來,最后把相關(guān)的屬性存放到 CompserState中。最后通過SurfaceControl.closeTransaction();一并將ComposerState提交到SurfaceFlinger中對應(yīng)的Layer類中的mCurrentState中, 并通過 Layer->setPosition將Surface的position設(shè)置到Layer中

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

四、SurfaceFlinger中的Surface

4.1 創(chuàng)建APP對應(yīng)的Client

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

Client繼承BnSurfaceComposerClient, 與WMS中的BpSurfaceComposerClient相對應(yīng)。

4.2 創(chuàng)建Surface

WMS通過SurfaceFlinger的Client來創(chuàng)建相應(yīng)的Surface

Client通過MessageCreateLayer將創(chuàng)建Surface的請求放到隊列中, 遵循先入先出的原則。 當(dāng)Message被執(zhí)行時,會調(diào)用SurfacefFlinger的createLayer()函數(shù),咦,這里的 surface就變成了Layer??

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

創(chuàng)建Layer分兩步,一步是創(chuàng)建Layer, 另一步是將Layer track起來

4.2.1 創(chuàng)建 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, 在實例化后會調(diào)用一次 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創(chuàng)建 BufferQueue模型 也就是典型的生產(chǎn)者/消費者模式,這個在后續(xù)講。
具體可以參考 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所示

五、小結(jié)

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

5.1 APP/WMS/SurfaceFlinger通信流程創(chuàng)建

App啟動Main Activity,

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

5.2 對Window進行布局(relayout)

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

relayout 主要是

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

整體代碼流程如下圖所示

Surface flowchart
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容