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

前言

一个窗口里面的所有的普通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
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343