Android 16 | Display Framework - 2 | Surface

写在前面

Surface 是整个 Android 显示框架中最重要也是最基础的一个概念,它承担着 App UI 的显示需求,App 需要展示的 UI 都必须要画到这个 Surface 上才能被显示出来。通过学习本章内容,你会了解:

  1. 什么是 Surface
  2. App 是如何获取 Surface
  3. Surface / SurfaceControl/ Layer 这些基本概念的区别与联系

什么是 Surface

我们知道 App 的 UI 最终都是通过 SurfaceFlinger 合成之后,然后提交给 Display 进行显示。而 Surface 就是 AppSurfaceFlinger 之间的桥梁。 我们从源码的角度来分析 Surface

arduino 复制代码
// frameworks/native/libs/gui/include/gui/Surface.h
class Surface
    : public ANativeObjectBase<ANativeWindow, Surface, RefBase>
{
sp<IGraphicBufferProducer> getIGraphicBufferProducer() const;

...
virtual int dequeueBuffer(ANativeWindowBuffer** buffer, int* fenceFd);
virtual int queueBuffer(ANativeWindowBuffer* buffer, int fenceFd);
...
}

getIGraphicBufferProducer :从名字可以看出,这个变量是 GraphicBuffer生产者GraphicBuffer 是什么呢? GraphicBuffer 代表着一块可以被 CPU/GPU 访问的图像缓冲区。App 可以通过第三方渲染引擎,如 OpenGL/SKia 等, 把 UI 渲染到这个一块缓冲区。GraphicBuffer 后面会单独拿一下小节讲解。

dequeueBuffer : 通过 dequeueBuffer 可以从 Buffer Queue 中获取一块 GraphicBuffer,用于 App 进行渲染。

queueBuffer :通过 queueBuffer 可以把渲染好的 GraphicBuffer 提交到 Buffer Queue 中,然后再提交给 SurfaceFlinger 进行合成,最终提交到 Display 进行显示。

那么 Buffer Queue 是由谁管理的呢? 为什么 Surface 的 dequeueBuffer/queueBuffer 就能从 Buffer Queue 中获取 Buffer 呢?实际上 Buffer Queue 管理以及 dequeueBuffer/queueBuffer 的实现都是由 BLASTBufferQueue 实现的,这个后面会单独拿一个小节来说。

那么 Surface 是什么时候被创建的呢?Surface 是运行在哪个进程?

Surface/SurfaceControl/Layer 创建

Surface 的创建是在 Activity 的 ViewRootImpl 进行 performTraversal (至于什么时候进行 performTraversal,后面会具体分析,先说结论:当 Vsync 来的时候,Activity 的 ViewRootImpl 会进行 performTraversal) 时候。

csharp 复制代码
// frameworks/base/core/java/android/view/ViewRootImpl.java
private void performTraversals() {
   ...
   relayoutResult = relayoutWindow(params, viewVisibility, insetsPending);
   ...
}
csharp 复制代码
private int relayoutWindow(WindowManager.LayoutParams params, int viewVisibility,boolean insetsPending){
    ...
    relayoutResult = mWindowSession.relayout(mWindow, params,
                    requestedWidth, requestedHeight, viewVisibility,
                    insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0,
                    mRelayoutSeq, mLastSyncSeqId, mRelayoutResult);
    ...
 }

其中 mRelayoutResult 包含了一个重要的参数 mSurfaceControl,这里留意一下,后面会具体说到这个 mSurfaceControl

mWindowSession 是一个 AIDL 接口, 所以 mWindowSession.relayout 是一个跨进程的方法,它的实现在另外一个进程中(WMS 所在的进程)

java 复制代码
// frameworks/base/services/core/java/com/android/server/wm/Session.java
public int relayout(IWindow window, WindowManager.LayoutParams attrs,
            int requestedWidth, int requestedHeight, int viewFlags, int flags, int seq,
            int lastSyncSeqId, WindowRelayoutResult outRelayoutResult) {
        int res = mService.relayoutWindow(this, window, attrs, requestedWidth,
                requestedHeight, viewFlags, flags, seq, lastSyncSeqId, outRelayoutResult);
        return res;
    }

这里的 mService 指的就是 WindowServiceManager, 所以 App 进程中通过 mWindowSession.relayout 最终通过跨进程调用到了 WindowManagerServicerelayoutWindow

java 复制代码
    // frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
    public int relayoutWindow(Session session, IWindow client, LayoutParams attrs,
            int requestedWidth, int requestedHeight, int viewVisibility, int flags, int seq,
            int lastSyncSeqId, WindowRelayoutResult outRelayoutResult) {
        final ClientWindowFrames outFrames;
        final MergedConfiguration outMergedConfiguration;
        final SurfaceControl outSurfaceControl;
        final InsetsState outInsetsState;
        final InsetsSourceControl.Array outActiveControls;
        if (outRelayoutResult != null) {
            ...
            把 SurfaceControl 从 WindowRelayoutResult 拿出来
            outSurfaceControl = outRelayoutResult.surfaceControl;
            ...
        } 
        // 创建一个 SurfaceControl
        result = createSurfaceControl(outSurfaceControl, result, win, winAnimator);
        ...
    } 

SurfaceControl 创建

csharp 复制代码
// frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java    
private int createSurfaceControl(SurfaceControl outSurfaceControl, int result,
            WindowState win, WindowStateAnimator winAnimator) {
        SurfaceControl surfaceControl;
        try {
            surfaceControl = winAnimator.createSurfaceLocked();
        } finally {
            Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
        }
        if (surfaceControl != null) {
            winAnimator.getSurfaceControl(outSurfaceControl);
            ProtoLog.i(WM_SHOW_TRANSACTIONS, "OUT SURFACE %s: copied", outSurfaceControl);

        } 
        ...
    }

createSurfaceControl

  1. WindowStateAnimator.createSurfaceLocked 创建一个 surfaceControl (这里其实可以猜到 SurfaceSurfaceControl 的关系很暧昧了,明明是创建一个 SurfaceControl, 但是方法名却是 createSurfaceLocked)
  2. 把创建的 SurfaceControl 通过 getSurfaceControl copy 给 outSurfaceControl, 这个 outSurfaceControl 也就是在 RootViewImpl 创建并作为参数传过来的 WMS 的SurfaceControl。所以把创建好的 SurfaceControl copy 给 outSurfaceControl, 也就是把这个的 SurfaceControl 返回给了 RootViewImpl 所持有

接下来继续分析 WindowStateAnimator.createSurfaceLocked

scss 复制代码
// frameworks/base/services/core/java/com/android/server/wm/WindowStateAnimator.java
SurfaceControl createSurfaceLocked() {
            ...
            mSurfaceControl = mWin.makeSurface()
                    .setParent(mWin.mSurfaceControl)
                    .setName(mTitle)
                    .setFormat(format)
                    .setFlags(flags)
                    .setMetadata(METADATA_WINDOW_TYPE, attrs.type)
                    .setMetadata(METADATA_OWNER_UID, mSession.mUid)
                    .setMetadata(METADATA_OWNER_PID, mSession.mPid)
                    .setCallsite("WindowSurfaceController")
                    .setBLASTLayer().build();
            ...

}

这里会对 SurfaceControl 做一些参数设置, 然后会调用 SurfaceControl.Builderbuild 来构建 SurfaceControl

csharp 复制代码
// frameworks/base/core/java/android/view/SurfaceControl.java
        public SurfaceControl build() {
            ...
            return new SurfaceControl(
                 mSession, mName, mWidth, mHeight, mFormat, mFlags, mParent, mMetadata, mLocalOwnerView, mCallsite);
        }

这里会调用 SurfaceControl 的带参构造函数

csharp 复制代码
// frameworks/base/core/java/android/view/SurfaceControl.java
    private SurfaceControl(SurfaceSession session, String name, int w, int h, int format, int flags,
            ...
            nativeObject = nativeCreate(session, name, w, h, format, flags,
                    parent != null ? parent.mNativeObject : 0, metaParcel);
            ...
    }

nativeCreate 是一个 JNI 方法,继续来看在 native 的实现

kotlin 复制代码
// frameworks/base/core/jni/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,
        jobject metadataParcel) {
    ScopedUtfChars name(env, nameStr);
    sp<SurfaceComposerClient> client;
    sp<SurfaceControl> surface;
    ...
    status_t err = client->createSurfaceChecked(String8(name.c_str()), w, h, format, &surface,
                                               flags, parentHandle, std::move(metadata));

    surface->incStrong((void *)nativeCreate);
    return reinterpret_cast<jlong>(surface.get());
}

SurfaceComposerClient->createSurfaceChecked

c 复制代码
status_t SurfaceComposerClient::createSurfaceChecked(const String8& name, uint32_t w, uint32_t h,
                                                     PixelFormat format,
                                                     sp<SurfaceControl>* outSurface, int32_t flags,
                                                     const sp<IBinder>& parentHandle,
                                                     LayerMetadata metadata,
                                                     uint32_t* outTransformHint) {

        ...
        gui::CreateSurfaceResult result;
        // 跨进程调用 createSurface
        binder::Status status = mClient->createSurface(std::string(name.c_str()), flags,
                                                       parentHandle, std::move(metadata), &result);

       ...
       // 最终创建了 C++ 层的 SurfaceControl
       *outSurface = sp<SurfaceControl>::make(this, result.handle, result.layerId,
                                                   toString(result.layerName), w, h, format,
                                                   result.transformHint, flags);
       
    }
    return err;
}
  1. mClientISurfaceComposerClient 接口的 Binder 客户端代理对象,所以 mClient->createSurface 是一个 Binder call,它的服务端实现在 SurfaceFlinger 所运行的进程。 所以 Create SurfaceWMS 所在进程跑到了 SurfaceFlinger 所在的进程。
  2. SurfaceControl 的构造函数可以看出,SurfaceControl的主要成员变量由 CreateSurfaceResult 提供,比如 CreateSurfaceResult.handleCreateSurfaceResult.layerId 等,通过 mClient->createSurface 创建完成之后,最终创建了 C++ 层的 SurfaceControl,并返回给 Java 层。所以这里重点关注 mClient->createSurface 的实现。

Layer 创建

rust 复制代码
binder::Status Client::createSurface(const std::string& name, int32_t flags,
                                     const sp<IBinder>& parent, const gui::LayerMetadata& metadata,
                                     gui::CreateSurfaceResult* outResult) {
    ...
    const status_t status = mFlinger->createLayer(args, *outResult);
    return binderStatusFromStatusT(status);
}

这里的 mFlinger 指的就是 SurfaceFlinger

ini 复制代码
status_t SurfaceFlinger::createLayer(LayerCreationArgs& args, gui::CreateSurfaceResult& outResult) {
    status_t result = NO_ERROR;
    // 声明一个 Layer
    sp<Layer> layer;

    switch (args.flags & ISurfaceComposerClient::eFXSurfaceMask) {
            ...
            // 创建一块 Layer
            result = createBufferStateLayer(args, &outResult.handle, &layer);
        } break;
    }
    ...
    outResult.transformHint = static_cast<int32_t>(outTransformHint);
    outResult.layerId = layer->sequence;
    outResult.layerName = String16(layer->getDebugName());
    return result;
}

这里我们重点看一下 createBufferStateLayer 的实现

scss 复制代码
status_t SurfaceFlinger::createBufferStateLayer(LayerCreationArgs& args, sp<IBinder>* handle,
                                                sp<Layer>* outLayer) {
    // getFactory() 返回的是 DefaultFactory
    *outLayer = getFactory().createBufferStateLayer(args);
    // 把 Layer Handle 交给 outResult.handle,也就是 CreateSurfaceResult.handle
    // CreateSurfaceResult.handle 最终会作为 SurfaceControl 构造函数的参数传递给 SurfaceControl
    *handle = (*outLayer)->getHandle();
}

sp<Layer> DefaultFactory::createBufferStateLayer(const LayerCreationArgs& args) {
    return sp<Layer>::make(args);
}

这里总结一下:

  1. Client::createSurface 最终会在 SurfaceFlinger 这边创建一块 Layer 对象
  2. LayerHandle 赋给 CreateSurfaceResult.handle,最终传给 SurfaceControl LayerHandle 是什么呢?LayerHandle 本质上是一个 BBinder,提供了 getLayer 等实现
arduino 复制代码
class LayerHandle : public BBinder {
public:
    LayerHandle(const sp<android::SurfaceFlinger>& flinger, const sp<android::Layer>& layer);
    static sp<LayerHandle> fromIBinder(const sp<IBinder>& handle);
    static sp<android::Layer> getLayer(const sp<IBinder>& handle);
    static uint32_t getLayerId(const sp<IBinder>& handle);
    ...
private:
    sp<android::SurfaceFlinger> mFlinger;
    sp<android::Layer> mLayer;
    const uint32_t mLayerId;
};

所以到这里,关于 SurfaceControlLayer 的联系就很清晰了

SurfaceControlLayer 是一一对应的关系,并且 SurfaceControl 间接持有 Layer,这意味着 SurfaceControl 能够控制 Layer

到目前为止,SurfaceControlLayer 的创建就已经完成了,但是今天的主角 Surface 并没有实际创建出来(我这里说的 Surface 指的是 C++ 层的 Surface,而不是 Java 层的 Surface), Surface 的真正创建发生在updateBlastSurfaceIfNeeded

Surface 创建

arduino 复制代码
// frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
    public int relayoutWindow(Session session, IWindow client, LayoutParams attrs,
            int requestedWidth, int requestedHeight, int viewVisibility, int flags, int seq,
            int lastSyncSeqId, WindowRelayoutResult outRelayoutResult) {

        // 创建 SurfaceControl
        result = createSurfaceControl(outSurfaceControl, result, win, winAnimator);
        ...
        updateBlastSurfaceIfNeeded();
        ...
    }
ini 复制代码
    void updateBlastSurfaceIfNeeded() {
        ...
        blastSurface = mBlastBufferQueue.createSurface();
        ...
        mSurface.transferFrom(blastSurface);
    }

mBlastBufferQueue 是 BLASTBufferQueue,关于 BLASTBufferQueue 可以参考鄙人另外一篇文章,这里只做简单的介绍:

BLASTBufferQueue 由 "Producer" + "Comsumer" + BufferQueueCore,

  • Producer 申请 GraphicBuffer,绘制 UI 到 GraphicBuffer;
  • Comsumer 可以消费 GraphicBuffer,并且把 GraphicBuffer 提交到 SurfaceFlinger
  • BufferQueueCore 队列负责管理 GraphicBuffer 在 Producer 和 Comsumer 之间的移动。

通过 BLASTBufferQueuecreateSurface 来创建一个 blastSurface,然后把这个 blastSurface 赋给 ViewRootImplmSurface。接下来我们分析 BLASTBufferQueue.createSurface 的实现

kotlin 复制代码
    // frameworks/base/graphics/java/android/graphics/BLASTBufferQueue.java
    public Surface createSurface() {
        // nativeGetSurface 是一个 native 方法
        return nativeGetSurface(mNativeObject, false /* includeSurfaceControlHandle */);
    }
    
    // frameworks/base/core/jni/android_graphics_BLASTBufferQueue.cpp
    static jobject nativeGetSurface(JNIEnv* env, jclass clazz, jlong ptr,
                                jboolean includeSurfaceControlHandle) {
    sp<BLASTBufferQueue> queue = reinterpret_cast<BLASTBufferQueue*>(ptr);
    return android_view_Surface_createFromSurface(env,
                                                  queue->getSurface(includeSurfaceControlHandle));
}

这里最终会调用 BLASTBufferQueue.cppgetSurface 方法

arduino 复制代码
sp<Surface> BLASTBufferQueue::getSurface(bool includeSurfaceControlHandle) {
    std::lock_guard _lock{mMutex};
    sp<IBinder> scHandle = nullptr;
    if (includeSurfaceControlHandle && mSurfaceControl) {
        // scHandle 指的就是 LayerHandle
        scHandle = mSurfaceControl->getHandle();
    }
    return sp<BBQSurface>::make(mProducer, true, scHandle, this);
}
  1. 在这里真正创建了 BBQSurfaceBBQSurfaceSurface 的子类,并且把 BLASTBufferQueuemProducer 作为构造函数的参数传给了 BBQSurface/Surface,这就意味着 BBQSurface/Surface 能通过 mProducer 来申请 GraphicBuffer 来进行绘制,并把绘制好的 Buffer 插入 BLASTBufferQueue,由 Comsumer 进行消费
  2. 从代码里面也可以看出 Surface 和 SurfaceControl 以及 Layer 之间的关系: Surface 通过 SurfaceControl 间接持有 Layer

到这里 native 层的 Surface 终于创建完成了, 并返回给 ViewRootImpl

相关推荐
钟智强2 小时前
Flutter 前端开发中的常见问题全面解析
android·前端·flutter·ios·前端框架·dart
解牛之术2 小时前
Android展示加载PDF
android·pdf
peakmain92 小时前
AGP 8 下TheRouter和bcprov的神坑
android
whysqwhw3 小时前
OkHttp-TLS 模块概要分析
android
DoraBigHead3 小时前
你以为你保存的是“文件”?其实是 inode + block 的数据幻术!
操作系统
byte轻骑兵3 小时前
【Bluedroid】蓝牙协议栈enable流程深度解析
android·c++·bluedroid
阿昭L4 小时前
关于僵尸进程
linux·操作系统·僵尸进程
Industio_触觉智能4 小时前
量产技巧之RK3588 Android12默认移除导航栏&状态栏
android·rk3588·开发板·核心板·瑞芯微·rk3588j
小馬佩德罗4 小时前
Android系统的问题分析笔记 - Android上的调试方式 bugreport
android·调试