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

相关推荐
前行的小黑炭16 小时前
Android :Comnpose各种副作用的使用
android·kotlin·app
BD_Marathon1 天前
【MySQL】函数
android·数据库·mysql
西西学代码1 天前
安卓开发---耳机的按键设置的UI实例
android·ui
崎岖Qiu1 天前
【OS笔记04】:进程和线程2-进程控制
笔记·操作系统·os
maki0771 天前
虚幻版Pico大空间VR入门教程 05 —— 原点坐标和项目优化技巧整理
android·游戏引擎·vr·虚幻·pico·htc vive·大空间
千里马学框架1 天前
音频焦点学习之AudioFocusRequest.Builder类剖析
android·面试·智能手机·车载系统·音视频·安卓framework开发·audio
fundroid2 天前
掌握 Compose 性能优化三步法
android·android jetpack
TeleostNaCl2 天前
如何在 IDEA 中使用 Proguard 自动混淆 Gradle 编译的Java 项目
android·java·经验分享·kotlin·gradle·intellij-idea
旷野说2 天前
Android Studio Narwhal 3 特性
android·ide·android studio
maki0772 天前
VR大空间资料 01 —— 常用VR框架对比
android·ue5·游戏引擎·vr·虚幻·pico