之前在分析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++;
- }
- 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)
- {
- }
- 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;
- }