美文网首页Android TV显示系统
SurfaceView源码分析(一):Surface的创建过程

SurfaceView源码分析(一):Surface的创建过程

作者: CDF_cc7d | 来源:发表于2020-08-29 18:57 被阅读0次

    前言

    一个窗口里面的所有的普通View都会共享一个Surface,这个Surface保存在ViewRootImpl里面。但是SurfaceView不同,SurfaceView自己独享一个Surface,也就意味着每次刷新SurfaceViewUI的时候,可以不必通知ViewRootImpl,这样会大大提高绘制效率。


    当然SurfaceView本身也是继承View的,都在一个View Hierarchy中,所以自然也会遵循View的绘制流程。不过SurfaceView自身调用了setWillNotDraw(true)方法,所以本身是不会调用onDraw的。接下来我们就开始往下探究SurfaceView的Surface到底是怎么创建的:

    public final class ViewRootImpl implements ViewParent,
            View.AttachInfo.Callbacks, ThreadedRenderer.DrawCallbacks {
        private void performTraversals() {
            // cache mView since it is used so much below...
           final View host = mView;
           ...代码省略...
           if (viewVisibilityChanged) {
                mAttachInfo.mWindowVisibility = viewVisibility;
                host.dispatchWindowVisibilityChanged(viewVisibility);
                if (viewUserVisibilityChanged) {
                    host.dispatchVisibilityAggregated(viewVisibility == View.VISIBLE);
                }
                if (viewVisibility != View.VISIBLE || mNewSurfaceNeeded) {
                    endDragResizing();
                    destroyHardwareResources();
                }
                if (viewVisibility == View.GONE) {
                    // After making a window gone, we will count it as being
                    // shown for the first time the next time it gets focus.
                    mHasHadWindowFocus = false;
                }
            }
           ...代码省略...
        }
    }
    

    ViewRootImpl#performTraversals这个方法应该都比较熟悉了,每次View请求重新测量或者绘制的时候都会执行这个方法,另外View刚被添加到ViewTree的时候也会执行一次。
    这里当当前窗口的可见性发生了变化,就会执行host.dispatchWindowVisibilityChanged方法,这里的host是ViewRootImpl 的mView成员变量,也就是一个窗口中最顶层的View——DecorView,DecorView继承了ViewGroup,自身并没有重写dispatchWindowVisibilityChanged方法,所以进入ViewGroup看下:

        @Override
        public void dispatchWindowVisibilityChanged(int visibility) {
            super.dispatchWindowVisibilityChanged(visibility);
            final int count = mChildrenCount;
            final View[] children = mChildren;
            for (int i = 0; i < count; i++) {
                children[i].dispatchWindowVisibilityChanged(visibility);
            }
        }
    

    这里面就是调用了所有子View的dispatchWindowVisibilityChanged:

        /**
         * Dispatch a window visibility change down the view hierarchy.
         * ViewGroups should override to route to their children.
         *
         * @param visibility The new visibility of the window.
         *
         * @see #onWindowVisibilityChanged(int)
         */
        public void dispatchWindowVisibilityChanged(@Visibility int visibility) {
            onWindowVisibilityChanged(visibility);
        }
    

    View中调用的onWindowVisibilityChanged方法,既然我们今天的主角是SurfaceView,那就去看SurfaceView是如何重写这个方法的:

        @Override
        protected void onWindowVisibilityChanged(int visibility) {
            super.onWindowVisibilityChanged(visibility);
            mWindowVisibility = visibility == VISIBLE;
            updateRequestedVisibility();
            updateSurface();
        }
    

    这里需要重点说下updateSurface这个核心方法:

        /** @hide */
        protected void updateSurface() {
            //判断SurfaceView的宿主窗口的大小是否已经计算好了,
            //SurfaceView必须在宿主窗口大小计算完毕之后才能更新
            if (!mHaveFrame) {
                return;
            }
            ViewRootImpl viewRoot = getViewRootImpl();
            
            ...代码省略...
            //检查surfaceview是否存在变化
            if (creating || formatChanged || sizeChanged || visibleChanged || windowVisibleChanged) {
                getLocationInWindow(mLocation);
    
                if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " "
                        + "Changes: creating=" + creating
                        + " format=" + formatChanged + " size=" + sizeChanged
                        + " visible=" + visibleChanged
                        + " left=" + (mWindowSpaceLeft != mLocation[0])
                        + " top=" + (mWindowSpaceTop != mLocation[1]));
    
                try {
                   ...代码省略...
    
                    if (creating) {
                        //创建SurfaceSession
                        mSurfaceSession = new SurfaceSession(viewRoot.mSurface);
                        mDeferredDestroySurfaceControl = mSurfaceControl;
    
                        updateOpaqueFlag();
                        通过SurfaceSession创建SurfaceControl
                        mSurfaceControl = new SurfaceControlWithBackground(mSurfaceSession,
                                "SurfaceView - " + viewRoot.getTitle().toString(),
                                mSurfaceWidth, mSurfaceHeight, mFormat,
                                mSurfaceFlags);
                    } else if (mSurfaceControl == null) {
                        return;
                    }
    
                    boolean realSizeChanged = false;
    
                    mSurfaceLock.lock();
                    try {
                        mDrawingStopped = !visible;
    
                        if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " "
                                + "Cur surface: " + mSurface);
    
                        SurfaceControl.openTransaction();
                        try {
                            //设置Layer属性
                            mSurfaceControl.setLayer(mSubLayer);
                           ...代码省略...
                        } finally {
                            SurfaceControl.closeTransaction();
                        }
    
                        if (sizeChanged || creating) {
                            redrawNeeded = true;
                        }
                         ...代码省略...
                    } finally {
                        mSurfaceLock.unlock();
                    }
    
                    try {
                         ...代码省略...
    
                        if (creating) {
                            //mSurface从mSurfaceControl中拷贝出GraphicBufferProducer
                            mSurface.copyFrom(mSurfaceControl);
                        }
    
                       ...代码省略...
                } catch (Exception ex) {
                    Log.e(TAG, "Exception configuring surface", ex);
                }
                ...代码省略...
            }
        }
    
    • 这里我们首先从创建SurfaceSession开始:
    public final class SurfaceSession {
        // Note: This field is accessed by native code.
        private long mNativeClient; // SurfaceComposerClient*
    
        private static native long nativeCreate();
        private static native long nativeCreateScoped(long surfacePtr);
        private static native void nativeDestroy(long ptr);
        private static native void nativeKill(long ptr);
    
        /** Create a new connection with the surface flinger. */
        public SurfaceSession() {
            mNativeClient = nativeCreate();
        }
    
        public SurfaceSession(Surface root) {
            mNativeClient = nativeCreateScoped(root.mNativeObject);
        }
    
        /* no user serviceable parts here ... */
        @Override
        protected void finalize() throws Throwable {
            try {
                if (mNativeClient != 0) {
                    nativeDestroy(mNativeClient);
                }
            } finally {
                super.finalize();
            }
        }
    
        /**
         * Forcibly detach native resources associated with this object.
         * Unlike destroy(), after this call any surfaces that were created
         * from the session will no longer work.
         */
        public void kill() {
            nativeKill(mNativeClient);
        }
    }
    

    SurfaceSession本身代码量非常少,在构造方法中调用了nativeCreateScoped(root.mNativeObject)方法,那么就进入对应的cpp文件看下具体实现:

    frameworks/base/core/jni/android_view_SurfaceSession.cpp

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

    这里创建了SurfaceComposerClient对象,调用了SurfaceComposerClient的父类方法IncStrong,内部会调用SurfaceComposerClient#onFirstRef方法

    /frameworks/native/libs/gui/SurfaceComposerClient.cpp

    void SurfaceComposerClient::onFirstRef() {
        //获取SurfacFlinger的代理BpSurfaceComposer
        sp<ISurfaceComposer> sf(ComposerService::getComposerService());
        if (sf != 0 && mStatus == NO_INIT) {
            auto rootProducer = mParent.promote();
            sp<ISurfaceComposerClient> conn;
            conn = (rootProducer != nullptr) ? sf->createScopedConnection(rootProducer) :
                    sf->createConnection();
            if (conn != 0) {
                mClient = conn;
                mStatus = NO_ERROR;
            }
        }
    }
    

    调用BpSurfaceComposer的createScopedConnection方法,然后通过Binder调用SurfaceFlinger的createScopedConnection

    sp<ISurfaceComposerClient> SurfaceFlinger::createScopedConnection(
            const sp<IGraphicBufferProducer>& gbp) {
        if (authenticateSurfaceTexture(gbp) == false) {
            return nullptr;
        }
        const auto& layer = (static_cast<MonitoredProducer*>(gbp.get()))->getLayer();
        if (layer == nullptr) {
            return nullptr;
        }
    
       return initClient(new Client(this, layer));
    }
    

    创建对应的BpSurfaceComposerClient,然后将Client返回给Java层的SurfaceSession,并赋值给mNativeClient.

    • 然后我们再来看下SurfaceControl的创建过程
     mSurfaceControl = new SurfaceControlWithBackground(mSurfaceSession,
               "SurfaceView - " + viewRoot.getTitle().toString(),
               mSurfaceWidth, mSurfaceHeight, mFormat,
               mSurfaceFlags);
    

    咱们重新回到updateSurface方法中,此处初始化了SurfaceControl,将SurfaceSession传进去,再来看下构造方法里面都做了什么操作

            public SurfaceControlWithBackground(SurfaceSession s,
                            String name, int w, int h, int format, int flags)
                           throws Exception {
                super(s, name, w, h, format, flags);
                mBackgroundControl = new SurfaceControl(s, "Background for - " + name, w, h,
                        PixelFormat.OPAQUE, flags | SurfaceControl.FX_SURFACE_DIM);
                mOpaque = (flags & SurfaceControl.OPAQUE) != 0;
            }
    
        public SurfaceControl(SurfaceSession session,
                String name, int w, int h, int format, int flags)
                        throws OutOfResourcesException {
            this(session, name, w, h, format, flags, null, INVALID_WINDOW_TYPE, Binder.getCallingUid());
        }
    
        public SurfaceControl(SurfaceSession session, String name, int w, int h, int format, int flags,
                SurfaceControl parent, int windowType, int ownerUid)
                        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,
                parent != null ? parent.mNativeObject : 0, windowType, ownerUid);
            if (mNativeObject == 0) {
                throw new OutOfResourcesException(
                        "Couldn't allocate SurfaceControl native object");
            }
    
            mCloseGuard.open("release");
        }
    

    SurfaceControlWithBackground的构造方法主要调用了父类的构造方法,然后父类SurfaceControl中调用了nativeCreate方法,那么再次进入C++层看下那提测Create的处理逻辑:

    frameworks\native\services\surfaceflinger\ android_view_SurfaceControl.cpp

    static jlong nativeCreate(JNIEnv* env, jclass clazz, jobject sessionObj,
            jstring nameStr, jint w, jint h, jint format, jint flags, jlong parentObject,
            jint windowType, jint ownerUid) {
        ScopedUtfChars name(env, nameStr);
        sp<SurfaceComposerClient> client(android_view_SurfaceSession_getClient(env, sessionObj));
        SurfaceControl *parent = reinterpret_cast<SurfaceControl*>(parentObject);
       //client为SurfaceComposerClient对象
        sp<SurfaceControl> surface;
        status_t err = client->createSurfaceChecked(
                String8(name.c_str()), w, h, format, &surface, flags, parent, windowType, ownerUid);
         ...代码省略...
        //增加SurfaceControl的引用计数
        surface->incStrong((void *)nativeCreate);
        //获取IGraphicBufferProducer对象
        return reinterpret_cast<jlong>(surface.get());
    }
    

    首先通过sessionObj获取SurfaceComposerClient的代理对象BpSurfaceComposerClient,然后通过SurfaceComposerClient创建Surface

    frameworks\native\libs\gui\SurfaceComposerClient.cpp

    status_t SurfaceComposerClient::createSurfaceChecked(
            const String8& name,
            uint32_t w,
            uint32_t h,
            PixelFormat format,
            sp<SurfaceControl>* outSurface,
            uint32_t flags,
            SurfaceControl* parent,
            int32_t windowType,
            int32_t ownerUid)
    {
        sp<SurfaceControl> sur;
        status_t err = mStatus;
    
        if (mStatus == NO_ERROR) {
            sp<IBinder> handle;
            sp<IBinder> parentHandle;
            sp<IGraphicBufferProducer> gbp;
    
            if (parent != nullptr) {
                parentHandle = parent->getHandle();
            }
            err = mClient->createSurface(name, w, h, format, flags, parentHandle,
                    windowType, ownerUid, &handle, &gbp);
            ALOGE_IF(err, "SurfaceComposerClient::createSurface error %s", strerror(-err));
            if (err == NO_ERROR) {
                *outSurface = new SurfaceControl(this, handle, gbp, true /* owned */);
            }
        }
        return err;
    }
    

    此处mClient是在刚才创建SurfaceSession的时候生成的,SurfaceFlinger为BnSurfaceComposerClient创建的一个代理对象即BpSurfaceComposerClient对象。然后调用对应的createSurface方法,如果没有出现错误,那么就直接创建出SurfaceControl。那么我们再看下createSurface的逻辑:

    frameworks\native\services\surfaceflinger\Client.cpp

    status_t Client::createSurface(
            const String8& name,
            uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
            const sp<IBinder>& parentHandle, int32_t windowType, int32_t ownerUid,
            sp<IBinder>* handle,
            sp<IGraphicBufferProducer>* gbp)
    {
       ...代码省略...
    
        sp<MessageBase> msg = new MessageCreateLayer(mFlinger.get(),
                name, this, w, h, format, flags, handle,
                windowType, ownerUid, gbp, &parent);
        mFlinger->postMessageSync(msg);
        return static_cast<MessageCreateLayer*>( msg.get() )->getResult();
    }
    

    这里通过跨进程的RPC通信,调用SurfaceFlinger进程的createLayer方法:

    frameworks\native\services\surfaceflinger\SurfaceFlinger.cpp

    status_t SurfaceFlinger::createLayer(
            const String8& name,
            const sp<Client>& client,
            uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
            int32_t windowType, int32_t ownerUid, sp<IBinder>* handle,
            sp<IGraphicBufferProducer>* gbp, sp<Layer>* parent)
    {
       ...代码省略...
       status_t result = NO_ERROR;
    
        sp<Layer> layer;
    
        String8 uniqueName = getUniqueLayerName(name);
    
        switch (flags & ISurfaceComposerClient::eFXSurfaceMask) {
            case ISurfaceComposerClient::eFXSurfaceNormal:
                result = createBufferLayer(client,
                        uniqueName, w, h, flags, format,
                        handle, gbp, &layer);
    
                break;
            case ISurfaceComposerClient::eFXSurfaceColor:
                result = createColorLayer(client,
                        uniqueName, w, h, flags,
                        handle, &layer);
                break;
            default:
                result = BAD_VALUE;
                break;
        }
    ...代码省略...
        //将client和Layer关联起来,把Layer添加到client的mLayers集合里面去
        result = addClientLayer(client, *handle, *gbp, layer, *parent);
        if (result != NO_ERROR) {
            return result;
        }
        mInterceptor->saveSurfaceCreation(layer);
    
        setTransactionFlags(eTransactionNeeded);
        return result;
    }
    

    此处调用createNormalLayer创建layer,然后将Layer与client关联起来。SurfaceFlinger里的Layer对应的就是Java层的Surface。
    所以初始化SurfaceControl的时候就是创建了一个SurfaceControl,并让SurfaceFlinger创建了一个对应的Layer。

    • 接下来就重新回到java层,再来看下初始化完SurfaceControl以后,就将SurfaceControl的GraphicBufferProducer copy给mSurface对象
                        if (creating) {
                            mSurface.copyFrom(mSurfaceControl);
                        }
    

    至此,Surface就创建完毕了,下一节再讲SurfaceView是如何"挖洞"的


    总结

    SurfaceView创建Surface主要的过程如下:

    1. 首先创建SurfaceSession,这个时候返回一个SurfaceComposeClient的指针给java层
    2. SurfaceComposeClient在创建的时候,会获取SurfaceFlinger的代理对象BpSurfaceComposer,通过该对象在SurfaceFlinger中创建BnSurfaceComposerClient对象。并且将该对象创建BpSurfaceComposerClient对象赋值给了SurfaceComposeClient的mClient
    3. 然后创建SurfaceControl,获取SurfaceComposeClient的代理对象BpSurfaceComposeClient,由改对象调用createSurface通过RPC通信调用到SurfaceFlinger的createSurface方法
    4. 创建Layer对象
    5. 将SurfaceControl拷贝给mSurface对象,copy过程中创建对应的Surface对象,然后将C++层的Surface赋值给Java层的Surface对象的mNativeObject

    相关文章

      网友评论

        本文标题:SurfaceView源码分析(一):Surface的创建过程

        本文链接:https://www.haomeiwen.com/subject/pjibjktx.html