天天看點

Android6.0 顯示系統(一) Surface建立

之前在分析Activity的時候,我們分析過Surface建立。這個系列的部落格是講述顯示系統,這裡再系統的分析下Surface建立過程。

之前我們分析在Activity在調用attach方法時,建立ViewRootImpl,以及建立其Surface過程,還有在WMS中建立Surface的過程。

這篇部落格我們通過另外一個方式分析,但是其實質是一樣的。

一、應用層建立Surface

應用開發中很少直接使用Surface,因為每個Activity中已經建立好了各自的Surface對象(就是之前部落格分析的在ViewRootImpl通過WMS建立的),通常隻有一些特殊應用才需要在Activity之外建立Surface,例如照相機、視訊播放應用。通常這些應用也是通過建立SurfaceView來使用Surface。在應用中不直接建立一個可用的Surface對象,或者說直接建立出來的Surface對象也沒用,因為這樣的Surface不能和SurfaceFlinger之間有關聯。

下面我們就來看下SurfaceView是如何建立Surface的,在SurfaceView有兩個Surface一個mSurface表示正在用的,另一個mNewSurface代表我們要切換的。

final Surface mSurface = new Surface();       // Current surface in use
    final Surface mNewSurface = new Surface();    // New surface we are switching to
           

至于Surface的構造函數沒什麼代碼,我們就不看了。

我們再來看SurfaceView的updateWindow函數,也是調用了WindowSession的relayout函數,和之前Activity建立Surface的流程一樣,這裡擷取到mNewSurface,再把mNewSurface的資料複制到mSurface中。

protected void updateWindow(boolean force, boolean redrawNeeded) {
        ......
        relayoutResult = mSession.relayout(mWindow, mWindow.mSeq, mLayout, mWidth, mHeight,
        visible ? VISIBLE : GONE,
        WindowManagerGlobal.RELAYOUT_DEFER_SURFACE_DESTROY,
        mWinFrame, mOverscanInsets, mContentInsets,
        mVisibleInsets, mStableInsets, mOutsets, mConfiguration,
        mNewSurface);
        ......
        mSurface.transferFrom(mNewSurface);
        ......
    }
           

mSession對象是IWindowSession,它是WMS中Session的代理對象。下面這是IWindowSession.aidl檔案中relayout函數的定義,我們可以看到outSurface的參數前面有一個out代表這是一個傳回參數,從WMS擷取這個對象的。而傳回資料都是通過Parcel來傳遞的。那下面我們來看看Surface的readFromParcel函數。

int relayout(IWindow window, int seq, in WindowManager.LayoutParams attrs,
            int requestedWidth, int requestedHeight, int viewVisibility,
            int flags, out Rect outFrame, out Rect outOverscanInsets,
            out Rect outContentInsets, out Rect outVisibleInsets, out Rect outStableInsets,
            out Rect outOutsets, out Configuration outConfig, out Surface outSurface);
           

我們來看下Surface的readFromParcel函數,前面是參數檢查,後面先是調用了nativeReadFromParcel函數來重新建立一個native層的Surface,然後調用setNativeObjectLocked來儲存這個native層的Surface到mNativeObject對象

public void readFromParcel(Parcel source) {
        if (source == null) {
            throw new IllegalArgumentException("source must not be null");
        }

        synchronized (mLock) {
            // nativeReadFromParcel() will either return mNativeObject, or
            // create a new native Surface and return it after reducing
            // the reference count on mNativeObject.  Either way, it is
            // not necessary to call nativeRelease() here.
            mName = source.readString();
            setNativeObjectLocked(nativeReadFromParcel(mNativeObject, source));
        }
    }
           

我們來看JNI層的nativeReadFromParcel函數,這個函數在android_view_Surface.cpp中,會将Parcel對象中讀取一個Binder對象,并且用它建立一個c層的Surface,并且傳回。這裡我們還不清楚這個Binder是什麼。

static jlong nativeReadFromParcel(JNIEnv* env, jclass clazz,
        jlong nativeObject, jobject parcelObj) {
    Parcel* parcel = parcelForJavaObject(env, parcelObj);//将資料解析成parcel
    if (parcel == NULL) {
        doThrowNPE(env);
        return 0;
    }

    sp<Surface> self(reinterpret_cast<Surface *>(nativeObject));
    sp<IBinder> binder(parcel->readStrongBinder());

    // update the Surface only if the underlying IGraphicBufferProducer
    // has changed.
    if (self != NULL //和原來的相同
            && (IInterface::asBinder(self->getIGraphicBufferProducer()) == binder)) {
        // same IGraphicBufferProducer, return ourselves
        return jlong(self.get());
    }

    sp<Surface> sur;
    sp<IGraphicBufferProducer> gbp(interface_cast<IGraphicBufferProducer>(binder));
    if (gbp != NULL) {
        // we have a new IGraphicBufferProducer, create a new Surface for it
        sur = new Surface(gbp, true);//建立一個Surface
        // and keep a reference before passing to java
        sur->incStrong(&sRefBaseOwner);
    }

    if (self != NULL) {
        // and loose the java reference to ourselves
        self->decStrong(&sRefBaseOwner);
    }

    return jlong(sur.get());
}
           

我們來看Surface,我們把binder對象儲存在mGraphicBufferProducer中了。

Surface::Surface(
        const sp<IGraphicBufferProducer>& bufferProducer,
        bool controlledByApp)
    : mGraphicBufferProducer(bufferProducer),
      mGenerationNumber(0)
           

二、WMS中Surface的建立過程

使用者程序中調用Session類的relayout接口來擷取WMS建立的Surface。而Session類的relayout接口實際上後面調用了WMS的relayout的relayoutWindow方法。

我們來看下WMS的relayoutWindow函數,顯示調用了winAnimator的createSurfaceLocked方法得到一個SurfaceControl對象,并使用它作為參數調整Surface類的copyFrom方法。

public int relayoutWindow(Session session, IWindow client, int seq,
            WindowManager.LayoutParams attrs, int requestedWidth,
            int requestedHeight, int viewVisibility, int flags,
            Rect outFrame, Rect outOverscanInsets, Rect outContentInsets,
            Rect outVisibleInsets, Rect outStableInsets, Rect outOutsets, Configuration outConfig,
            Surface outSurface) {
            ......
            SurfaceControl surfaceControl = winAnimator.createSurfaceLocked();
                    if (surfaceControl != null) {
                        outSurface.copyFrom(surfaceControl);
                    }
            ......
           

我們先來看Surface的copyFrom方法,這個方法其實很簡單隻是把SurfaceControl的native層的SurfaceControl的Surface複制到Surface的mNativeObject

public void copyFrom(SurfaceControl other) {
        if (other == null) {
            throw new IllegalArgumentException("other must not be null");
        }

        long surfaceControlPtr = other.mNativeObject;
        if (surfaceControlPtr == 0) {
            throw new NullPointerException(
                    "SurfaceControl native object is null. Are you using a released SurfaceControl?");
        }
        long newNativeObject = nativeCreateFromSurfaceControl(surfaceControlPtr);

        synchronized (mLock) {
            if (mNativeObject != 0) {
                nativeRelease(mNativeObject);
            }
            setNativeObjectLocked(newNativeObject);
        }
    }
           

nativeCreateFromSurfaceControl方法是把native層的SurfaceControl的surface傳出去。

static jlong nativeCreateFromSurfaceControl(JNIEnv* env, jclass clazz,
        jlong surfaceControlNativeObj) {
    /*
     * This is used by the WindowManagerService just after constructing
     * a Surface and is necessary for returning the Surface reference to
     * the caller. At this point, we should only have a SurfaceControl.
     */

    sp<SurfaceControl> ctrl(reinterpret_cast<SurfaceControl *>(surfaceControlNativeObj));
    sp<Surface> surface(ctrl->getSurface());//擷取Surface
    if (surface != NULL) {
        surface->incStrong(&sRefBaseOwner);
    }
    return reinterpret_cast<jlong>(surface.get());//這個get方法是強指針的方法,擷取其指針而已
}
           

再來看看SurfaceControl的getSurface方法。

sp<Surface> SurfaceControl::getSurface() const
{
    Mutex::Autolock _l(mLock);
    if (mSurfaceData == 0) {
        // This surface is always consumed by SurfaceFlinger, so the
        // producerControlledByApp value doesn't matter; using false.
        mSurfaceData = new Surface(mGraphicBufferProducer, false);
    }
    return mSurfaceData;
}
           

2.1 SurfaceControl的建立

下面我們再來看看SurfaceControl的建立,下面SurfaceTrace是SurfaceControl的一個子類。

SurfaceControl createSurfaceLocked() {
        ......
        mSurfaceControl = new SurfaceTrace(
        mSession.mSurfaceSession,
        attrs.getTitle().toString(),
        width, height, format, flags);
        ......
           

我們先看下SurfaceTrace的構造函數,先調用了父類的構造函數

public SurfaceTrace(SurfaceSession s,
                       String name, int w, int h, int format, int flags)
                   throws OutOfResourcesException {
            super(s, name, w, h, format, flags);
            mName = name != null ? name : "Not named";
            mSize.set(w, h);
            synchronized (sSurfaces) {
                sSurfaces.add(0, this);
            }
        }
           

我們再來看SurfaceControl的構造函數,就是調用了nativeCreate來建立一個mNativeObject對象。前面我們看過通過這個對象就可以擷取native層的Surface。

public SurfaceControl(SurfaceSession session,
            String name, int w, int h, int format, int flags)
                    throws OutOfResourcesException {
        if (session == null) {
            throw new IllegalArgumentException("session must not be null");
        }
        if (name == null) {
            throw new IllegalArgumentException("name must not be null");
        }

        if ((flags & SurfaceControl.HIDDEN) == 0) {
            Log.w(TAG, "Surfaces should always be created with the HIDDEN flag set "
                    + "to ensure that they are not made visible prematurely before "
                    + "all of the surface's properties have been configured.  "
                    + "Set the other properties and make the surface visible within "
                    + "a transaction.  New surface name: " + name,
                    new Throwable());
        }

        mName = name;
        mNativeObject = nativeCreate(session, name, w, h, format, flags);
        if (mNativeObject == 0) {
            throw new OutOfResourcesException(
                    "Couldn't allocate SurfaceControl native object");
        }

        mCloseGuard.open("release");
    }
           

我們來看SurfaceControl的nativeCreate的JNI對應的方法,先用SurfaceSession擷取SurfaceComposerClient,然後調用createSurface方法,擷取SurfaceControl。

static jlong nativeCreate(JNIEnv* env, jclass clazz, jobject sessionObj,
        jstring nameStr, jint w, jint h, jint format, jint flags) {
    ScopedUtfChars name(env, nameStr);
    sp<SurfaceComposerClient> client(android_view_SurfaceSession_getClient(env, sessionObj));
    sp<SurfaceControl> surface = client->createSurface(
            String8(name.c_str()), w, h, format, flags);
    if (surface == NULL) {
        jniThrowException(env, OutOfResourcesException, NULL);
        return 0;
    }
    surface->incStrong((void *)nativeCreate);
    return reinterpret_cast<jlong>(surface.get());
}
           

我們來看android_view_SurfaceSession_getClient就是擷取SurfaceSession的mNativeObject對象,也就是SurfaceComposerClient對象。

sp<SurfaceComposerClient> android_view_SurfaceSession_getClient(
        JNIEnv* env, jobject surfaceSessionObj) {
    return reinterpret_cast<SurfaceComposerClient*>(
            env->GetLongField(surfaceSessionObj, gSurfaceSessionClassInfo.mNativeClient));
}
           

2.2  SurfaceSession建立

那麼Session的成員變量mSurfaceSession又是什麼時候建立的?

之前在分析ViewRootImpl的setView時候,會調用Session的addToDisplay函數,在這個函數調用了PKMS的addWindow函數,而在addWindow方法,後面會建立一個WindowState對象,然後調用了其attach方法。

......
            WindowState win = new WindowState(this, session, client, token,
                    attachedWindow, appOp[0], seq, attrs, viewVisibility, displayContent);
            ......
            win.attach();
           

我們來看下這個WindowState的attach方法,調用了Session的windowAddedLocked方法。

void attach() {
        if (WindowManagerService.localLOGV) Slog.v(
            TAG, "Attaching " + this + " token=" + mToken
            + ", list=" + mToken.windows);
        mSession.windowAddedLocked();
    }
           

在Session的windowAddedLocked方法中建立了SurfaceSession對象。

void windowAddedLocked() {
        if (mSurfaceSession == null) {
            if (WindowManagerService.localLOGV) Slog.v(
                WindowManagerService.TAG, "First window added to " + this + ", creating SurfaceSession");
            mSurfaceSession = new SurfaceSession();
            if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(
                    WindowManagerService.TAG, "  NEW SURFACE SESSION " + mSurfaceSession);
            mService.mSessions.add(this);
            if (mLastReportedAnimatorScale != mService.getCurrentAnimatorScale()) {
                mService.dispatchNewAnimatorScaleLocked(this);
            }
        }
        mNumWindow++;
    }
           

在SurfaceSession構造函數中直接調用了nativeCreate JNI函數。

public SurfaceSession() {
        mNativeClient = nativeCreate();
    }
           

我們來看下這個JNI函數,建立了一個SurfaceComposerClient對象

static jlong nativeCreate(JNIEnv* env, jclass clazz) {
    SurfaceComposerClient* client = new SurfaceComposerClient();
    client->incStrong((void*)nativeCreate);
    return reinterpret_cast<jlong>(client);
}
           

2.3 SurfaceComposerClient連接配接SurfaceFlinger

SurfaceComposerClient對象的構造函數也沒有什麼,因為SurfaceComposerClient類也是RefBase類派生的,是以我們來看下onFirstRef函數。

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

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

onFirstRef函數先調用了ComposerService的getComposerService方法來擷取一個ISurfaceComposer的指針,然後調用它的createConnection來得到一個ISurfaceComposerClient的指針,并且儲存在mClient成員變量中。

最後我們知道在SurfaceControl中是調用SurfaceComposerClient的createSurface來得到Surface對象的。

我們再來看ComposerService::getComposerService函數,調用了connectLocked函數

/*static*/ sp<ISurfaceComposer> ComposerService::getComposerService() {
    ComposerService& instance = ComposerService::getInstance();
    Mutex::Autolock _l(instance.mLock);
    if (instance.mComposerService == NULL) {
        ComposerService::getInstance().connectLocked();
        assert(instance.mComposerService != NULL);
        ALOGD("ComposerService reconnected");
    }
    return instance.mComposerService;
}
           

connectLocked函數隻是擷取SurfaceFlinger的Binder對象,然後儲存在mComposerService。

void ComposerService::connectLocked() {
    const String16 name("SurfaceFlinger");
    while (getService(name, &mComposerService) != NO_ERROR) {
        usleep(250000);
    }
    ......
           

是以最後在SurfaceComposerClient的onFirstRef函數中,先是擷取SurfaceFlinger的Binder對象,然後調用函數createConnection函數,最終也是到SurfaceFlinger的createConnection函數。我們來看SurfaceFlinger的createConnection函數,建立一個client對象(這也是一個Binder服務),最後傳回這個對象。而傳回的對象儲存在SurfaceComposerClient類的mClient成員變量中。這樣每一個連接配接都會有一個新的Client對象。

sp<ISurfaceComposerClient> SurfaceFlinger::createConnection()
{
    sp<ISurfaceComposerClient> bclient;
    sp<Client> client(new Client(this));
    status_t err = client->initCheck();
    if (err == NO_ERROR) {
        bclient = client;
    }
    return bclient;
}
           

最後在SurfaceComposerClient中建立Surface,也是調用了mClient的createSurface,就到SurfaceFlinger的Client對象的createSurface函數了,擷取了handle和gbp對象就建立了SurfaceControl對象。

sp<SurfaceControl> SurfaceComposerClient::createSurface(
        const String8& name,
        uint32_t w,
        uint32_t h,
        PixelFormat format,
        uint32_t flags)
{
    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);
        ALOGE_IF(err, "SurfaceComposerClient::createSurface error %s", strerror(-err));
        if (err == NO_ERROR) {
            sur = new SurfaceControl(this, handle, gbp);
        }
    }
    return sur;
}
           

我們再來看SurfaceControl對象的構造函數就是初始化各種變量。

SurfaceControl::SurfaceControl(
        const sp<SurfaceComposerClient>& client,
        const sp<IBinder>& handle,
        const sp<IGraphicBufferProducer>& gbp)
    : mClient(client), mHandle(handle), mGraphicBufferProducer(gbp)
{
}
           

最後通過getSurface來建立一個Surface對象,Surface對象一個重要的參數是mGraphicBufferProducer,而這個對象的一個參數就是gbp

sp<Surface> SurfaceControl::getSurface() const
{
    Mutex::Autolock _l(mLock);
    if (mSurfaceData == 0) {
        // This surface is always consumed by SurfaceFlinger, so the
        // producerControlledByApp value doesn't matter; using false.
        mSurfaceData = new Surface(mGraphicBufferProducer, false);
    }
    return mSurfaceData;
}
           



繼續閱讀